From cbdc51590d3d3437406627bc445009dd2b5fed4e Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Sat, 2 May 2020 15:48:06 +0100 Subject: [PATCH 1/1] Import konqueror_20.04.0.orig.tar.xz [dgit import orig konqueror_20.04.0.orig.tar.xz] --- .arcconfig | 3 + AUTHORS | 16 + CMakeLists.txt | 97 + COPYING | 339 + COPYING.DOC | 451 + COPYING.LIB | 502 + ChangeLog | 436 + DESIGN | 106 + DESIGN_config | 43 + Messages.sh | 6 + autotests/CMakeLists.txt | 33 + autotests/historymanagertest.cpp | 144 + autotests/konqhtmltest.cpp | 254 + autotests/konqviewmgrtest.cpp | 945 ++ autotests/konqviewmgrtest.h | 62 + autotests/konqviewtest.cpp | 63 + autotests/undomanagertest.cpp | 92 + client/CMakeLists.txt | 38 + client/ChangeLog | 14 + client/Messages.sh | 2 + client/kfmclient.cpp | 291 + client/kfmclient.h | 52 + client/konqclientrequest.cpp | 157 + client/konqclientrequest.h | 75 + config-konqueror.h.cmake | 8 + doc/CMakeLists.txt | 5 + doc/kcontrol5/CMakeLists.txt | 9 + doc/kcontrol5/bookmarks/CMakeLists.txt | 2 + doc/kcontrol5/bookmarks/index.docbook | 101 + doc/kcontrol5/filemanager/CMakeLists.txt | 2 + doc/kcontrol5/filemanager/index.docbook | 61 + doc/kcontrol5/history/CMakeLists.txt | 2 + doc/kcontrol5/history/index.docbook | 62 + doc/kcontrol5/kcmcss/CMakeLists.txt | 2 + doc/kcontrol5/kcmcss/index.docbook | 367 + doc/kcontrol5/khtml-adblock/CMakeLists.txt | 2 + doc/kcontrol5/khtml-adblock/index.docbook | 86 + doc/kcontrol5/khtml-behavior/CMakeLists.txt | 2 + doc/kcontrol5/khtml-behavior/index.docbook | 100 + doc/kcontrol5/khtml-general/CMakeLists.txt | 2 + doc/kcontrol5/khtml-general/index.docbook | 125 + doc/kcontrol5/khtml-java-js/CMakeLists.txt | 2 + doc/kcontrol5/khtml-java-js/index.docbook | 144 + doc/kcontrol5/performance/CMakeLists.txt | 2 + doc/kcontrol5/performance/index.docbook | 46 + doc/konqueror/CMakeLists.txt | 4 + doc/konqueror/cmndline.png | Bin 0 -> 29810 bytes doc/konqueror/dirtree.png | Bin 0 -> 50550 bytes doc/konqueror/dragdrop.png | Bin 0 -> 17849 bytes doc/konqueror/folders.png | Bin 0 -> 24357 bytes doc/konqueror/format-font-size-less.png | Bin 0 -> 531 bytes doc/konqueror/format-font-size-more.png | Bin 0 -> 513 bytes doc/konqueror/go-jump.png | Bin 0 -> 317 bytes doc/konqueror/grouping-view.png | Bin 0 -> 58416 bytes doc/konqueror/index.docbook | 4336 ++++++++ doc/konqueror/konqorg.png | Bin 0 -> 89127 bytes doc/konqueror/look.png | Bin 0 -> 26246 bytes doc/konqueror/parts.png | Bin 0 -> 28266 bytes doc/konqueror/reset.png | Bin 0 -> 627 bytes doc/konqueror/thumbnails.png | Bin 0 -> 17520 bytes doc/konqueror/viewproperties-dialog.png | Bin 0 -> 23793 bytes kfmclient.desktop | 104 + kfmclient_dir.desktop | 103 + kfmclient_html.desktop | 102 + kfmclient_war.desktop | 102 + konqbrowser.desktop | 191 + konqueror-version.h.cmake | 7 + konqueror.categories | 2 + konqy_preload.desktop | 45 + libkonq/AUTHORS | 7 + libkonq/CMakeLists.txt | 55 + libkonq/COPYING | 346 + libkonq/COPYING.LIB | 510 + libkonq/DESIGN | 44 + libkonq/KF5KonqConfig.cmake.in | 11 + libkonq/Mainpage.dox | 28 + libkonq/Messages.sh | 2 + libkonq/SERVICEMENUS | 52 + libkonq/autotests/CMakeLists.txt | 16 + libkonq/autotests/konqpopupmenutest.cpp | 455 + libkonq/autotests/konqpopupmenutest.h | 75 + libkonq/src/CMakeLists.txt | 60 + libkonq/src/directory_bookmarkbar.desktop | 95 + libkonq/src/konq_events.cpp | 42 + libkonq/src/konq_events.h | 92 + libkonq/src/konq_historyentry.cpp | 125 + libkonq/src/konq_historyentry.h | 85 + libkonq/src/konq_historyloader.cpp | 149 + libkonq/src/konq_historyloader_p.h | 60 + libkonq/src/konq_historyprovider.cpp | 465 + libkonq/src/konq_historyprovider.h | 160 + libkonq/src/konq_popupmenu.cpp | 560 + libkonq/src/konq_popupmenu.h | 144 + org.kde.konqueror.appdata.xml | 427 + org.kde.konqueror.desktop | 226 + pics/128-apps-konqueror.png | Bin 0 -> 15670 bytes pics/16-apps-konqueror.png | Bin 0 -> 947 bytes pics/22-apps-konqueror.png | Bin 0 -> 1381 bytes pics/32-apps-konqueror.png | Bin 0 -> 2176 bytes pics/48-apps-konqueror.png | Bin 0 -> 4054 bytes pics/64-apps-konqueror.png | Bin 0 -> 6384 bytes pics/CMakeLists.txt | 3 + pics/hisc-app-konqueror.svgz | Bin 0 -> 11820 bytes pics/indicators/CMakeLists.txt | 3 + pics/indicators/indicator_connect.png | Bin 0 -> 297 bytes pics/indicators/indicator_empty.png | Bin 0 -> 428 bytes pics/indicators/indicator_noconnect.png | Bin 0 -> 166 bytes pics/indicators/indicator_viewactive.png | Bin 0 -> 643 bytes plugins/CMakeLists.txt | 28 + plugins/COPYING | 346 + plugins/COPYING.DOC | 397 + plugins/COPYING.LIB | 510 + plugins/README | 45 + plugins/akregator/CMakeLists.txt | 39 + plugins/akregator/Messages.sh | 3 + .../akregator/akregator_konqfeedicon.desktop | 135 + plugins/akregator/akregator_konqfeedicon.rc | 3 + .../akregator/akregator_konqplugin.desktop | 133 + plugins/akregator/akregatorplugin.categories | 1 + plugins/akregator/akregatorplugin.cpp | 121 + plugins/akregator/akregatorplugin.h | 52 + plugins/akregator/feed.png | Bin 0 -> 930 bytes plugins/akregator/feed.svg | 645 ++ plugins/akregator/feeddetector.cpp | 148 + plugins/akregator/feeddetector.h | 83 + plugins/akregator/konqfeedicon.cpp | 220 + plugins/akregator/konqfeedicon.h | 77 + plugins/akregator/pluginutil.cpp | 103 + plugins/akregator/pluginutil.h | 56 + plugins/autorefresh/CMakeLists.txt | 23 + plugins/autorefresh/Messages.sh | 3 + plugins/autorefresh/autorefresh.cpp | 127 + plugins/autorefresh/autorefresh.desktop | 135 + plugins/autorefresh/autorefresh.h | 69 + plugins/autorefresh/autorefresh.rc | 10 + plugins/babelfish/16-actions-babelfish.png | Bin 0 -> 780 bytes plugins/babelfish/22-actions-babelfish.png | Bin 0 -> 1279 bytes plugins/babelfish/CMakeLists.txt | 23 + plugins/babelfish/Messages.sh | 3 + plugins/babelfish/plugin_babelfish.cpp | 425 + plugins/babelfish/plugin_babelfish.h | 47 + plugins/babelfish/plugin_babelfish.rc | 11 + plugins/babelfish/plugin_translator.desktop | 128 + plugins/babelfish/translaterc | 6 + plugins/dirfilter/CMakeLists.txt | 14 + plugins/dirfilter/Messages.sh | 3 + plugins/dirfilter/dirfilterplugin.cpp | 550 + plugins/dirfilter/dirfilterplugin.desktop | 135 + plugins/dirfilter/dirfilterplugin.h | 145 + plugins/dirfilter/dirfilterplugin.rc | 11 + plugins/fsview/22-apps-fsview.png | Bin 0 -> 802 bytes plugins/fsview/32-apps-fsview.png | Bin 0 -> 862 bytes plugins/fsview/CMakeLists.txt | 45 + plugins/fsview/Messages.sh | 3 + plugins/fsview/README | 29 + plugins/fsview/fsview.cpp | 591 ++ plugins/fsview/fsview.desktop | 133 + plugins/fsview/fsview.h | 159 + plugins/fsview/fsview_part.cpp | 549 + plugins/fsview/fsview_part.desktop | 129 + plugins/fsview/fsview_part.h | 132 + plugins/fsview/fsview_part.rc | 37 + plugins/fsview/inode.cpp | 429 + plugins/fsview/inode.h | 108 + plugins/fsview/main.cpp | 56 + plugins/fsview/scan.cpp | 437 + plugins/fsview/scan.h | 294 + plugins/fsview/tests/CMakeLists.txt | 23 + plugins/fsview/tests/scantest.cpp | 57 + plugins/fsview/treemap.cpp | 3646 +++++++ plugins/fsview/treemap.h | 900 ++ plugins/imagerotation/CMakeLists.txt | 9 + plugins/imagerotation/exif.py | 1079 ++ plugins/imagerotation/imageconverter.desktop | 358 + plugins/imagerotation/jpegorient | 85 + plugins/imagerotation/jpegorient.desktop | 359 + plugins/imagerotation/orient.py | 104 + plugins/khtmlsettingsplugin/CMakeLists.txt | 24 + plugins/khtmlsettingsplugin/Messages.sh | 3 + .../khtmlsettingsplugin.desktop | 137 + .../khtmlsettingsplugin.rc | 11 + .../khtmlsettingsplugin/settingsplugin.cpp | 305 + plugins/khtmlsettingsplugin/settingsplugin.h | 55 + .../16-actions-imagegallery.png | Bin 0 -> 871 bytes .../22-actions-imagegallery.png | Bin 0 -> 1438 bytes plugins/kimgalleryplugin/CMakeLists.txt | 22 + plugins/kimgalleryplugin/Messages.sh | 3 + plugins/kimgalleryplugin/imgallerydialog.cpp | 482 + plugins/kimgalleryplugin/imgallerydialog.h | 110 + plugins/kimgalleryplugin/imgalleryplugin.cpp | 541 + plugins/kimgalleryplugin/imgalleryplugin.h | 79 + .../kimgalleryplugin/kimgalleryplugin.desktop | 134 + plugins/kimgalleryplugin/kimgalleryplugin.rc | 8 + plugins/searchbar/CMakeLists.txt | 28 + plugins/searchbar/Messages.sh | 3 + plugins/searchbar/OpenSearchManager.cpp | 169 + plugins/searchbar/OpenSearchManager.h | 86 + plugins/searchbar/SuggestionEngine.cpp | 53 + plugins/searchbar/SuggestionEngine.h | 61 + plugins/searchbar/WebShortcutWidget.cpp | 100 + plugins/searchbar/WebShortcutWidget.h | 51 + plugins/searchbar/icons/16-actions-google.png | Bin 0 -> 459 bytes plugins/searchbar/icons/22-actions-google.png | Bin 0 -> 634 bytes plugins/searchbar/icons/32-actions-google.png | Bin 0 -> 771 bytes plugins/searchbar/icons/48-actions-google.png | Bin 0 -> 1078 bytes plugins/searchbar/icons/64-actions-google.png | Bin 0 -> 1281 bytes plugins/searchbar/icons/CMakeLists.txt | 9 + .../searchbar/icons/sc-actions-google.svgz | Bin 0 -> 2043 bytes plugins/searchbar/opensearch/CMakeLists.txt | 2 + .../searchbar/opensearch/OpenSearchEngine.cpp | 226 + .../searchbar/opensearch/OpenSearchEngine.h | 91 + .../searchbar/opensearch/OpenSearchReader.cpp | 132 + .../searchbar/opensearch/OpenSearchReader.h | 39 + .../searchbar/opensearch/OpenSearchWriter.cpp | 111 + .../searchbar/opensearch/OpenSearchWriter.h | 41 + .../opensearch/engines/CMakeLists.txt | 2 + .../searchbar/opensearch/engines/google.xml | 9 + plugins/searchbar/searchbar.cpp | 746 ++ plugins/searchbar/searchbar.desktop | 137 + plugins/searchbar/searchbar.h | 241 + plugins/searchbar/searchbar.rc | 6 + plugins/shellcmdplugin/CMakeLists.txt | 17 + plugins/shellcmdplugin/Messages.sh | 3 + plugins/shellcmdplugin/kshellcmddialog.cpp | 102 + plugins/shellcmdplugin/kshellcmddialog.h | 46 + plugins/shellcmdplugin/kshellcmdexecutor.cpp | 150 + plugins/shellcmdplugin/kshellcmdexecutor.h | 52 + plugins/shellcmdplugin/kshellcmdplugin.cpp | 99 + .../shellcmdplugin/kshellcmdplugin.desktop | 187 + plugins/shellcmdplugin/kshellcmdplugin.h | 35 + plugins/shellcmdplugin/kshellcmdplugin.rc | 8 + plugins/ttsplugin/CMakeLists.txt | 17 + plugins/ttsplugin/Messages.sh | 3 + plugins/ttsplugin/khtmltts.cpp | 64 + plugins/ttsplugin/khtmltts.desktop | 185 + plugins/ttsplugin/khtmltts.h | 42 + plugins/ttsplugin/khtmltts.rc | 14 + plugins/uachanger/CMakeLists.txt | 14 + plugins/uachanger/Messages.sh | 3 + plugins/uachanger/uachangerplugin.cpp | 463 + plugins/uachanger/uachangerplugin.desktop | 136 + plugins/uachanger/uachangerplugin.h | 115 + plugins/uachanger/uachangerplugin.rc | 11 + plugins/uninstall.desktop | 2 + po/ar/akregator_konqplugin.po | 69 + po/ar/autorefresh.po | 102 + po/ar/babelfish.po | 250 + po/ar/dirfilterplugin.po | 90 + po/ar/fsview.po | 449 + po/ar/imgalleryplugin.po | 288 + po/ar/kcmbookmarks.po | 1421 +++ po/ar/kcmkonq.po | 335 + po/ar/kcmkonqhtml.po | 2391 +++++ po/ar/kcmperformance.po | 222 + po/ar/kfmclient.po | 169 + po/ar/khtmlsettingsplugin.po | 124 + po/ar/khtmltts.po | 53 + po/ar/konqueror.po | 2675 +++++ po/ar/kshellcmdplugin.po | 1939 ++++ po/ar/libkonq.po | 267 + po/ar/searchbarplugin.po | 90 + po/ar/uachangerplugin.po | 111 + po/ar/webenginepart.po | 1358 +++ po/ast/akregator_konqplugin.po | 60 + po/ast/autorefresh.po | 96 + po/ast/babelfish.po | 228 + po/ast/dirfilterplugin.po | 75 + po/ast/fsview.po | 432 + po/ast/imgalleryplugin.po | 282 + po/ast/kcmbookmarks.po | 162 + po/ast/kcmkonq.po | 94 + po/ast/kcmkonqhtml.po | 2201 ++++ po/ast/kcmperformance.po | 129 + po/ast/kfmclient.po | 136 + po/ast/khtmlsettingsplugin.po | 113 + po/ast/khtmltts.po | 35 + po/ast/konqueror.po | 1907 ++++ po/ast/kshellcmdplugin.po | 64 + po/ast/libkonq.po | 88 + po/ast/searchbarplugin.po | 78 + po/ast/uachangerplugin.po | 104 + po/ast/webenginepart.po | 1235 +++ po/bg/akregator_konqplugin.po | 68 + po/bg/autorefresh.po | 96 + po/bg/babelfish.po | 232 + po/bg/dirfilterplugin.po | 100 + po/bg/fsview.po | 430 + po/bg/imgalleryplugin.po | 285 + po/bg/kcmbookmarks.po | 1782 ++++ po/bg/kcmkonq.po | 299 + po/bg/kcmkonqhtml.po | 2415 +++++ po/bg/kcmperformance.po | 224 + po/bg/kfmclient.po | 330 + po/bg/khtmlsettingsplugin.po | 122 + po/bg/khtmltts.po | 50 + po/bg/konqueror.po | 2683 +++++ po/bg/kshellcmdplugin.po | 1865 ++++ po/bg/libkonq.po | 236 + po/bg/searchbarplugin.po | 88 + po/bg/uachangerplugin.po | 106 + po/bg/webenginepart.po | 1389 +++ po/bs/akregator_konqplugin.po | 71 + po/bs/autorefresh.po | 97 + po/bs/babelfish.po | 229 + po/bs/dirfilterplugin.po | 78 + po/bs/fsview.po | 434 + po/bs/imgalleryplugin.po | 290 + po/bs/kcmbookmarks.po | 1334 +++ po/bs/kcmkonq.po | 101 + po/bs/kcmkonqhtml.po | 2465 +++++ po/bs/kcmperformance.po | 230 + po/bs/kfmclient.po | 167 + po/bs/khtmlsettingsplugin.po | 122 + po/bs/khtmltts.po | 48 + po/bs/konqueror.po | 2604 +++++ po/bs/kshellcmdplugin.po | 71 + po/bs/libkonq.po | 221 + po/bs/searchbarplugin.po | 85 + po/bs/uachangerplugin.po | 107 + po/bs/webenginepart.po | 1385 +++ po/ca/akregator_konqplugin.po | 67 + po/ca/autorefresh.po | 100 + po/ca/babelfish.po | 235 + po/ca/dirfilterplugin.po | 80 + po/ca/docs/kcontrol5/bookmarks/index.docbook | 152 + .../docs/kcontrol5/filemanager/index.docbook | 87 + po/ca/docs/kcontrol5/history/index.docbook | 81 + po/ca/docs/kcontrol5/kcmcss/index.docbook | 440 + .../kcontrol5/khtml-adblock/index.docbook | 94 + .../kcontrol5/khtml-behavior/index.docbook | 114 + .../kcontrol5/khtml-general/index.docbook | 182 + .../kcontrol5/khtml-java-js/index.docbook | 161 + .../docs/kcontrol5/performance/index.docbook | 63 + .../docs/konqueror/format-font-size-less.png | Bin 0 -> 531 bytes .../docs/konqueror/format-font-size-more.png | Bin 0 -> 513 bytes po/ca/docs/konqueror/go-jump.png | Bin 0 -> 317 bytes po/ca/docs/konqueror/index.docbook | 7189 +++++++++++++ po/ca/docs/konqueror/konqorg.png | Bin 0 -> 110959 bytes po/ca/docs/konqueror/reset.png | Bin 0 -> 627 bytes .../docs/konqueror/viewproperties-dialog.png | Bin 0 -> 51864 bytes po/ca/fsview.po | 430 + po/ca/imgalleryplugin.po | 287 + po/ca/kcmbookmarks.po | 165 + po/ca/kcmkonq.po | 99 + po/ca/kcmkonqhtml.po | 2476 +++++ po/ca/kcmperformance.po | 156 + po/ca/kfmclient.po | 138 + po/ca/khtmlsettingsplugin.po | 121 + po/ca/khtmltts.po | 38 + po/ca/konqueror.po | 1860 ++++ po/ca/kshellcmdplugin.po | 70 + po/ca/libkonq.po | 92 + po/ca/searchbarplugin.po | 83 + po/ca/uachangerplugin.po | 110 + po/ca/webenginepart.po | 1316 +++ po/ca@valencia/akregator_konqplugin.po | 67 + po/ca@valencia/autorefresh.po | 100 + po/ca@valencia/babelfish.po | 235 + po/ca@valencia/dirfilterplugin.po | 80 + po/ca@valencia/fsview.po | 430 + po/ca@valencia/imgalleryplugin.po | 287 + po/ca@valencia/kcmbookmarks.po | 165 + po/ca@valencia/kcmkonq.po | 99 + po/ca@valencia/kcmkonqhtml.po | 2476 +++++ po/ca@valencia/kcmperformance.po | 156 + po/ca@valencia/kfmclient.po | 138 + po/ca@valencia/khtmlsettingsplugin.po | 121 + po/ca@valencia/khtmltts.po | 38 + po/ca@valencia/konqueror.po | 1861 ++++ po/ca@valencia/kshellcmdplugin.po | 70 + po/ca@valencia/libkonq.po | 92 + po/ca@valencia/searchbarplugin.po | 83 + po/ca@valencia/uachangerplugin.po | 110 + po/ca@valencia/webenginepart.po | 1316 +++ po/cs/akregator_konqplugin.po | 60 + po/cs/autorefresh.po | 95 + po/cs/babelfish.po | 225 + po/cs/dirfilterplugin.po | 75 + po/cs/fsview.po | 426 + po/cs/imgalleryplugin.po | 281 + po/cs/kcmbookmarks.po | 162 + po/cs/kcmkonq.po | 93 + po/cs/kcmkonqhtml.po | 2421 +++++ po/cs/kcmperformance.po | 147 + po/cs/kfmclient.po | 133 + po/cs/khtmlsettingsplugin.po | 114 + po/cs/khtmltts.po | 35 + po/cs/konqueror.po | 1832 ++++ po/cs/kshellcmdplugin.po | 64 + po/cs/libkonq.po | 89 + po/cs/searchbarplugin.po | 78 + po/cs/uachangerplugin.po | 104 + po/cs/webenginepart.po | 1295 +++ po/da/akregator_konqplugin.po | 63 + po/da/autorefresh.po | 96 + po/da/babelfish.po | 243 + po/da/dirfilterplugin.po | 98 + po/da/docs/konqueror/basics.docbook | 601 ++ po/da/docs/konqueror/bookmarks.docbook | 229 + po/da/docs/konqueror/browser.docbook | 681 ++ po/da/docs/konqueror/cmndline.png | Bin 0 -> 33688 bytes po/da/docs/konqueror/commands.docbook | 2103 ++++ po/da/docs/konqueror/config.docbook | 189 + po/da/docs/konqueror/credits.docbook | 307 + po/da/docs/konqueror/dirtree.png | Bin 0 -> 43374 bytes po/da/docs/konqueror/dragdrop.png | Bin 0 -> 35167 bytes po/da/docs/konqueror/faq.docbook | 281 + po/da/docs/konqueror/filemanager.docbook | 1527 +++ po/da/docs/konqueror/index.docbook | 137 + po/da/docs/konqueror/introduction.docbook | 73 + po/da/docs/konqueror/konqorg.png | Bin 0 -> 35865 bytes po/da/docs/konqueror/parts.png | Bin 0 -> 34310 bytes po/da/docs/konqueror/path-complete.docbook | 122 + po/da/docs/konqueror/plugins.docbook | 268 + po/da/docs/konqueror/save-settings.docbook | 156 + po/da/docs/konqueror/shortcut1.png | Bin 0 -> 18685 bytes po/da/docs/konqueror/shortcut2.png | Bin 0 -> 12036 bytes po/da/docs/konqueror/sidebar.docbook | 312 + po/da/fsview.po | 431 + po/da/imgalleryplugin.po | 285 + po/da/kcmbookmarks.po | 1875 ++++ po/da/kcmkonq.po | 228 + po/da/kcmkonqhtml.po | 2450 +++++ po/da/kcmperformance.po | 218 + po/da/kfmclient.po | 318 + po/da/khtmlsettingsplugin.po | 122 + po/da/khtmltts.po | 51 + po/da/konqueror.po | 2644 +++++ po/da/kshellcmdplugin.po | 1913 ++++ po/da/libkonq.po | 238 + po/da/searchbarplugin.po | 89 + po/da/uachangerplugin.po | 105 + po/da/webenginepart.po | 1401 +++ po/de/akregator_konqplugin.po | 66 + po/de/autorefresh.po | 97 + po/de/babelfish.po | 247 + po/de/dirfilterplugin.po | 99 + po/de/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 103 + po/de/docs/kcontrol5/history/index.docbook | 95 + po/de/docs/kcontrol5/kcmcss/index.docbook | 460 + .../kcontrol5/khtml-adblock/index.docbook | 122 + .../kcontrol5/khtml-behavior/index.docbook | 142 + .../kcontrol5/khtml-general/index.docbook | 200 + .../kcontrol5/khtml-java-js/index.docbook | 191 + .../docs/kcontrol5/performance/index.docbook | 77 + po/de/docs/konqueror/cmndline.png | Bin 0 -> 43597 bytes po/de/docs/konqueror/dirtree.png | Bin 0 -> 60200 bytes po/de/docs/konqueror/dragdrop.png | Bin 0 -> 42811 bytes po/de/docs/konqueror/folders.png | Bin 0 -> 44097 bytes po/de/docs/konqueror/index.docbook | 7809 ++++++++++++++ po/de/docs/konqueror/konqorg.png | Bin 0 -> 91528 bytes po/de/docs/konqueror/look.png | Bin 0 -> 47640 bytes po/de/docs/konqueror/parts.png | Bin 0 -> 41715 bytes po/de/docs/konqueror/shortcut1.png | Bin 0 -> 46600 bytes po/de/docs/konqueror/shortcut2.png | Bin 0 -> 46686 bytes po/de/docs/konqueror/thumbnails.png | Bin 0 -> 38958 bytes po/de/fsview.po | 433 + po/de/imgalleryplugin.po | 286 + po/de/kcmbookmarks.po | 2148 ++++ po/de/kcmkonq.po | 831 ++ po/de/kcmkonqhtml.po | 2610 +++++ po/de/kcmperformance.po | 216 + po/de/kfmclient.po | 335 + po/de/khtmlsettingsplugin.po | 123 + po/de/khtmltts.po | 68 + po/de/konqueror.po | 5603 +++++++++++ po/de/kshellcmdplugin.po | 4865 +++++++++ po/de/libkonq.po | 365 + po/de/searchbarplugin.po | 91 + po/de/uachangerplugin.po | 106 + po/de/webenginepart.po | 1481 +++ po/el/akregator_konqplugin.po | 69 + po/el/autorefresh.po | 99 + po/el/babelfish.po | 252 + po/el/dirfilterplugin.po | 104 + po/el/docs/konqueror/basics.docbook | 590 ++ po/el/docs/konqueror/bookmarks.docbook | 235 + po/el/docs/konqueror/browser.docbook | 790 ++ po/el/docs/konqueror/cmndline.png | Bin 0 -> 52971 bytes po/el/docs/konqueror/commands.docbook | 2466 +++++ po/el/docs/konqueror/config.docbook | 320 + po/el/docs/konqueror/credits.docbook | 453 + po/el/docs/konqueror/dirtree.png | Bin 0 -> 76753 bytes po/el/docs/konqueror/dragdrop.png | Bin 0 -> 82276 bytes po/el/docs/konqueror/faq.docbook | 311 + po/el/docs/konqueror/filemanager.docbook | 1453 +++ po/el/docs/konqueror/folders.png | Bin 0 -> 67909 bytes po/el/docs/konqueror/index.docbook | 8424 ++++++++++++++++ po/el/docs/konqueror/introduction.docbook | 95 + po/el/docs/konqueror/konqorg.png | Bin 0 -> 120451 bytes po/el/docs/konqueror/look.png | Bin 0 -> 75428 bytes po/el/docs/konqueror/parts.png | Bin 0 -> 42954 bytes po/el/docs/konqueror/path-complete.docbook | 165 + po/el/docs/konqueror/plugins.docbook | 865 ++ po/el/docs/konqueror/save-settings.docbook | 167 + po/el/docs/konqueror/shortcut1.png | Bin 0 -> 54554 bytes po/el/docs/konqueror/shortcut2.png | Bin 0 -> 56629 bytes po/el/docs/konqueror/sidebar.docbook | 393 + po/el/docs/konqueror/thumbnails.png | Bin 0 -> 58559 bytes po/el/docs/konqueror/view-extensions.docbook | 177 + .../docs/konqueror/viewproperties-dialog.png | Bin 0 -> 54272 bytes po/el/fsview.po | 433 + po/el/imgalleryplugin.po | 293 + po/el/kcmbookmarks.po | 1956 ++++ po/el/kcmkonq.po | 666 ++ po/el/kcmkonqhtml.po | 2553 +++++ po/el/kcmperformance.po | 220 + po/el/kfmclient.po | 339 + po/el/khtmlsettingsplugin.po | 126 + po/el/khtmltts.po | 59 + po/el/konqueror.po | 2695 +++++ po/el/kshellcmdplugin.po | 1962 ++++ po/el/libkonq.po | 355 + po/el/searchbarplugin.po | 90 + po/el/uachangerplugin.po | 106 + po/el/webenginepart.po | 1416 +++ po/en_GB/akregator_konqplugin.po | 64 + po/en_GB/autorefresh.po | 95 + po/en_GB/babelfish.po | 245 + po/en_GB/dirfilterplugin.po | 99 + po/en_GB/docs/konqueror/basics.docbook | 602 ++ po/en_GB/docs/konqueror/bookmarks.docbook | 245 + po/en_GB/docs/konqueror/browser.docbook | 593 ++ po/en_GB/docs/konqueror/commands.docbook | 2129 ++++ po/en_GB/docs/konqueror/config.docbook | 200 + po/en_GB/docs/konqueror/credits.docbook | 316 + po/en_GB/docs/konqueror/faq.docbook | 295 + po/en_GB/docs/konqueror/filemanager.docbook | 1455 +++ po/en_GB/docs/konqueror/index.docbook | 155 + po/en_GB/docs/konqueror/introduction.docbook | 87 + po/en_GB/docs/konqueror/path-complete.docbook | 136 + po/en_GB/docs/konqueror/plugins.docbook | 282 + po/en_GB/docs/konqueror/save-settings.docbook | 164 + po/en_GB/docs/konqueror/sidebar.docbook | 330 + po/en_GB/fsview.po | 431 + po/en_GB/imgalleryplugin.po | 285 + po/en_GB/kcmbookmarks.po | 1902 ++++ po/en_GB/kcmkonq.po | 790 ++ po/en_GB/kcmkonqhtml.po | 2570 +++++ po/en_GB/kcmperformance.po | 218 + po/en_GB/kfmclient.po | 327 + po/en_GB/khtmlsettingsplugin.po | 123 + po/en_GB/khtmltts.po | 61 + po/en_GB/konqueror.po | 3809 +++++++ po/en_GB/kshellcmdplugin.po | 3093 ++++++ po/en_GB/libkonq.po | 419 + po/en_GB/searchbarplugin.po | 88 + po/en_GB/uachangerplugin.po | 104 + po/en_GB/webenginepart.po | 1463 +++ po/eo/akregator_konqplugin.po | 67 + po/eo/autorefresh.po | 94 + po/eo/babelfish.po | 241 + po/eo/dirfilterplugin.po | 85 + po/eo/fsview.po | 420 + po/eo/imgalleryplugin.po | 288 + po/eo/kcmbookmarks.po | 1989 ++++ po/eo/kcmkonq.po | 236 + po/eo/kcmkonqhtml.po | 2442 +++++ po/eo/kcmperformance.po | 221 + po/eo/kfmclient.po | 160 + po/eo/khtmlsettingsplugin.po | 126 + po/eo/khtmltts.po | 49 + po/eo/konqueror.po | 2859 ++++++ po/eo/kshellcmdplugin.po | 2038 ++++ po/eo/libkonq.po | 324 + po/eo/searchbarplugin.po | 88 + po/eo/uachangerplugin.po | 103 + po/eo/webenginepart.po | 1309 +++ po/es/akregator_konqplugin.po | 67 + po/es/autorefresh.po | 104 + po/es/babelfish.po | 236 + po/es/dirfilterplugin.po | 80 + po/es/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 117 + po/es/docs/kcontrol5/history/index.docbook | 95 + po/es/docs/kcontrol5/kcmcss/index.docbook | 460 + .../kcontrol5/khtml-adblock/index.docbook | 136 + .../kcontrol5/khtml-behavior/index.docbook | 142 + .../kcontrol5/khtml-general/index.docbook | 210 + .../kcontrol5/khtml-java-js/index.docbook | 189 + .../docs/kcontrol5/performance/index.docbook | 77 + po/es/docs/konqueror/basics.docbook | 610 ++ po/es/docs/konqueror/bookmarks.docbook | 291 + po/es/docs/konqueror/browser.docbook | 820 ++ po/es/docs/konqueror/commands.docbook | 2521 +++++ po/es/docs/konqueror/config.docbook | 348 + po/es/docs/konqueror/credits.docbook | 487 + po/es/docs/konqueror/faq.docbook | 335 + po/es/docs/konqueror/filemanager.docbook | 1451 +++ po/es/docs/konqueror/index.docbook | 8964 +++++++++++++++++ po/es/docs/konqueror/introduction.docbook | 137 + po/es/docs/konqueror/path-complete.docbook | 195 + po/es/docs/konqueror/plugins.docbook | 896 ++ po/es/docs/konqueror/save-settings.docbook | 191 + po/es/docs/konqueror/sidebar.docbook | 415 + po/es/docs/konqueror/view-extensions.docbook | 177 + po/es/fsview.po | 443 + po/es/imgalleryplugin.po | 298 + po/es/kcmbookmarks.po | 1369 +++ po/es/kcmkonq.po | 109 + po/es/kcmkonqhtml.po | 2592 +++++ po/es/kcmperformance.po | 220 + po/es/kfmclient.po | 171 + po/es/khtmlsettingsplugin.po | 121 + po/es/khtmltts.po | 52 + po/es/konqueror.po | 2596 +++++ po/es/kshellcmdplugin.po | 77 + po/es/libkonq.po | 230 + po/es/searchbarplugin.po | 87 + po/es/uachangerplugin.po | 106 + po/es/webenginepart.po | 1446 +++ po/et/akregator_konqplugin.po | 64 + po/et/autorefresh.po | 96 + po/et/babelfish.po | 245 + po/et/dirfilterplugin.po | 97 + po/et/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 103 + po/et/docs/kcontrol5/history/index.docbook | 95 + po/et/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 114 + .../kcontrol5/khtml-behavior/index.docbook | 121 + .../kcontrol5/khtml-general/index.docbook | 216 + .../kcontrol5/khtml-java-js/index.docbook | 176 + .../docs/kcontrol5/performance/index.docbook | 181 + po/et/fsview.po | 432 + po/et/imgalleryplugin.po | 284 + po/et/kcmbookmarks.po | 1877 ++++ po/et/kcmkonq.po | 791 ++ po/et/kcmkonqhtml.po | 2465 +++++ po/et/kcmperformance.po | 207 + po/et/kfmclient.po | 328 + po/et/khtmlsettingsplugin.po | 121 + po/et/khtmltts.po | 54 + po/et/konqueror.po | 6026 +++++++++++ po/et/kshellcmdplugin.po | 5311 ++++++++++ po/et/libkonq.po | 421 + po/et/searchbarplugin.po | 86 + po/et/uachangerplugin.po | 105 + po/et/webenginepart.po | 1456 +++ po/eu/akregator_konqplugin.po | 70 + po/eu/autorefresh.po | 97 + po/eu/babelfish.po | 232 + po/eu/dirfilterplugin.po | 92 + po/eu/fsview.po | 435 + po/eu/imgalleryplugin.po | 288 + po/eu/kcmbookmarks.po | 1737 ++++ po/eu/kcmkonq.po | 254 + po/eu/kcmkonqhtml.po | 2485 +++++ po/eu/kcmperformance.po | 222 + po/eu/kfmclient.po | 171 + po/eu/khtmlsettingsplugin.po | 127 + po/eu/khtmltts.po | 51 + po/eu/konqueror.po | 2651 +++++ po/eu/kshellcmdplugin.po | 1912 ++++ po/eu/libkonq.po | 233 + po/eu/searchbarplugin.po | 91 + po/eu/uachangerplugin.po | 108 + po/eu/webenginepart.po | 1431 +++ po/fa/akregator_konqplugin.po | 68 + po/fa/autorefresh.po | 96 + po/fa/babelfish.po | 244 + po/fa/dirfilterplugin.po | 99 + po/fa/fsview.po | 428 + po/fa/imgalleryplugin.po | 284 + po/fa/kcmbookmarks.po | 2099 ++++ po/fa/kcmkonq.po | 884 ++ po/fa/kcmkonqhtml.po | 2538 +++++ po/fa/kcmperformance.po | 226 + po/fa/kfmclient.po | 328 + po/fa/khtmlsettingsplugin.po | 126 + po/fa/khtmltts.po | 78 + po/fa/konqueror.po | 4612 +++++++++ po/fa/kshellcmdplugin.po | 3662 +++++++ po/fa/libkonq.po | 329 + po/fa/searchbarplugin.po | 78 + po/fa/uachangerplugin.po | 109 + po/fa/webenginepart.po | 1325 +++ po/fi/akregator_konqplugin.po | 69 + po/fi/autorefresh.po | 102 + po/fi/babelfish.po | 249 + po/fi/dirfilterplugin.po | 105 + po/fi/fsview.po | 438 + po/fi/imgalleryplugin.po | 287 + po/fi/kcmbookmarks.po | 1849 ++++ po/fi/kcmkonq.po | 311 + po/fi/kcmkonqhtml.po | 2586 +++++ po/fi/kcmperformance.po | 221 + po/fi/kfmclient.po | 172 + po/fi/khtmlsettingsplugin.po | 130 + po/fi/khtmltts.po | 55 + po/fi/konqueror.po | 2725 +++++ po/fi/kshellcmdplugin.po | 2005 ++++ po/fi/libkonq.po | 355 + po/fi/searchbarplugin.po | 99 + po/fi/uachangerplugin.po | 108 + po/fi/webenginepart.po | 1361 +++ po/fr/akregator_konqplugin.po | 70 + po/fr/autorefresh.po | 103 + po/fr/babelfish.po | 263 + po/fr/dirfilterplugin.po | 101 + po/fr/docs/konqueror/basics.docbook | 560 + po/fr/docs/konqueror/bookmarks.docbook | 215 + po/fr/docs/konqueror/browser.docbook | 760 ++ po/fr/docs/konqueror/cmndline.png | Bin 0 -> 52369 bytes po/fr/docs/konqueror/commands.docbook | 2467 +++++ po/fr/docs/konqueror/config.docbook | 310 + po/fr/docs/konqueror/credits.docbook | 431 + po/fr/docs/konqueror/dirtree.png | Bin 0 -> 65577 bytes po/fr/docs/konqueror/dragdrop.png | Bin 0 -> 49378 bytes po/fr/docs/konqueror/faq.docbook | 295 + po/fr/docs/konqueror/filemanager.docbook | 1434 +++ po/fr/docs/konqueror/index.docbook | 8179 +++++++++++++++ po/fr/docs/konqueror/introduction.docbook | 85 + po/fr/docs/konqueror/konqorg.png | Bin 0 -> 89941 bytes po/fr/docs/konqueror/parts.png | Bin 0 -> 43621 bytes po/fr/docs/konqueror/path-complete.docbook | 149 + po/fr/docs/konqueror/plugins.docbook | 856 ++ po/fr/docs/konqueror/save-settings.docbook | 153 + po/fr/docs/konqueror/shortcut1.png | Bin 0 -> 55089 bytes po/fr/docs/konqueror/shortcut2.png | Bin 0 -> 46118 bytes po/fr/docs/konqueror/sidebar.docbook | 357 + po/fr/docs/konqueror/view-extensions.docbook | 177 + po/fr/fsview.po | 443 + po/fr/imgalleryplugin.po | 300 + po/fr/kcmbookmarks.po | 1850 ++++ po/fr/kcmkonq.po | 271 + po/fr/kcmkonqhtml.po | 2549 +++++ po/fr/kcmperformance.po | 233 + po/fr/kfmclient.po | 173 + po/fr/khtmlsettingsplugin.po | 132 + po/fr/khtmltts.po | 52 + po/fr/konqueror.po | 2750 +++++ po/fr/kshellcmdplugin.po | 2012 ++++ po/fr/libkonq.po | 274 + po/fr/searchbarplugin.po | 95 + po/fr/uachangerplugin.po | 111 + po/fr/webenginepart.po | 1490 +++ po/ga/akregator_konqplugin.po | 66 + po/ga/autorefresh.po | 97 + po/ga/babelfish.po | 244 + po/ga/dirfilterplugin.po | 101 + po/ga/fsview.po | 441 + po/ga/imgalleryplugin.po | 289 + po/ga/kcmbookmarks.po | 1817 ++++ po/ga/kcmkonq.po | 384 + po/ga/kcmkonqhtml.po | 2513 +++++ po/ga/kcmperformance.po | 232 + po/ga/kfmclient.po | 166 + po/ga/khtmlsettingsplugin.po | 127 + po/ga/khtmltts.po | 61 + po/ga/konqueror.po | 4001 ++++++++ po/ga/kshellcmdplugin.po | 3089 ++++++ po/ga/libkonq.po | 407 + po/ga/searchbarplugin.po | 87 + po/ga/uachangerplugin.po | 105 + po/ga/webenginepart.po | 1380 +++ po/gl/akregator_konqplugin.po | 67 + po/gl/autorefresh.po | 99 + po/gl/babelfish.po | 231 + po/gl/dirfilterplugin.po | 88 + po/gl/fsview.po | 435 + po/gl/imgalleryplugin.po | 288 + po/gl/kcmbookmarks.po | 1374 +++ po/gl/kcmkonq.po | 107 + po/gl/kcmkonqhtml.po | 2474 +++++ po/gl/kcmperformance.po | 218 + po/gl/kfmclient.po | 177 + po/gl/khtmlsettingsplugin.po | 118 + po/gl/khtmltts.po | 48 + po/gl/konqueror.po | 2577 +++++ po/gl/kshellcmdplugin.po | 77 + po/gl/libkonq.po | 227 + po/gl/searchbarplugin.po | 91 + po/gl/uachangerplugin.po | 106 + po/gl/webenginepart.po | 1384 +++ po/he/akregator_konqplugin.po | 67 + po/he/autorefresh.po | 94 + po/he/babelfish.po | 235 + po/he/dirfilterplugin.po | 85 + po/he/fsview.po | 429 + po/he/imgalleryplugin.po | 285 + po/he/kcmbookmarks.po | 169 + po/he/kcmkonq.po | 104 + po/he/kcmkonqhtml.po | 2372 +++++ po/he/kcmperformance.po | 142 + po/he/kfmclient.po | 136 + po/he/khtmlsettingsplugin.po | 124 + po/he/khtmltts.po | 35 + po/he/konqueror.po | 2147 ++++ po/he/kshellcmdplugin.po | 75 + po/he/libkonq.po | 100 + po/he/searchbarplugin.po | 79 + po/he/uachangerplugin.po | 113 + po/hi/akregator_konqplugin.po | 62 + po/hi/autorefresh.po | 99 + po/hi/babelfish.po | 244 + po/hi/dirfilterplugin.po | 94 + po/hi/fsview.po | 429 + po/hi/imgalleryplugin.po | 277 + po/hi/kcmbookmarks.po | 1274 +++ po/hi/kcmkonq.po | 92 + po/hi/kcmkonqhtml.po | 2252 +++++ po/hi/kcmperformance.po | 153 + po/hi/kfmclient.po | 125 + po/hi/khtmlsettingsplugin.po | 123 + po/hi/khtmltts.po | 70 + po/hi/konqueror.po | 4248 ++++++++ po/hi/kshellcmdplugin.po | 3358 ++++++ po/hi/libkonq.po | 309 + po/hi/searchbarplugin.po | 79 + po/hi/uachangerplugin.po | 109 + po/hr/akregator_konqplugin.po | 71 + po/hr/autorefresh.po | 99 + po/hr/babelfish.po | 244 + po/hr/dirfilterplugin.po | 104 + po/hr/fsview.po | 436 + po/hr/imgalleryplugin.po | 288 + po/hr/kcmbookmarks.po | 1784 ++++ po/hr/kcmkonq.po | 662 ++ po/hr/kcmkonqhtml.po | 2547 +++++ po/hr/kcmperformance.po | 232 + po/hr/kfmclient.po | 341 + po/hr/khtmlsettingsplugin.po | 128 + po/hr/khtmltts.po | 56 + po/hr/konqueror.po | 3923 ++++++++ po/hr/kshellcmdplugin.po | 3141 ++++++ po/hr/libkonq.po | 416 + po/hr/searchbarplugin.po | 92 + po/hr/uachangerplugin.po | 107 + po/hu/akregator_konqplugin.po | 65 + po/hu/autorefresh.po | 97 + po/hu/babelfish.po | 244 + po/hu/dirfilterplugin.po | 100 + po/hu/fsview.po | 430 + po/hu/imgalleryplugin.po | 288 + po/hu/kcmbookmarks.po | 2112 ++++ po/hu/kcmkonq.po | 650 ++ po/hu/kcmkonqhtml.po | 2472 +++++ po/hu/kcmperformance.po | 216 + po/hu/kfmclient.po | 164 + po/hu/khtmlsettingsplugin.po | 126 + po/hu/khtmltts.po | 49 + po/hu/konqueror.po | 2690 +++++ po/hu/kshellcmdplugin.po | 1879 ++++ po/hu/libkonq.po | 242 + po/hu/searchbarplugin.po | 89 + po/hu/uachangerplugin.po | 105 + po/hu/webenginepart.po | 1394 +++ po/ia/akregator_konqplugin.po | 64 + po/ia/autorefresh.po | 96 + po/ia/babelfish.po | 230 + po/ia/dirfilterplugin.po | 85 + po/ia/fsview.po | 431 + po/ia/imgalleryplugin.po | 287 + po/ia/kcmbookmarks.po | 1964 ++++ po/ia/kcmkonq.po | 95 + po/ia/kcmkonqhtml.po | 2485 +++++ po/ia/kcmperformance.po | 215 + po/ia/kfmclient.po | 165 + po/ia/khtmlsettingsplugin.po | 115 + po/ia/khtmltts.po | 49 + po/ia/konqueror.po | 2640 +++++ po/ia/kshellcmdplugin.po | 1906 ++++ po/ia/libkonq.po | 217 + po/ia/searchbarplugin.po | 87 + po/ia/uachangerplugin.po | 104 + po/ia/webenginepart.po | 1291 +++ po/id/akregator_konqplugin.po | 65 + po/id/autorefresh.po | 94 + po/id/babelfish.po | 227 + po/id/dirfilterplugin.po | 75 + po/id/fsview.po | 423 + po/id/imgalleryplugin.po | 281 + po/id/kcmbookmarks.po | 1717 ++++ po/id/kcmkonq.po | 232 + po/id/kcmkonqhtml.po | 2501 +++++ po/id/kcmperformance.po | 217 + po/id/kfmclient.po | 166 + po/id/khtmlsettingsplugin.po | 114 + po/id/khtmltts.po | 50 + po/id/konqueror.po | 2656 +++++ po/id/kshellcmdplugin.po | 1975 ++++ po/id/libkonq.po | 218 + po/id/searchbarplugin.po | 85 + po/id/uachangerplugin.po | 104 + po/id/webenginepart.po | 1249 +++ po/is/akregator_konqplugin.po | 70 + po/is/autorefresh.po | 102 + po/is/babelfish.po | 232 + po/is/dirfilterplugin.po | 80 + po/is/fsview.po | 436 + po/is/imgalleryplugin.po | 291 + po/is/kcmbookmarks.po | 1300 +++ po/is/kcmkonq.po | 103 + po/is/kcmkonqhtml.po | 2440 +++++ po/is/kcmperformance.po | 217 + po/is/kfmclient.po | 170 + po/is/khtmlsettingsplugin.po | 119 + po/is/khtmltts.po | 49 + po/is/konqueror.po | 2558 +++++ po/is/kshellcmdplugin.po | 75 + po/is/libkonq.po | 226 + po/is/searchbarplugin.po | 88 + po/is/uachangerplugin.po | 108 + po/it/akregator_konqplugin.po | 63 + po/it/autorefresh.po | 97 + po/it/babelfish.po | 249 + po/it/dirfilterplugin.po | 100 + po/it/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 131 + po/it/docs/kcontrol5/history/index.docbook | 95 + po/it/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 118 + .../kcontrol5/khtml-behavior/index.docbook | 136 + .../kcontrol5/khtml-general/index.docbook | 212 + .../kcontrol5/khtml-java-js/index.docbook | 191 + .../docs/kcontrol5/performance/index.docbook | 85 + po/it/docs/konqueror/index.docbook | 7343 ++++++++++++++ po/it/fsview.po | 430 + po/it/imgalleryplugin.po | 290 + po/it/kcmbookmarks.po | 1900 ++++ po/it/kcmkonq.po | 648 ++ po/it/kcmkonqhtml.po | 2603 +++++ po/it/kcmperformance.po | 223 + po/it/kfmclient.po | 332 + po/it/khtmlsettingsplugin.po | 117 + po/it/khtmltts.po | 68 + po/it/konqueror.po | 2689 +++++ po/it/kshellcmdplugin.po | 1948 ++++ po/it/libkonq.po | 235 + po/it/searchbarplugin.po | 85 + po/it/uachangerplugin.po | 106 + po/it/webenginepart.po | 1369 +++ po/ja/akregator_konqplugin.po | 65 + po/ja/autorefresh.po | 98 + po/ja/babelfish.po | 231 + po/ja/dirfilterplugin.po | 80 + po/ja/fsview.po | 429 + po/ja/imgalleryplugin.po | 285 + po/ja/kcmbookmarks.po | 171 + po/ja/kcmkonq.po | 108 + po/ja/kcmkonqhtml.po | 2450 +++++ po/ja/kcmperformance.po | 171 + po/ja/kfmclient.po | 143 + po/ja/khtmlsettingsplugin.po | 123 + po/ja/khtmltts.po | 32 + po/ja/konqueror.po | 2295 +++++ po/ja/kshellcmdplugin.po | 79 + po/ja/libkonq.po | 102 + po/ja/searchbarplugin.po | 82 + po/ja/uachangerplugin.po | 109 + po/ja/webenginepart.po | 1201 +++ po/kk/akregator_konqplugin.po | 66 + po/kk/autorefresh.po | 95 + po/kk/babelfish.po | 240 + po/kk/dirfilterplugin.po | 97 + po/kk/fsview.po | 425 + po/kk/imgalleryplugin.po | 282 + po/kk/kcmbookmarks.po | 1700 ++++ po/kk/kcmkonq.po | 332 + po/kk/kcmkonqhtml.po | 2445 +++++ po/kk/kcmperformance.po | 227 + po/kk/kfmclient.po | 338 + po/kk/khtmlsettingsplugin.po | 125 + po/kk/khtmltts.po | 51 + po/kk/konqueror.po | 2690 +++++ po/kk/kshellcmdplugin.po | 1934 ++++ po/kk/libkonq.po | 258 + po/kk/searchbarplugin.po | 90 + po/kk/uachangerplugin.po | 104 + po/kk/webenginepart.po | 1375 +++ po/km/akregator_konqplugin.po | 68 + po/km/autorefresh.po | 96 + po/km/babelfish.po | 395 + po/km/dirfilterplugin.po | 96 + po/km/fsview.po | 427 + po/km/imgalleryplugin.po | 280 + po/km/kcmbookmarks.po | 1400 +++ po/km/kcmkonq.po | 95 + po/km/kcmkonqhtml.po | 2431 +++++ po/km/kcmperformance.po | 232 + po/km/kfmclient.po | 163 + po/km/khtmlsettingsplugin.po | 460 + po/km/khtmltts.po | 48 + po/km/konqueror.po | 2563 +++++ po/km/kshellcmdplugin.po | 1238 +++ po/km/libkonq.po | 209 + po/km/searchbarplugin.po | 89 + po/km/uachangerplugin.po | 106 + po/km/webenginepart.po | 1366 +++ po/ko/akregator_konqplugin.po | 64 + po/ko/autorefresh.po | 95 + po/ko/babelfish.po | 228 + po/ko/dirfilterplugin.po | 76 + po/ko/fsview.po | 425 + po/ko/imgalleryplugin.po | 281 + po/ko/kcmbookmarks.po | 1270 +++ po/ko/kcmkonq.po | 101 + po/ko/kcmkonqhtml.po | 2376 +++++ po/ko/kcmperformance.po | 205 + po/ko/kfmclient.po | 162 + po/ko/khtmlsettingsplugin.po | 114 + po/ko/khtmltts.po | 46 + po/ko/konqueror.po | 2510 +++++ po/ko/kshellcmdplugin.po | 64 + po/ko/libkonq.po | 211 + po/ko/searchbarplugin.po | 85 + po/ko/uachangerplugin.po | 104 + po/ko/webenginepart.po | 1413 +++ po/lt/akregator_konqplugin.po | 68 + po/lt/autorefresh.po | 97 + po/lt/babelfish.po | 230 + po/lt/dirfilterplugin.po | 77 + po/lt/docs/konqueror/basics.docbook | 606 ++ po/lt/docs/konqueror/bookmarks.docbook | 233 + po/lt/docs/konqueror/browser.docbook | 767 ++ po/lt/docs/konqueror/config.docbook | 320 + po/lt/docs/konqueror/filemanager.docbook | 1478 +++ po/lt/docs/konqueror/introduction.docbook | 97 + po/lt/docs/konqueror/plugins.docbook | 298 + po/lt/docs/konqueror/save-settings.docbook | 171 + po/lt/docs/konqueror/sidebar.docbook | 369 + po/lt/docs/konqueror/view-extensions.docbook | 177 + po/lt/fsview.po | 439 + po/lt/imgalleryplugin.po | 290 + po/lt/kcmbookmarks.po | 1356 +++ po/lt/kcmkonq.po | 97 + po/lt/kcmkonqhtml.po | 2461 +++++ po/lt/kcmperformance.po | 226 + po/lt/kfmclient.po | 166 + po/lt/khtmlsettingsplugin.po | 120 + po/lt/khtmltts.po | 46 + po/lt/konqueror.po | 2606 +++++ po/lt/kshellcmdplugin.po | 65 + po/lt/libkonq.po | 222 + po/lt/searchbarplugin.po | 87 + po/lt/uachangerplugin.po | 104 + po/lt/webenginepart.po | 1385 +++ po/lv/akregator_konqplugin.po | 70 + po/lv/autorefresh.po | 99 + po/lv/babelfish.po | 245 + po/lv/dirfilterplugin.po | 97 + po/lv/fsview.po | 437 + po/lv/imgalleryplugin.po | 286 + po/lv/kcmbookmarks.po | 1706 ++++ po/lv/kcmkonq.po | 629 ++ po/lv/kcmkonqhtml.po | 2465 +++++ po/lv/kcmperformance.po | 231 + po/lv/kfmclient.po | 166 + po/lv/khtmlsettingsplugin.po | 127 + po/lv/khtmltts.po | 64 + po/lv/konqueror.po | 2687 +++++ po/lv/kshellcmdplugin.po | 1935 ++++ po/lv/libkonq.po | 269 + po/lv/searchbarplugin.po | 89 + po/lv/uachangerplugin.po | 106 + po/ml/akregator_konqplugin.po | 62 + po/ml/autorefresh.po | 97 + po/ml/babelfish.po | 229 + po/ml/dirfilterplugin.po | 77 + po/ml/fsview.po | 419 + po/ml/imgalleryplugin.po | 265 + po/ml/kcmbookmarks.po | 1023 ++ po/ml/kcmkonq.po | 583 ++ po/ml/kcmkonqhtml.po | 2205 ++++ po/ml/kcmperformance.po | 144 + po/ml/kfmclient.po | 157 + po/ml/khtmlsettingsplugin.po | 115 + po/ml/khtmltts.po | 45 + po/ml/konqueror.po | 2099 ++++ po/ml/kshellcmdplugin.po | 1076 ++ po/ml/libkonq.po | 212 + po/ml/searchbarplugin.po | 79 + po/ml/uachangerplugin.po | 106 + po/ml/webenginepart.po | 1206 +++ po/mr/akregator_konqplugin.po | 66 + po/mr/autorefresh.po | 95 + po/mr/babelfish.po | 225 + po/mr/dirfilterplugin.po | 75 + po/mr/fsview.po | 418 + po/mr/imgalleryplugin.po | 267 + po/mr/kcmbookmarks.po | 803 ++ po/mr/kcmkonq.po | 226 + po/mr/kcmkonqhtml.po | 2162 ++++ po/mr/kcmperformance.po | 179 + po/mr/kfmclient.po | 165 + po/mr/khtmlsettingsplugin.po | 118 + po/mr/khtmltts.po | 51 + po/mr/konqueror.po | 2453 +++++ po/mr/kshellcmdplugin.po | 1616 +++ po/mr/libkonq.po | 231 + po/mr/searchbarplugin.po | 84 + po/mr/uachangerplugin.po | 104 + po/mr/webenginepart.po | 1328 +++ po/nb/akregator_konqplugin.po | 64 + po/nb/autorefresh.po | 101 + po/nb/babelfish.po | 229 + po/nb/dirfilterplugin.po | 78 + po/nb/docs/kcontrol5/bookmarks/index.docbook | 166 + po/nb/docs/kcontrol5/history/index.docbook | 95 + po/nb/docs/kcontrol5/kcmcss/index.docbook | 452 + po/nb/docs/konqueror/basics.docbook | 620 ++ po/nb/docs/konqueror/bookmarks.docbook | 235 + po/nb/docs/konqueror/browser.docbook | 695 ++ po/nb/docs/konqueror/commands.docbook | 2117 ++++ po/nb/docs/konqueror/config.docbook | 203 + po/nb/docs/konqueror/credits.docbook | 447 + po/nb/docs/konqueror/faq.docbook | 309 + po/nb/docs/konqueror/filemanager.docbook | 1545 +++ po/nb/docs/konqueror/introduction.docbook | 95 + po/nb/docs/konqueror/path-complete.docbook | 165 + po/nb/docs/konqueror/plugins.docbook | 282 + po/nb/docs/konqueror/save-settings.docbook | 169 + po/nb/docs/konqueror/sidebar.docbook | 330 + po/nb/docs/konqueror/view-extensions.docbook | 175 + po/nb/fsview.po | 429 + po/nb/imgalleryplugin.po | 283 + po/nb/kcmbookmarks.po | 172 + po/nb/kcmkonq.po | 99 + po/nb/kcmkonqhtml.po | 2422 +++++ po/nb/kcmperformance.po | 145 + po/nb/kfmclient.po | 140 + po/nb/khtmlsettingsplugin.po | 117 + po/nb/khtmltts.po | 40 + po/nb/konqueror.po | 1842 ++++ po/nb/kshellcmdplugin.po | 72 + po/nb/libkonq.po | 94 + po/nb/searchbarplugin.po | 81 + po/nb/uachangerplugin.po | 108 + po/nb/webenginepart.po | 1241 +++ po/nds/akregator_konqplugin.po | 66 + po/nds/autorefresh.po | 97 + po/nds/babelfish.po | 242 + po/nds/dirfilterplugin.po | 97 + po/nds/fsview.po | 429 + po/nds/imgalleryplugin.po | 284 + po/nds/kcmbookmarks.po | 1856 ++++ po/nds/kcmkonq.po | 97 + po/nds/kcmkonqhtml.po | 2467 +++++ po/nds/kcmperformance.po | 226 + po/nds/kfmclient.po | 169 + po/nds/khtmlsettingsplugin.po | 125 + po/nds/khtmltts.po | 57 + po/nds/konqueror.po | 2744 +++++ po/nds/kshellcmdplugin.po | 1988 ++++ po/nds/libkonq.po | 325 + po/nds/searchbarplugin.po | 90 + po/nds/uachangerplugin.po | 105 + po/nds/webenginepart.po | 1415 +++ po/nl/akregator_konqplugin.po | 63 + po/nl/autorefresh.po | 99 + po/nl/babelfish.po | 254 + po/nl/dirfilterplugin.po | 105 + po/nl/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 89 + po/nl/docs/kcontrol5/history/index.docbook | 81 + po/nl/docs/kcontrol5/kcmcss/index.docbook | 440 + .../kcontrol5/khtml-adblock/index.docbook | 94 + .../kcontrol5/khtml-behavior/index.docbook | 114 + .../kcontrol5/khtml-general/index.docbook | 182 + .../kcontrol5/khtml-java-js/index.docbook | 161 + .../docs/kcontrol5/performance/index.docbook | 63 + po/nl/docs/konqueror/basics.docbook | 568 ++ po/nl/docs/konqueror/bookmarks.docbook | 213 + po/nl/docs/konqueror/browser.docbook | 776 ++ po/nl/docs/konqueror/cmndline.png | Bin 0 -> 37247 bytes po/nl/docs/konqueror/commands.docbook | 2454 +++++ po/nl/docs/konqueror/config.docbook | 306 + po/nl/docs/konqueror/credits.docbook | 435 + po/nl/docs/konqueror/dirtree.png | Bin 0 -> 35723 bytes po/nl/docs/konqueror/dragdrop.png | Bin 0 -> 37627 bytes po/nl/docs/konqueror/faq.docbook | 297 + po/nl/docs/konqueror/filemanager.docbook | 1441 +++ po/nl/docs/konqueror/index.docbook | 7245 +++++++++++++ po/nl/docs/konqueror/introduction.docbook | 81 + po/nl/docs/konqueror/konqorg.png | Bin 0 -> 41799 bytes po/nl/docs/konqueror/parts.png | Bin 0 -> 35120 bytes po/nl/docs/konqueror/path-complete.docbook | 151 + po/nl/docs/konqueror/plugins.docbook | 853 ++ po/nl/docs/konqueror/save-settings.docbook | 149 + po/nl/docs/konqueror/shortcut1.png | Bin 0 -> 21260 bytes po/nl/docs/konqueror/shortcut2.png | Bin 0 -> 11994 bytes po/nl/docs/konqueror/sidebar.docbook | 373 + po/nl/docs/konqueror/view-extensions.docbook | 175 + po/nl/fsview.po | 437 + po/nl/imgalleryplugin.po | 298 + po/nl/kcmbookmarks.po | 2158 ++++ po/nl/kcmkonq.po | 270 + po/nl/kcmkonqhtml.po | 2604 +++++ po/nl/kcmperformance.po | 222 + po/nl/kfmclient.po | 346 + po/nl/khtmlsettingsplugin.po | 126 + po/nl/khtmltts.po | 50 + po/nl/konqueror.po | 2693 +++++ po/nl/kshellcmdplugin.po | 1956 ++++ po/nl/libkonq.po | 247 + po/nl/searchbarplugin.po | 89 + po/nl/uachangerplugin.po | 106 + po/nl/webenginepart.po | 1472 +++ po/nn/akregator_konqplugin.po | 63 + po/nn/autorefresh.po | 99 + po/nn/babelfish.po | 231 + po/nn/dirfilterplugin.po | 78 + po/nn/fsview.po | 426 + po/nn/imgalleryplugin.po | 280 + po/nn/kcmbookmarks.po | 166 + po/nn/kcmkonq.po | 98 + po/nn/kcmkonqhtml.po | 2415 +++++ po/nn/kcmperformance.po | 156 + po/nn/kfmclient.po | 137 + po/nn/khtmlsettingsplugin.po | 118 + po/nn/khtmltts.po | 39 + po/nn/konqueror.po | 1840 ++++ po/nn/kshellcmdplugin.po | 67 + po/nn/libkonq.po | 92 + po/nn/searchbarplugin.po | 81 + po/nn/uachangerplugin.po | 107 + po/nn/webenginepart.po | 1303 +++ po/pa/akregator_konqplugin.po | 66 + po/pa/autorefresh.po | 96 + po/pa/babelfish.po | 241 + po/pa/dirfilterplugin.po | 97 + po/pa/fsview.po | 429 + po/pa/imgalleryplugin.po | 283 + po/pa/kcmbookmarks.po | 819 ++ po/pa/kcmkonq.po | 243 + po/pa/kcmkonqhtml.po | 2237 ++++ po/pa/kcmperformance.po | 148 + po/pa/kfmclient.po | 132 + po/pa/khtmlsettingsplugin.po | 119 + po/pa/khtmltts.po | 50 + po/pa/konqueror.po | 2487 +++++ po/pa/kshellcmdplugin.po | 1597 +++ po/pa/libkonq.po | 252 + po/pa/searchbarplugin.po | 85 + po/pa/uachangerplugin.po | 105 + po/pa/webenginepart.po | 1397 +++ po/pl/akregator_konqplugin.po | 78 + po/pl/autorefresh.po | 99 + po/pl/babelfish.po | 253 + po/pl/dirfilterplugin.po | 103 + po/pl/docs/konqueror/basics.docbook | 608 ++ po/pl/docs/konqueror/bookmarks.docbook | 241 + po/pl/docs/konqueror/browser.docbook | 701 ++ po/pl/docs/konqueror/cmndline.png | Bin 0 -> 43919 bytes po/pl/docs/konqueror/commands.docbook | 2115 ++++ po/pl/docs/konqueror/config.docbook | 195 + po/pl/docs/konqueror/credits.docbook | 343 + po/pl/docs/konqueror/dirtree.png | Bin 0 -> 55653 bytes po/pl/docs/konqueror/dragdrop.png | Bin 0 -> 58321 bytes po/pl/docs/konqueror/faq.docbook | 293 + po/pl/docs/konqueror/filemanager.docbook | 1523 +++ po/pl/docs/konqueror/index.docbook | 173 + po/pl/docs/konqueror/introduction.docbook | 85 + po/pl/docs/konqueror/konqorg.png | Bin 0 -> 126902 bytes po/pl/docs/konqueror/parts.png | Bin 0 -> 34950 bytes po/pl/docs/konqueror/path-complete.docbook | 136 + po/pl/docs/konqueror/plugins.docbook | 278 + po/pl/docs/konqueror/save-settings.docbook | 170 + po/pl/docs/konqueror/shortcut1.png | Bin 0 -> 47201 bytes po/pl/docs/konqueror/shortcut2.png | Bin 0 -> 46685 bytes po/pl/docs/konqueror/sidebar.docbook | 324 + po/pl/fsview.po | 436 + po/pl/imgalleryplugin.po | 291 + po/pl/kcmbookmarks.po | 1730 ++++ po/pl/kcmkonq.po | 244 + po/pl/kcmkonqhtml.po | 2554 +++++ po/pl/kcmperformance.po | 216 + po/pl/kfmclient.po | 338 + po/pl/khtmlsettingsplugin.po | 126 + po/pl/khtmltts.po | 53 + po/pl/konqueror.po | 2678 +++++ po/pl/kshellcmdplugin.po | 1962 ++++ po/pl/libkonq.po | 245 + po/pl/searchbarplugin.po | 97 + po/pl/uachangerplugin.po | 109 + po/pl/webenginepart.po | 1395 +++ po/pt/akregator_konqplugin.po | 56 + po/pt/autorefresh.po | 92 + po/pt/babelfish.po | 224 + po/pt/dirfilterplugin.po | 72 + po/pt/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 103 + po/pt/docs/kcontrol5/history/index.docbook | 95 + po/pt/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 106 + .../kcontrol5/khtml-behavior/index.docbook | 120 + .../kcontrol5/khtml-general/index.docbook | 196 + .../kcontrol5/khtml-java-js/index.docbook | 173 + .../docs/kcontrol5/performance/index.docbook | 77 + po/pt/docs/konqueror/basics.docbook | 590 ++ po/pt/docs/konqueror/bookmarks.docbook | 233 + po/pt/docs/konqueror/browser.docbook | 790 ++ po/pt/docs/konqueror/commands.docbook | 2477 +++++ po/pt/docs/konqueror/config.docbook | 320 + po/pt/docs/konqueror/credits.docbook | 447 + po/pt/docs/konqueror/faq.docbook | 311 + po/pt/docs/konqueror/filemanager.docbook | 1450 +++ po/pt/docs/konqueror/index.docbook | 8420 ++++++++++++++++ po/pt/docs/konqueror/introduction.docbook | 95 + po/pt/docs/konqueror/path-complete.docbook | 165 + po/pt/docs/konqueror/plugins.docbook | 874 ++ po/pt/docs/konqueror/save-settings.docbook | 167 + po/pt/docs/konqueror/sidebar.docbook | 391 + po/pt/docs/konqueror/view-extensions.docbook | 177 + po/pt/fsview.po | 429 + po/pt/imgalleryplugin.po | 282 + po/pt/kcmbookmarks.po | 228 + po/pt/kcmkonq.po | 92 + po/pt/kcmkonqhtml.po | 2488 +++++ po/pt/kcmperformance.po | 147 + po/pt/kfmclient.po | 137 + po/pt/khtmlsettingsplugin.po | 111 + po/pt/khtmltts.po | 42 + po/pt/konqueror.po | 2234 ++++ po/pt/kshellcmdplugin.po | 99 + po/pt/libkonq.po | 215 + po/pt/searchbarplugin.po | 83 + po/pt/uachangerplugin.po | 100 + po/pt/webenginepart.po | 1318 +++ po/pt_BR/akregator_konqplugin.po | 65 + po/pt_BR/autorefresh.po | 101 + po/pt_BR/babelfish.po | 233 + po/pt_BR/dirfilterplugin.po | 77 + .../docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 103 + po/pt_BR/docs/kcontrol5/history/index.docbook | 95 + po/pt_BR/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 114 + .../kcontrol5/khtml-behavior/index.docbook | 121 + .../kcontrol5/khtml-general/index.docbook | 216 + .../kcontrol5/khtml-java-js/index.docbook | 176 + .../docs/kcontrol5/performance/index.docbook | 181 + po/pt_BR/docs/konqueror/cmndline.png | Bin 0 -> 33651 bytes po/pt_BR/docs/konqueror/dirtree.png | Bin 0 -> 54312 bytes po/pt_BR/docs/konqueror/dragdrop.png | Bin 0 -> 40032 bytes po/pt_BR/docs/konqueror/folders.png | Bin 0 -> 40743 bytes po/pt_BR/docs/konqueror/index.docbook | 8624 ++++++++++++++++ po/pt_BR/docs/konqueror/konqorg.png | Bin 0 -> 82688 bytes po/pt_BR/docs/konqueror/look.png | Bin 0 -> 42932 bytes po/pt_BR/docs/konqueror/parts.png | Bin 0 -> 36183 bytes po/pt_BR/docs/konqueror/shortcut1.png | Bin 0 -> 33947 bytes po/pt_BR/docs/konqueror/shortcut2.png | Bin 0 -> 33958 bytes po/pt_BR/docs/konqueror/thumbnails.png | Bin 0 -> 33988 bytes .../docs/konqueror/viewproperties-dialog.png | Bin 0 -> 39544 bytes po/pt_BR/fsview.po | 441 + po/pt_BR/imgalleryplugin.po | 291 + po/pt_BR/kcmbookmarks.po | 1363 +++ po/pt_BR/kcmkonq.po | 99 + po/pt_BR/kcmkonqhtml.po | 2479 +++++ po/pt_BR/kcmperformance.po | 223 + po/pt_BR/kfmclient.po | 142 + po/pt_BR/khtmlsettingsplugin.po | 122 + po/pt_BR/khtmltts.po | 51 + po/pt_BR/konqueror.po | 2202 ++++ po/pt_BR/kshellcmdplugin.po | 1886 ++++ po/pt_BR/libkonq.po | 225 + po/pt_BR/searchbarplugin.po | 91 + po/pt_BR/uachangerplugin.po | 108 + po/pt_BR/webenginepart.po | 1314 +++ po/ro/akregator_konqplugin.po | 68 + po/ro/autorefresh.po | 98 + po/ro/babelfish.po | 244 + po/ro/dirfilterplugin.po | 101 + po/ro/fsview.po | 438 + po/ro/imgalleryplugin.po | 287 + po/ro/kcmbookmarks.po | 1921 ++++ po/ro/kcmkonq.po | 694 ++ po/ro/kcmkonqhtml.po | 2542 +++++ po/ro/kcmperformance.po | 237 + po/ro/kfmclient.po | 334 + po/ro/khtmlsettingsplugin.po | 130 + po/ro/khtmltts.po | 64 + po/ro/konqueror.po | 2791 +++++ po/ro/kshellcmdplugin.po | 1982 ++++ po/ro/libkonq.po | 359 + po/ro/searchbarplugin.po | 88 + po/ro/uachangerplugin.po | 107 + po/ro/webenginepart.po | 1412 +++ po/ru/akregator_konqplugin.po | 69 + po/ru/autorefresh.po | 102 + po/ru/babelfish.po | 256 + po/ru/dirfilterplugin.po | 118 + po/ru/docs/konqueror/basics.docbook | 578 ++ po/ru/docs/konqueror/bookmarks.docbook | 245 + po/ru/docs/konqueror/browser.docbook | 594 ++ po/ru/docs/konqueror/cmndline.png | Bin 0 -> 13869 bytes po/ru/docs/konqueror/commands.docbook | 2133 ++++ po/ru/docs/konqueror/config.docbook | 203 + po/ru/docs/konqueror/credits.docbook | 361 + po/ru/docs/konqueror/dirtree.png | Bin 0 -> 18238 bytes po/ru/docs/konqueror/dragdrop.png | Bin 0 -> 16254 bytes po/ru/docs/konqueror/faq.docbook | 301 + po/ru/docs/konqueror/filemanager.docbook | 1433 +++ po/ru/docs/konqueror/index.docbook | 173 + po/ru/docs/konqueror/introduction.docbook | 109 + po/ru/docs/konqueror/konqorg.png | Bin 0 -> 26645 bytes po/ru/docs/konqueror/parts.png | Bin 0 -> 14228 bytes po/ru/docs/konqueror/path-complete.docbook | 152 + po/ru/docs/konqueror/plugins.docbook | 292 + po/ru/docs/konqueror/save-settings.docbook | 170 + po/ru/docs/konqueror/shortcut1.png | Bin 0 -> 12514 bytes po/ru/docs/konqueror/shortcut2.png | Bin 0 -> 5971 bytes po/ru/docs/konqueror/sidebar.docbook | 326 + po/ru/fsview.po | 448 + po/ru/imgalleryplugin.po | 289 + po/ru/kcmbookmarks.po | 1910 ++++ po/ru/kcmkonq.po | 275 + po/ru/kcmkonqhtml.po | 2588 +++++ po/ru/kcmperformance.po | 226 + po/ru/kfmclient.po | 179 + po/ru/khtmlsettingsplugin.po | 131 + po/ru/khtmltts.po | 70 + po/ru/konqueror.po | 2712 +++++ po/ru/kshellcmdplugin.po | 1956 ++++ po/ru/libkonq.po | 393 + po/ru/searchbarplugin.po | 97 + po/ru/uachangerplugin.po | 113 + po/ru/webenginepart.po | 1459 +++ po/sk/akregator_konqplugin.po | 64 + po/sk/autorefresh.po | 93 + po/sk/babelfish.po | 229 + po/sk/dirfilterplugin.po | 76 + po/sk/fsview.po | 432 + po/sk/imgalleryplugin.po | 283 + po/sk/kcmbookmarks.po | 1329 +++ po/sk/kcmkonq.po | 97 + po/sk/kcmkonqhtml.po | 2510 +++++ po/sk/kcmperformance.po | 209 + po/sk/kfmclient.po | 161 + po/sk/khtmlsettingsplugin.po | 115 + po/sk/khtmltts.po | 45 + po/sk/konqueror.po | 2561 +++++ po/sk/kshellcmdplugin.po | 66 + po/sk/libkonq.po | 220 + po/sk/searchbarplugin.po | 84 + po/sk/uachangerplugin.po | 104 + po/sk/webenginepart.po | 1376 +++ po/sl/akregator_konqplugin.po | 71 + po/sl/autorefresh.po | 100 + po/sl/babelfish.po | 233 + po/sl/dirfilterplugin.po | 80 + po/sl/docs/konqueror/cmndline.png | Bin 0 -> 20746 bytes po/sl/docs/konqueror/dirtree.png | Bin 0 -> 18091 bytes po/sl/docs/konqueror/dragdrop.png | Bin 0 -> 16657 bytes po/sl/docs/konqueror/filetype1.png | Bin 0 -> 10276 bytes po/sl/docs/konqueror/filetype3.png | Bin 0 -> 16708 bytes po/sl/docs/konqueror/filetype4.png | Bin 0 -> 9139 bytes po/sl/docs/konqueror/konqdoc5.png | Bin 0 -> 8325 bytes po/sl/docs/konqueror/konqdoc9.png | Bin 0 -> 6918 bytes po/sl/docs/konqueror/konqorg.png | Bin 0 -> 31203 bytes po/sl/docs/konqueror/parts.png | Bin 0 -> 20698 bytes po/sl/docs/konqueror/samba.png | Bin 0 -> 24130 bytes po/sl/fsview.po | 441 + po/sl/imgalleryplugin.po | 291 + po/sl/kcmbookmarks.po | 1354 +++ po/sl/kcmkonq.po | 102 + po/sl/kcmkonqhtml.po | 2530 +++++ po/sl/kcmperformance.po | 211 + po/sl/kfmclient.po | 170 + po/sl/khtmlsettingsplugin.po | 122 + po/sl/khtmltts.po | 49 + po/sl/konqueror.po | 2583 +++++ po/sl/kshellcmdplugin.po | 72 + po/sl/libkonq.po | 226 + po/sl/searchbarplugin.po | 89 + po/sl/uachangerplugin.po | 107 + po/sl/webenginepart.po | 1373 +++ po/sr/akregator_konqplugin.po | 69 + po/sr/autorefresh.po | 111 + po/sr/babelfish.po | 251 + po/sr/dirfilterplugin.po | 80 + po/sr/docs/kcontrol5/bookmarks/index.docbook | 170 + .../docs/kcontrol5/filemanager/index.docbook | 121 + po/sr/docs/kcontrol5/kcmcss/index.docbook | 466 + .../kcontrol5/khtml-adblock/index.docbook | 124 + .../kcontrol5/khtml-behavior/index.docbook | 146 + .../kcontrol5/khtml-general/index.docbook | 218 + .../kcontrol5/khtml-java-js/index.docbook | 189 + .../docs/kcontrol5/performance/index.docbook | 99 + po/sr/docs/konqueror/basics.docbook | 668 ++ po/sr/docs/konqueror/bookmarks.docbook | 223 + po/sr/docs/konqueror/browser.docbook | 886 ++ po/sr/docs/konqueror/commands.docbook | 2568 +++++ po/sr/docs/konqueror/config.docbook | 362 + po/sr/docs/konqueror/credits.docbook | 697 ++ po/sr/docs/konqueror/faq.docbook | 337 + po/sr/docs/konqueror/filemanager.docbook | 1541 +++ po/sr/docs/konqueror/index.docbook | 8361 +++++++++++++++ po/sr/docs/konqueror/introduction.docbook | 101 + po/sr/docs/konqueror/l10n-track | 18 + po/sr/docs/konqueror/path-complete.docbook | 197 + po/sr/docs/konqueror/plugins.docbook | 889 ++ po/sr/docs/konqueror/save-settings.docbook | 181 + po/sr/docs/konqueror/sidebar.docbook | 387 + po/sr/docs/konqueror/view-extensions.docbook | 189 + po/sr/fsview.po | 436 + po/sr/imgalleryplugin.po | 289 + po/sr/kcmbookmarks.po | 166 + po/sr/kcmkonq.po | 100 + po/sr/kcmkonqhtml.po | 2434 +++++ po/sr/kcmperformance.po | 149 + po/sr/kfmclient.po | 136 + po/sr/khtmlsettingsplugin.po | 119 + po/sr/khtmltts.po | 36 + po/sr/konqueror.po | 2327 +++++ po/sr/kshellcmdplugin.po | 69 + po/sr/libkonq.po | 93 + po/sr/searchbarplugin.po | 85 + po/sr/uachangerplugin.po | 114 + po/sr/webenginepart.po | 813 ++ po/sv/akregator_konqplugin.po | 62 + po/sv/autorefresh.po | 99 + po/sv/babelfish.po | 246 + po/sv/dirfilterplugin.po | 98 + po/sv/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 103 + po/sv/docs/kcontrol5/history/index.docbook | 95 + po/sv/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 106 + .../kcontrol5/khtml-behavior/index.docbook | 128 + .../kcontrol5/khtml-general/index.docbook | 196 + .../kcontrol5/khtml-java-js/index.docbook | 175 + .../docs/kcontrol5/performance/index.docbook | 77 + po/sv/docs/konqueror/cmndline.png | Bin 0 -> 45400 bytes po/sv/docs/konqueror/dirtree.png | Bin 0 -> 41981 bytes po/sv/docs/konqueror/dragdrop.png | Bin 0 -> 44449 bytes po/sv/docs/konqueror/index.docbook | 7401 ++++++++++++++ po/sv/docs/konqueror/konqorg.png | Bin 0 -> 52374 bytes po/sv/docs/konqueror/parts.png | Bin 0 -> 48061 bytes po/sv/docs/konqueror/shortcut1.png | Bin 0 -> 21731 bytes po/sv/docs/konqueror/shortcut2.png | Bin 0 -> 14049 bytes po/sv/fsview.po | 432 + po/sv/imgalleryplugin.po | 286 + po/sv/kcmbookmarks.po | 1966 ++++ po/sv/kcmkonq.po | 261 + po/sv/kcmkonqhtml.po | 2574 +++++ po/sv/kcmperformance.po | 213 + po/sv/kfmclient.po | 338 + po/sv/khtmlsettingsplugin.po | 118 + po/sv/khtmltts.po | 58 + po/sv/konqueror.po | 2659 +++++ po/sv/kshellcmdplugin.po | 1922 ++++ po/sv/libkonq.po | 240 + po/sv/searchbarplugin.po | 88 + po/sv/uachangerplugin.po | 104 + po/sv/webenginepart.po | 1353 +++ po/tr/akregator_konqplugin.po | 72 + po/tr/autorefresh.po | 100 + po/tr/babelfish.po | 236 + po/tr/dirfilterplugin.po | 82 + po/tr/fsview.po | 436 + po/tr/imgalleryplugin.po | 288 + po/tr/kcmbookmarks.po | 1341 +++ po/tr/kcmkonq.po | 102 + po/tr/kcmkonqhtml.po | 2452 +++++ po/tr/kcmperformance.po | 213 + po/tr/kfmclient.po | 170 + po/tr/khtmlsettingsplugin.po | 119 + po/tr/khtmltts.po | 51 + po/tr/konqueror.po | 2567 +++++ po/tr/kshellcmdplugin.po | 74 + po/tr/libkonq.po | 222 + po/tr/searchbarplugin.po | 90 + po/tr/uachangerplugin.po | 109 + po/tr/webenginepart.po | 1378 +++ po/ug/akregator_konqplugin.po | 66 + po/ug/autorefresh.po | 95 + po/ug/babelfish.po | 225 + po/ug/dirfilterplugin.po | 85 + po/ug/fsview.po | 426 + po/ug/imgalleryplugin.po | 283 + po/ug/kcmbookmarks.po | 782 ++ po/ug/kcmkonq.po | 94 + po/ug/kcmkonqhtml.po | 2225 ++++ po/ug/kcmperformance.po | 127 + po/ug/kfmclient.po | 121 + po/ug/khtmlsettingsplugin.po | 118 + po/ug/khtmltts.po | 46 + po/ug/konqueror.po | 2318 +++++ po/ug/kshellcmdplugin.po | 61 + po/ug/libkonq.po | 215 + po/ug/searchbarplugin.po | 87 + po/ug/uachangerplugin.po | 104 + po/ug/webenginepart.po | 1374 +++ po/uk/akregator_konqplugin.po | 67 + po/uk/autorefresh.po | 99 + po/uk/babelfish.po | 251 + po/uk/dirfilterplugin.po | 103 + po/uk/docs/kcontrol5/bookmarks/index.docbook | 166 + .../docs/kcontrol5/filemanager/index.docbook | 101 + po/uk/docs/kcontrol5/history/index.docbook | 95 + po/uk/docs/kcontrol5/kcmcss/index.docbook | 454 + .../kcontrol5/khtml-adblock/index.docbook | 108 + .../kcontrol5/khtml-behavior/index.docbook | 128 + .../kcontrol5/khtml-general/index.docbook | 196 + .../kcontrol5/khtml-java-js/index.docbook | 183 + .../docs/kcontrol5/performance/index.docbook | 77 + po/uk/docs/konqueror/cmndline.png | Bin 0 -> 25311 bytes po/uk/docs/konqueror/dirtree.png | Bin 0 -> 22769 bytes po/uk/docs/konqueror/dragdrop.png | Bin 0 -> 22321 bytes po/uk/docs/konqueror/folders.png | Bin 0 -> 19112 bytes po/uk/docs/konqueror/index.docbook | 7414 ++++++++++++++ po/uk/docs/konqueror/konqorg.png | Bin 0 -> 36030 bytes po/uk/docs/konqueror/look.png | Bin 0 -> 19536 bytes po/uk/docs/konqueror/parts.png | Bin 0 -> 25975 bytes po/uk/docs/konqueror/shortcut1.png | Bin 0 -> 25464 bytes po/uk/docs/konqueror/shortcut2.png | Bin 0 -> 19863 bytes po/uk/docs/konqueror/thumbnails.png | Bin 0 -> 14682 bytes .../docs/konqueror/viewproperties-dialog.png | Bin 0 -> 18211 bytes po/uk/fsview.po | 439 + po/uk/imgalleryplugin.po | 288 + po/uk/kcmbookmarks.po | 1993 ++++ po/uk/kcmkonq.po | 251 + po/uk/kcmkonqhtml.po | 2577 +++++ po/uk/kcmperformance.po | 223 + po/uk/kfmclient.po | 338 + po/uk/khtmlsettingsplugin.po | 121 + po/uk/khtmltts.po | 60 + po/uk/konqueror.po | 2704 +++++ po/uk/kshellcmdplugin.po | 1964 ++++ po/uk/libkonq.po | 262 + po/uk/searchbarplugin.po | 92 + po/uk/uachangerplugin.po | 109 + po/uk/webenginepart.po | 1365 +++ po/wa/akregator_konqplugin.po | 68 + po/wa/autorefresh.po | 96 + po/wa/babelfish.po | 227 + po/wa/dirfilterplugin.po | 86 + po/wa/fsview.po | 432 + po/wa/imgalleryplugin.po | 288 + po/wa/kcmbookmarks.po | 1224 +++ po/wa/kcmkonq.po | 415 + po/wa/kcmkonqhtml.po | 2242 +++++ po/wa/kcmperformance.po | 146 + po/wa/kfmclient.po | 132 + po/wa/khtmltts.po | 68 + po/wa/konqueror.po | 2839 ++++++ po/wa/kshellcmdplugin.po | 2027 ++++ po/wa/libkonq.po | 235 + po/wa/uachangerplugin.po | 104 + po/zh_CN/akregator_konqplugin.po | 62 + po/zh_CN/autorefresh.po | 97 + po/zh_CN/babelfish.po | 230 + po/zh_CN/dirfilterplugin.po | 78 + po/zh_CN/fsview.po | 421 + po/zh_CN/imgalleryplugin.po | 281 + po/zh_CN/kcmbookmarks.po | 165 + po/zh_CN/kcmkonq.po | 99 + po/zh_CN/kcmkonqhtml.po | 2300 +++++ po/zh_CN/kcmperformance.po | 143 + po/zh_CN/kfmclient.po | 134 + po/zh_CN/khtmlsettingsplugin.po | 119 + po/zh_CN/khtmltts.po | 37 + po/zh_CN/konqueror.po | 1802 ++++ po/zh_CN/kshellcmdplugin.po | 71 + po/zh_CN/libkonq.po | 92 + po/zh_CN/searchbarplugin.po | 78 + po/zh_CN/uachangerplugin.po | 108 + po/zh_CN/webenginepart.po | 1274 +++ po/zh_TW/akregator_konqplugin.po | 61 + po/zh_TW/autorefresh.po | 97 + po/zh_TW/babelfish.po | 229 + po/zh_TW/dirfilterplugin.po | 76 + po/zh_TW/fsview.po | 417 + po/zh_TW/imgalleryplugin.po | 270 + po/zh_TW/kcmbookmarks.po | 162 + po/zh_TW/kcmkonq.po | 98 + po/zh_TW/kcmkonqhtml.po | 2308 +++++ po/zh_TW/kcmperformance.po | 143 + po/zh_TW/kfmclient.po | 133 + po/zh_TW/khtmlsettingsplugin.po | 116 + po/zh_TW/khtmltts.po | 36 + po/zh_TW/konqueror.po | 2114 ++++ po/zh_TW/kshellcmdplugin.po | 70 + po/zh_TW/libkonq.po | 96 + po/zh_TW/searchbarplugin.po | 77 + po/zh_TW/uachangerplugin.po | 105 + po/zh_TW/webenginepart.po | 1258 +++ settings/CMakeLists.txt | 4 + settings/bookmarks/CMakeLists.txt | 22 + settings/bookmarks/Messages.sh | 3 + settings/bookmarks/bookmarks.cpp | 113 + settings/bookmarks/bookmarks.desktop | 238 + settings/bookmarks/bookmarks.h | 50 + settings/bookmarks/bookmarks.ui | 200 + settings/bookmarks/main.cpp | 37 + settings/konq/CMakeLists.txt | 22 + settings/konq/Messages.sh | 2 + settings/konq/README | 19 + settings/konq/behaviour.cpp | 144 + settings/konq/behaviour.h | 54 + settings/konq/fileappearance.desktop | 246 + settings/konq/filebehavior.desktop | 246 + settings/konq/kcustommenueditor.cpp | 252 + settings/konq/kcustommenueditor.h | 65 + settings/konq/konqkcmfactory.cpp | 32 + settings/konq/konqkcmfactory.h | 27 + settings/konq/onlyone.png | Bin 0 -> 9507 bytes settings/konq/overlapping.png | Bin 0 -> 10105 bytes settings/konq/tests/kcustommenueditortest.cpp | 21 + settings/konq/webappearance.desktop | 247 + settings/konq/webbehavior.desktop | 247 + settings/konqhtml/CMakeLists.txt | 45 + settings/konqhtml/Messages.sh | 3 + settings/konqhtml/advancedTabOptions.ui | 140 + settings/konqhtml/appearance.cpp | 439 + settings/konqhtml/appearance.h | 85 + settings/konqhtml/css/cssconfig.ui | 226 + settings/konqhtml/css/csscustom.ui | 448 + settings/konqhtml/css/kcmcss.cpp | 358 + settings/konqhtml/css/kcmcss.desktop | 248 + settings/konqhtml/css/kcmcss.h | 74 + settings/konqhtml/css/template.cpp | 67 + settings/konqhtml/css/template.css | 77 + settings/konqhtml/css/template.h | 22 + settings/konqhtml/domainlistview.cpp | 231 + settings/konqhtml/domainlistview.h | 228 + settings/konqhtml/filteropts.cpp | 586 ++ settings/konqhtml/filteropts.h | 123 + settings/konqhtml/generalopts.cpp | 287 + settings/konqhtml/generalopts.h | 48 + settings/konqhtml/htmlopts.cpp | 246 + settings/konqhtml/htmlopts.h | 57 + settings/konqhtml/javaopts.cpp | 343 + settings/konqhtml/javaopts.h | 118 + settings/konqhtml/jsopts.cpp | 238 + settings/konqhtml/jsopts.h | 82 + settings/konqhtml/jspolicies.cpp | 426 + settings/konqhtml/jspolicies.h | 272 + settings/konqhtml/khtml_appearance.desktop | 228 + settings/konqhtml/khtml_behavior.desktop | 243 + settings/konqhtml/khtml_filter.desktop | 196 + settings/konqhtml/khtml_general.desktop | 218 + settings/konqhtml/khtml_java_js.desktop | 248 + settings/konqhtml/khttpoptdlg.cpp | 78 + settings/konqhtml/khttpoptdlg.h | 54 + settings/konqhtml/main.cpp | 144 + settings/konqhtml/main.h | 58 + settings/konqhtml/nsconfigwidget.ui | 170 + settings/konqhtml/pluginopts.cpp | 698 ++ settings/konqhtml/pluginopts.h | 176 + settings/konqhtml/policies.cpp | 86 + settings/konqhtml/policies.h | 138 + settings/konqhtml/policydlg.cpp | 146 + settings/konqhtml/policydlg.h | 136 + settings/performance/CMakeLists.txt | 22 + settings/performance/Messages.sh | 3 + .../performance/kcmkonqyperformance.desktop | 245 + settings/performance/kcmperformance.cpp | 107 + settings/performance/kcmperformance.desktop | 243 + settings/performance/kcmperformance.h | 59 + settings/performance/konqueror.cpp | 78 + settings/performance/konqueror.h | 52 + settings/performance/konqueror_ui.ui | 57 + settings/performance/system.cpp | 74 + settings/performance/system.h | 53 + settings/performance/system_ui.ui | 51 + sidebar/CMakeLists.txt | 46 + sidebar/default_entries/CMakeLists.txt | 9 + sidebar/default_entries/bookmarks.desktop | 192 + sidebar/default_entries/history.desktop | 189 + sidebar/default_entries/home.desktop | 191 + sidebar/default_entries/places.desktop | 146 + sidebar/default_entries/remote.desktop | 99 + sidebar/default_entries/root.desktop | 190 + sidebar/default_entries/services.desktop | 100 + sidebar/history_module/CMakeLists.txt | 25 + sidebar/history_module/history_dlg.ui | 191 + sidebar/history_module/history_module.cpp | 158 + sidebar/history_module/history_module.h | 49 + sidebar/history_module/kcmhistory.cpp | 265 + sidebar/history_module/kcmhistory.desktop | 246 + sidebar/history_module/kcmhistory.h | 74 + .../konqsidebar_history.desktop | 74 + sidebar/konq_sidebartng.desktop | 85 + sidebar/konqmultitabbar.cpp | 51 + sidebar/konqmultitabbar.h | 44 + sidebar/konqsidebarplugin.cpp | 110 + sidebar/konqsidebarplugin.h | 214 + sidebar/konqsidebartngrc | 7 + sidebar/module_manager.cpp | 239 + sidebar/module_manager.h | 83 + sidebar/places_module/CMakeLists.txt | 15 + .../places_module/konqsidebar_places.desktop | 70 + sidebar/places_module/places_module.cpp | 148 + sidebar/places_module/places_module.h | 71 + sidebar/sidebar_part.cpp | 85 + sidebar/sidebar_part.h | 103 + sidebar/sidebar_widget.cpp | 849 ++ sidebar/sidebar_widget.h | 215 + sidebar/test/CMakeLists.txt | 19 + sidebar/test/konqsidebartest.cpp | 26 + sidebar/test/konqsidebartest.h | 46 + sidebar/test/modulemanagertest.cpp | 222 + sidebar/test/test.desktop | 99 + sidebar/trees/CMakeLists.txt | 27 + sidebar/trees/bookmark_module/CMakeLists.txt | 14 + .../trees/bookmark_module/bookmark_item.cpp | 81 + sidebar/trees/bookmark_module/bookmark_item.h | 61 + .../trees/bookmark_module/bookmark_module.cpp | 630 ++ .../trees/bookmark_module/bookmark_module.h | 95 + sidebar/trees/dirtree_module/CMakeLists.txt | 17 + sidebar/trees/dirtree_module/dirtree_item.cpp | 323 + sidebar/trees/dirtree_module/dirtree_item.h | 79 + .../trees/dirtree_module/dirtree_module.cpp | 619 ++ sidebar/trees/dirtree_module/dirtree_module.h | 79 + sidebar/trees/init/CMakeLists.txt | 7 + sidebar/trees/init/README | 6 + sidebar/trees/init/bookmarks_module.desktop | 192 + sidebar/trees/init/dirtree_module.desktop | 102 + sidebar/trees/init/remote/.directory | 95 + sidebar/trees/init/remote/CMakeLists.txt | 6 + sidebar/trees/init/remote/ftp/.directory | 88 + sidebar/trees/init/remote/ftp/CMakeLists.txt | 1 + sidebar/trees/init/remote/ftp/kde_ftp.desktop | 98 + sidebar/trees/init/remote/web/.directory | 89 + sidebar/trees/init/remote/web/CMakeLists.txt | 1 + .../trees/init/remote/web/apps_web.desktop | 99 + sidebar/trees/init/remote/web/dot_web.desktop | 99 + sidebar/trees/init/remote/web/kde_web.desktop | 98 + .../trees/init/remote/web/look_web.desktop | 91 + sidebar/trees/init/services/.directory | 95 + sidebar/trees/init/services/CMakeLists.txt | 8 + .../trees/init/services/applications.desktop | 98 + .../trees/init/services/printsystem.desktop | 98 + sidebar/trees/init/services/settings.desktop | 99 + sidebar/trees/konq_sidebartree.cpp | 1101 ++ sidebar/trees/konq_sidebartree.h | 236 + sidebar/trees/konq_sidebartreeitem.cpp | 65 + sidebar/trees/konq_sidebartreeitem.h | 143 + sidebar/trees/konq_sidebartreemodule.h | 74 + .../trees/konq_sidebartreetoplevelitem.cpp | 196 + sidebar/trees/konq_sidebartreetoplevelitem.h | 128 + sidebar/trees/konqsidebar_oldtreemodule.cpp | 210 + sidebar/trees/konqsidebar_oldtreemodule.h | 29 + sidebar/trees/konqsidebar_tree.desktop | 96 + sidebar/web_module/CMakeLists.txt | 17 + sidebar/web_module/TODO | 6 + sidebar/web_module/konqsidebar_web.desktop | 93 + sidebar/web_module/test_websidebar.html | 4 + sidebar/web_module/web_module.cpp | 320 + sidebar/web_module/web_module.h | 145 + src/CMakeLists.txt | 129 + src/KonqMainWindowAdaptor.cpp | 131 + src/KonqMainWindowAdaptor.h | 93 + src/KonqViewAdaptor.cpp | 119 + src/KonqViewAdaptor.h | 134 + src/KonquerorAdaptor.cpp | 151 + src/KonquerorAdaptor.h | 106 + src/delayedinitializer.cpp | 53 + src/delayedinitializer.h | 45 + src/htmldefaults.h | 33 + src/konqactions.cpp | 248 + src/konqactions.h | 118 + src/konqanimatedlogo.cpp | 68 + src/konqanimatedlogo_p.h | 49 + src/konqapplication.cpp | 73 + src/konqapplication.h | 43 + src/konqbookmarkbar.cpp | 383 + src/konqbookmarkbar.h | 89 + src/konqbookmarkmenu.cpp | 338 + src/konqbookmarkmenu.h | 121 + src/konqbookmarkmenu_p.h | 96 + src/konqcloseditem.cpp | 165 + src/konqcloseditem.h | 136 + src/konqclosedwindowsmanager.cpp | 432 + src/konqclosedwindowsmanager.h | 167 + src/konqcombo.cpp | 907 ++ src/konqcombo.h | 122 + src/konqdraggablelabel.cpp | 93 + src/konqdraggablelabel.h | 48 + src/konqextendedbookmarkowner.h | 44 + src/konqextensionmanager.cpp | 158 + src/konqextensionmanager.h | 62 + src/konqfactory.cpp | 216 + src/konqfactory.h | 90 + src/konqframe.cpp | 265 + src/konqframe.h | 224 + src/konqframecontainer.cpp | 233 + src/konqframecontainer.h | 171 + src/konqframestatusbar.cpp | 303 + src/konqframestatusbar.h | 104 + src/konqframevisitor.cpp | 68 + src/konqframevisitor.h | 153 + src/konqguiclients.cpp | 302 + src/konqguiclients.h | 98 + src/konqhistory.h | 42 + src/konqhistorydialog.cpp | 122 + src/konqhistorydialog.h | 50 + src/konqhistorymanager.cpp | 283 + src/konqhistorymanager.h | 190 + src/konqhistorymodel.cpp | 472 + src/konqhistorymodel.h | 69 + src/konqhistoryproxymodel.cpp | 120 + src/konqhistoryproxymodel.h | 54 + src/konqhistorysettings.cpp | 110 + src/konqhistorysettings.h | 94 + src/konqhistoryview.cpp | 259 + src/konqhistoryview.h | 83 + src/konqmain.cpp | 301 + src/konqmainwindow.cpp | 5503 ++++++++++ src/konqmainwindow.h | 711 ++ src/konqmainwindowfactory.cpp | 87 + src/konqmainwindowfactory.h | 50 + src/konqmisc.cpp | 116 + src/konqmisc.h | 61 + src/konqmouseeventfilter.cpp | 134 + src/konqmouseeventfilter.h | 47 + src/konqnewsessiondlg_base.ui | 81 + src/konqopenurlrequest.h | 100 + src/konqpixmapprovider.cpp | 196 + src/konqpixmapprovider.h | 88 + src/konqprivate_export.h | 34 + src/konqrun.cpp | 233 + src/konqrun.h | 84 + src/konqsessiondlg.cpp | 289 + src/konqsessiondlg.h | 73 + src/konqsessiondlg_base.ui | 81 + src/konqsessionmanager.cpp | 703 ++ src/konqsessionmanager.h | 233 + src/konqsettings.cpp | 137 + src/konqsettings.h | 80 + src/konqsettingsxt.kcfgc | 7 + src/konqstatusbarmessagelabel.cpp | 405 + src/konqstatusbarmessagelabel.h | 134 + src/konqtabs.cpp | 626 ++ src/konqtabs.h | 198 + src/konqueror.kcfg | 531 + src/konqueror.qrc | 5 + src/konqueror.rc | 126 + src/konqundomanager.cpp | 311 + src/konqundomanager.h | 115 + src/konqurl.cpp | 81 + src/konqurl.h | 63 + src/konqview.cpp | 1432 +++ src/konqview.h | 666 ++ src/konqviewmanager.cpp | 1455 +++ src/konqviewmanager.h | 364 + src/ksortfilterproxymodel.cpp | 94 + src/ksortfilterproxymodel.h | 61 + src/ktabbar.cpp | 231 + src/ktabbar.h | 111 + src/ktabwidget.cpp | 524 + src/ktabwidget.h | 176 + src/org.kde.Konqueror.HistoryManager.xml | 22 + src/org.kde.Konqueror.Main.xml | 37 + src/org.kde.Konqueror.MainWindow.xml | 33 + src/org.kde.Konqueror.SessionManager.xml | 8 + src/org.kde.Konqueror.UndoManager.xml | 15 + src/tests/CMakeLists.txt | 12 + src/tests/centralwidget.cpp | 48 + src/tests/centralwidget.h | 34 + webenginepart/CMakeLists.txt | 6 + webenginepart/COPYING.LIB | 486 + webenginepart/Mainpage.dox | 4 + webenginepart/Messages.sh | 4 + webenginepart/README | 40 + webenginepart/TODO | 23 + webenginepart/autotests/CMakeLists.txt | 19 + webenginepart/autotests/data/hello.html | 1 + .../autotests/data/page-with-link.html | 1 + .../autotests/webengine_partapi_test.cpp | 133 + webenginepart/autotests/webengine_testutils.h | 110 + .../autotests/webenginepartcookiejar_test.cpp | 365 + .../autotests/webenginepartcookiejar_test.h | 91 + webenginepart/icons/128-apps-webengine.png | Bin 0 -> 4169 bytes webenginepart/icons/16-apps-webengine.png | Bin 0 -> 716 bytes webenginepart/icons/22-apps-webengine.png | Bin 0 -> 916 bytes webenginepart/icons/32-apps-webengine.png | Bin 0 -> 1334 bytes webenginepart/icons/48-apps-webengine.png | Bin 0 -> 1880 bytes webenginepart/icons/64-apps-webengine.png | Bin 0 -> 2365 bytes webenginepart/icons/CMakeLists.txt | 11 + webenginepart/icons/webengine.svg | 104 + webenginepart/scripts/codingstyle.sh | 19 + .../scripts/create_release_package.sh | 16 + webenginepart/src/CMakeLists.txt | 87 + webenginepart/src/about/CMakeLists.txt | 10 + webenginepart/src/about/intro.html | 84 + webenginepart/src/about/konq.css | 19 + webenginepart/src/about/konq_aboutpage.cpp | 378 + .../src/about/konq_aboutpage.desktop | 98 + webenginepart/src/about/konq_aboutpage.h | 36 + webenginepart/src/about/konqaboutpage.desktop | 4 + webenginepart/src/about/launch.html | 106 + webenginepart/src/about/plugins.html | 48 + webenginepart/src/about/plugins_rtl.html | 51 + webenginepart/src/about/specs.html | 200 + webenginepart/src/about/tips.html | 122 + .../src/about/top-left-konqueror.png | Bin 0 -> 27425 bytes webenginepart/src/error.html | 62 + .../src/settings/webengine_filter.cpp | 344 + webenginepart/src/settings/webengine_filter.h | 60 + .../src/settings/webenginesettings.cpp | 1286 +++ .../src/settings/webenginesettings.h | 219 + webenginepart/src/ui/featurepermissionbar.cpp | 73 + webenginepart/src/ui/featurepermissionbar.h | 54 + webenginepart/src/ui/passwordbar.cpp | 103 + webenginepart/src/ui/passwordbar.h | 60 + webenginepart/src/ui/searchbar.cpp | 186 + webenginepart/src/ui/searchbar.h | 68 + webenginepart/src/ui/searchbar.ui | 183 + webenginepart/src/utils.h | 18 + webenginepart/src/webenginepage.cpp | 959 ++ webenginepart/src/webenginepage.h | 208 + webenginepart/src/webenginepart.cpp | 1000 ++ webenginepart/src/webenginepart.desktop | 85 + webenginepart/src/webenginepart.h | 175 + webenginepart/src/webenginepart.rc | 35 + webenginepart/src/webenginepart_ext.cpp | 1230 +++ webenginepart/src/webenginepart_ext.h | 201 + webenginepart/src/webenginepartcookiejar.cpp | 362 + webenginepart/src/webenginepartcookiejar.h | 353 + .../src/webenginepartdownloadmanager.cpp | 105 + .../src/webenginepartdownloadmanager.h | 65 + .../src/webengineparterrorschemehandler.cpp | 173 + .../src/webengineparterrorschemehandler.h | 59 + webenginepart/src/webenginepartfactory.cpp | 62 + webenginepart/src/webenginepartfactory.h | 47 + .../src/webengineparthtmlembedder.cpp | 120 + webenginepart/src/webengineparthtmlembedder.h | 178 + webenginepart/src/webenginepartkiohandler.cpp | 121 + webenginepart/src/webenginepartkiohandler.h | 316 + webenginepart/src/webengineview.cpp | 606 ++ webenginepart/src/webengineview.h | 133 + webenginepart/src/webenginewallet.cpp | 598 ++ webenginepart/src/webenginewallet.h | 305 + webenginepart/src/webhistoryinterface.cpp | 38 + webenginepart/src/webhistoryinterface.h | 34 + webenginepart/src/websslinfo.cpp | 224 + webenginepart/src/websslinfo.h | 68 + webenginepart/testfiles/embed_tag_test.html | 20 + .../testfiles/form_save_restore_test.html | 68 + webenginepart/testfiles/frameset_test.html | 9 + .../testfiles/frametest/frame_a.html | 7 + .../testfiles/frametest/frame_b.html | 7 + .../testfiles/frametest/frame_c.html | 7 + .../testfiles/frametest/frame_navigation.html | 9 + webenginepart/testfiles/js.html | 52 + webenginepart/testfiles/link_tests.html | 136 + .../testfiles/meta_tag_refresh_test.html | 14 + webenginepart/tests/CMakeLists.txt | 2 + webenginepart/tests/webenginepart_tester.cpp | 430 + 2044 files changed, 953421 insertions(+) create mode 100644 .arcconfig create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 COPYING.DOC create mode 100644 COPYING.LIB create mode 100644 ChangeLog create mode 100644 DESIGN create mode 100644 DESIGN_config create mode 100644 Messages.sh create mode 100644 autotests/CMakeLists.txt create mode 100644 autotests/historymanagertest.cpp create mode 100644 autotests/konqhtmltest.cpp create mode 100644 autotests/konqviewmgrtest.cpp create mode 100644 autotests/konqviewmgrtest.h create mode 100644 autotests/konqviewtest.cpp create mode 100644 autotests/undomanagertest.cpp create mode 100644 client/CMakeLists.txt create mode 100644 client/ChangeLog create mode 100644 client/Messages.sh create mode 100644 client/kfmclient.cpp create mode 100644 client/kfmclient.h create mode 100644 client/konqclientrequest.cpp create mode 100644 client/konqclientrequest.h create mode 100644 config-konqueror.h.cmake create mode 100644 doc/CMakeLists.txt create mode 100644 doc/kcontrol5/CMakeLists.txt create mode 100644 doc/kcontrol5/bookmarks/CMakeLists.txt create mode 100644 doc/kcontrol5/bookmarks/index.docbook create mode 100644 doc/kcontrol5/filemanager/CMakeLists.txt create mode 100644 doc/kcontrol5/filemanager/index.docbook create mode 100644 doc/kcontrol5/history/CMakeLists.txt create mode 100644 doc/kcontrol5/history/index.docbook create mode 100644 doc/kcontrol5/kcmcss/CMakeLists.txt create mode 100644 doc/kcontrol5/kcmcss/index.docbook create mode 100644 doc/kcontrol5/khtml-adblock/CMakeLists.txt create mode 100644 doc/kcontrol5/khtml-adblock/index.docbook create mode 100644 doc/kcontrol5/khtml-behavior/CMakeLists.txt create mode 100644 doc/kcontrol5/khtml-behavior/index.docbook create mode 100644 doc/kcontrol5/khtml-general/CMakeLists.txt create mode 100644 doc/kcontrol5/khtml-general/index.docbook create mode 100644 doc/kcontrol5/khtml-java-js/CMakeLists.txt create mode 100644 doc/kcontrol5/khtml-java-js/index.docbook create mode 100644 doc/kcontrol5/performance/CMakeLists.txt create mode 100644 doc/kcontrol5/performance/index.docbook create mode 100644 doc/konqueror/CMakeLists.txt create mode 100644 doc/konqueror/cmndline.png create mode 100644 doc/konqueror/dirtree.png create mode 100644 doc/konqueror/dragdrop.png create mode 100644 doc/konqueror/folders.png create mode 100644 doc/konqueror/format-font-size-less.png create mode 100644 doc/konqueror/format-font-size-more.png create mode 100644 doc/konqueror/go-jump.png create mode 100644 doc/konqueror/grouping-view.png create mode 100644 doc/konqueror/index.docbook create mode 100644 doc/konqueror/konqorg.png create mode 100644 doc/konqueror/look.png create mode 100644 doc/konqueror/parts.png create mode 100644 doc/konqueror/reset.png create mode 100644 doc/konqueror/thumbnails.png create mode 100644 doc/konqueror/viewproperties-dialog.png create mode 100755 kfmclient.desktop create mode 100755 kfmclient_dir.desktop create mode 100755 kfmclient_html.desktop create mode 100755 kfmclient_war.desktop create mode 100755 konqbrowser.desktop create mode 100644 konqueror-version.h.cmake create mode 100644 konqueror.categories create mode 100644 konqy_preload.desktop create mode 100644 libkonq/AUTHORS create mode 100644 libkonq/CMakeLists.txt create mode 100644 libkonq/COPYING create mode 100644 libkonq/COPYING.LIB create mode 100644 libkonq/DESIGN create mode 100644 libkonq/KF5KonqConfig.cmake.in create mode 100644 libkonq/Mainpage.dox create mode 100644 libkonq/Messages.sh create mode 100644 libkonq/SERVICEMENUS create mode 100644 libkonq/autotests/CMakeLists.txt create mode 100644 libkonq/autotests/konqpopupmenutest.cpp create mode 100644 libkonq/autotests/konqpopupmenutest.h create mode 100644 libkonq/src/CMakeLists.txt create mode 100644 libkonq/src/directory_bookmarkbar.desktop create mode 100644 libkonq/src/konq_events.cpp create mode 100644 libkonq/src/konq_events.h create mode 100644 libkonq/src/konq_historyentry.cpp create mode 100644 libkonq/src/konq_historyentry.h create mode 100644 libkonq/src/konq_historyloader.cpp create mode 100644 libkonq/src/konq_historyloader_p.h create mode 100644 libkonq/src/konq_historyprovider.cpp create mode 100644 libkonq/src/konq_historyprovider.h create mode 100644 libkonq/src/konq_popupmenu.cpp create mode 100644 libkonq/src/konq_popupmenu.h create mode 100644 org.kde.konqueror.appdata.xml create mode 100644 org.kde.konqueror.desktop create mode 100644 pics/128-apps-konqueror.png create mode 100644 pics/16-apps-konqueror.png create mode 100644 pics/22-apps-konqueror.png create mode 100644 pics/32-apps-konqueror.png create mode 100644 pics/48-apps-konqueror.png create mode 100644 pics/64-apps-konqueror.png create mode 100644 pics/CMakeLists.txt create mode 100644 pics/hisc-app-konqueror.svgz create mode 100644 pics/indicators/CMakeLists.txt create mode 100644 pics/indicators/indicator_connect.png create mode 100644 pics/indicators/indicator_empty.png create mode 100644 pics/indicators/indicator_noconnect.png create mode 100644 pics/indicators/indicator_viewactive.png create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/COPYING create mode 100644 plugins/COPYING.DOC create mode 100644 plugins/COPYING.LIB create mode 100644 plugins/README create mode 100644 plugins/akregator/CMakeLists.txt create mode 100644 plugins/akregator/Messages.sh create mode 100644 plugins/akregator/akregator_konqfeedicon.desktop create mode 100644 plugins/akregator/akregator_konqfeedicon.rc create mode 100644 plugins/akregator/akregator_konqplugin.desktop create mode 100644 plugins/akregator/akregatorplugin.categories create mode 100644 plugins/akregator/akregatorplugin.cpp create mode 100644 plugins/akregator/akregatorplugin.h create mode 100644 plugins/akregator/feed.png create mode 100644 plugins/akregator/feed.svg create mode 100644 plugins/akregator/feeddetector.cpp create mode 100644 plugins/akregator/feeddetector.h create mode 100644 plugins/akregator/konqfeedicon.cpp create mode 100644 plugins/akregator/konqfeedicon.h create mode 100644 plugins/akregator/pluginutil.cpp create mode 100644 plugins/akregator/pluginutil.h create mode 100644 plugins/autorefresh/CMakeLists.txt create mode 100644 plugins/autorefresh/Messages.sh create mode 100644 plugins/autorefresh/autorefresh.cpp create mode 100644 plugins/autorefresh/autorefresh.desktop create mode 100644 plugins/autorefresh/autorefresh.h create mode 100644 plugins/autorefresh/autorefresh.rc create mode 100644 plugins/babelfish/16-actions-babelfish.png create mode 100644 plugins/babelfish/22-actions-babelfish.png create mode 100644 plugins/babelfish/CMakeLists.txt create mode 100644 plugins/babelfish/Messages.sh create mode 100644 plugins/babelfish/plugin_babelfish.cpp create mode 100644 plugins/babelfish/plugin_babelfish.h create mode 100644 plugins/babelfish/plugin_babelfish.rc create mode 100644 plugins/babelfish/plugin_translator.desktop create mode 100644 plugins/babelfish/translaterc create mode 100644 plugins/dirfilter/CMakeLists.txt create mode 100644 plugins/dirfilter/Messages.sh create mode 100644 plugins/dirfilter/dirfilterplugin.cpp create mode 100644 plugins/dirfilter/dirfilterplugin.desktop create mode 100644 plugins/dirfilter/dirfilterplugin.h create mode 100644 plugins/dirfilter/dirfilterplugin.rc create mode 100644 plugins/fsview/22-apps-fsview.png create mode 100644 plugins/fsview/32-apps-fsview.png create mode 100644 plugins/fsview/CMakeLists.txt create mode 100644 plugins/fsview/Messages.sh create mode 100644 plugins/fsview/README create mode 100644 plugins/fsview/fsview.cpp create mode 100644 plugins/fsview/fsview.desktop create mode 100644 plugins/fsview/fsview.h create mode 100644 plugins/fsview/fsview_part.cpp create mode 100644 plugins/fsview/fsview_part.desktop create mode 100644 plugins/fsview/fsview_part.h create mode 100644 plugins/fsview/fsview_part.rc create mode 100644 plugins/fsview/inode.cpp create mode 100644 plugins/fsview/inode.h create mode 100644 plugins/fsview/main.cpp create mode 100644 plugins/fsview/scan.cpp create mode 100644 plugins/fsview/scan.h create mode 100644 plugins/fsview/tests/CMakeLists.txt create mode 100644 plugins/fsview/tests/scantest.cpp create mode 100644 plugins/fsview/treemap.cpp create mode 100644 plugins/fsview/treemap.h create mode 100644 plugins/imagerotation/CMakeLists.txt create mode 100755 plugins/imagerotation/exif.py create mode 100644 plugins/imagerotation/imageconverter.desktop create mode 100755 plugins/imagerotation/jpegorient create mode 100644 plugins/imagerotation/jpegorient.desktop create mode 100755 plugins/imagerotation/orient.py create mode 100644 plugins/khtmlsettingsplugin/CMakeLists.txt create mode 100644 plugins/khtmlsettingsplugin/Messages.sh create mode 100644 plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop create mode 100644 plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc create mode 100644 plugins/khtmlsettingsplugin/settingsplugin.cpp create mode 100644 plugins/khtmlsettingsplugin/settingsplugin.h create mode 100644 plugins/kimgalleryplugin/16-actions-imagegallery.png create mode 100644 plugins/kimgalleryplugin/22-actions-imagegallery.png create mode 100644 plugins/kimgalleryplugin/CMakeLists.txt create mode 100644 plugins/kimgalleryplugin/Messages.sh create mode 100644 plugins/kimgalleryplugin/imgallerydialog.cpp create mode 100644 plugins/kimgalleryplugin/imgallerydialog.h create mode 100644 plugins/kimgalleryplugin/imgalleryplugin.cpp create mode 100644 plugins/kimgalleryplugin/imgalleryplugin.h create mode 100644 plugins/kimgalleryplugin/kimgalleryplugin.desktop create mode 100644 plugins/kimgalleryplugin/kimgalleryplugin.rc create mode 100644 plugins/searchbar/CMakeLists.txt create mode 100644 plugins/searchbar/Messages.sh create mode 100644 plugins/searchbar/OpenSearchManager.cpp create mode 100644 plugins/searchbar/OpenSearchManager.h create mode 100644 plugins/searchbar/SuggestionEngine.cpp create mode 100644 plugins/searchbar/SuggestionEngine.h create mode 100644 plugins/searchbar/WebShortcutWidget.cpp create mode 100644 plugins/searchbar/WebShortcutWidget.h create mode 100644 plugins/searchbar/icons/16-actions-google.png create mode 100644 plugins/searchbar/icons/22-actions-google.png create mode 100644 plugins/searchbar/icons/32-actions-google.png create mode 100644 plugins/searchbar/icons/48-actions-google.png create mode 100644 plugins/searchbar/icons/64-actions-google.png create mode 100644 plugins/searchbar/icons/CMakeLists.txt create mode 100644 plugins/searchbar/icons/sc-actions-google.svgz create mode 100644 plugins/searchbar/opensearch/CMakeLists.txt create mode 100644 plugins/searchbar/opensearch/OpenSearchEngine.cpp create mode 100644 plugins/searchbar/opensearch/OpenSearchEngine.h create mode 100644 plugins/searchbar/opensearch/OpenSearchReader.cpp create mode 100644 plugins/searchbar/opensearch/OpenSearchReader.h create mode 100644 plugins/searchbar/opensearch/OpenSearchWriter.cpp create mode 100644 plugins/searchbar/opensearch/OpenSearchWriter.h create mode 100644 plugins/searchbar/opensearch/engines/CMakeLists.txt create mode 100644 plugins/searchbar/opensearch/engines/google.xml create mode 100644 plugins/searchbar/searchbar.cpp create mode 100644 plugins/searchbar/searchbar.desktop create mode 100644 plugins/searchbar/searchbar.h create mode 100644 plugins/searchbar/searchbar.rc create mode 100644 plugins/shellcmdplugin/CMakeLists.txt create mode 100644 plugins/shellcmdplugin/Messages.sh create mode 100644 plugins/shellcmdplugin/kshellcmddialog.cpp create mode 100644 plugins/shellcmdplugin/kshellcmddialog.h create mode 100644 plugins/shellcmdplugin/kshellcmdexecutor.cpp create mode 100644 plugins/shellcmdplugin/kshellcmdexecutor.h create mode 100644 plugins/shellcmdplugin/kshellcmdplugin.cpp create mode 100644 plugins/shellcmdplugin/kshellcmdplugin.desktop create mode 100644 plugins/shellcmdplugin/kshellcmdplugin.h create mode 100644 plugins/shellcmdplugin/kshellcmdplugin.rc create mode 100644 plugins/ttsplugin/CMakeLists.txt create mode 100644 plugins/ttsplugin/Messages.sh create mode 100644 plugins/ttsplugin/khtmltts.cpp create mode 100644 plugins/ttsplugin/khtmltts.desktop create mode 100644 plugins/ttsplugin/khtmltts.h create mode 100644 plugins/ttsplugin/khtmltts.rc create mode 100644 plugins/uachanger/CMakeLists.txt create mode 100644 plugins/uachanger/Messages.sh create mode 100644 plugins/uachanger/uachangerplugin.cpp create mode 100644 plugins/uachanger/uachangerplugin.desktop create mode 100644 plugins/uachanger/uachangerplugin.h create mode 100644 plugins/uachanger/uachangerplugin.rc create mode 100644 plugins/uninstall.desktop create mode 100644 po/ar/akregator_konqplugin.po create mode 100644 po/ar/autorefresh.po create mode 100644 po/ar/babelfish.po create mode 100644 po/ar/dirfilterplugin.po create mode 100644 po/ar/fsview.po create mode 100644 po/ar/imgalleryplugin.po create mode 100644 po/ar/kcmbookmarks.po create mode 100644 po/ar/kcmkonq.po create mode 100644 po/ar/kcmkonqhtml.po create mode 100644 po/ar/kcmperformance.po create mode 100644 po/ar/kfmclient.po create mode 100644 po/ar/khtmlsettingsplugin.po create mode 100644 po/ar/khtmltts.po create mode 100644 po/ar/konqueror.po create mode 100644 po/ar/kshellcmdplugin.po create mode 100644 po/ar/libkonq.po create mode 100644 po/ar/searchbarplugin.po create mode 100644 po/ar/uachangerplugin.po create mode 100644 po/ar/webenginepart.po create mode 100644 po/ast/akregator_konqplugin.po create mode 100644 po/ast/autorefresh.po create mode 100644 po/ast/babelfish.po create mode 100644 po/ast/dirfilterplugin.po create mode 100644 po/ast/fsview.po create mode 100644 po/ast/imgalleryplugin.po create mode 100644 po/ast/kcmbookmarks.po create mode 100644 po/ast/kcmkonq.po create mode 100644 po/ast/kcmkonqhtml.po create mode 100644 po/ast/kcmperformance.po create mode 100644 po/ast/kfmclient.po create mode 100644 po/ast/khtmlsettingsplugin.po create mode 100644 po/ast/khtmltts.po create mode 100644 po/ast/konqueror.po create mode 100644 po/ast/kshellcmdplugin.po create mode 100644 po/ast/libkonq.po create mode 100644 po/ast/searchbarplugin.po create mode 100644 po/ast/uachangerplugin.po create mode 100644 po/ast/webenginepart.po create mode 100644 po/bg/akregator_konqplugin.po create mode 100644 po/bg/autorefresh.po create mode 100644 po/bg/babelfish.po create mode 100644 po/bg/dirfilterplugin.po create mode 100644 po/bg/fsview.po create mode 100644 po/bg/imgalleryplugin.po create mode 100644 po/bg/kcmbookmarks.po create mode 100644 po/bg/kcmkonq.po create mode 100644 po/bg/kcmkonqhtml.po create mode 100644 po/bg/kcmperformance.po create mode 100644 po/bg/kfmclient.po create mode 100644 po/bg/khtmlsettingsplugin.po create mode 100644 po/bg/khtmltts.po create mode 100644 po/bg/konqueror.po create mode 100644 po/bg/kshellcmdplugin.po create mode 100644 po/bg/libkonq.po create mode 100644 po/bg/searchbarplugin.po create mode 100644 po/bg/uachangerplugin.po create mode 100644 po/bg/webenginepart.po create mode 100644 po/bs/akregator_konqplugin.po create mode 100644 po/bs/autorefresh.po create mode 100644 po/bs/babelfish.po create mode 100644 po/bs/dirfilterplugin.po create mode 100644 po/bs/fsview.po create mode 100644 po/bs/imgalleryplugin.po create mode 100644 po/bs/kcmbookmarks.po create mode 100644 po/bs/kcmkonq.po create mode 100644 po/bs/kcmkonqhtml.po create mode 100644 po/bs/kcmperformance.po create mode 100644 po/bs/kfmclient.po create mode 100644 po/bs/khtmlsettingsplugin.po create mode 100644 po/bs/khtmltts.po create mode 100644 po/bs/konqueror.po create mode 100644 po/bs/kshellcmdplugin.po create mode 100644 po/bs/libkonq.po create mode 100644 po/bs/searchbarplugin.po create mode 100644 po/bs/uachangerplugin.po create mode 100644 po/bs/webenginepart.po create mode 100644 po/ca/akregator_konqplugin.po create mode 100644 po/ca/autorefresh.po create mode 100644 po/ca/babelfish.po create mode 100644 po/ca/dirfilterplugin.po create mode 100644 po/ca/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/ca/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/ca/docs/kcontrol5/history/index.docbook create mode 100644 po/ca/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/ca/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/ca/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/ca/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/ca/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/ca/docs/kcontrol5/performance/index.docbook create mode 100644 po/ca/docs/konqueror/format-font-size-less.png create mode 100644 po/ca/docs/konqueror/format-font-size-more.png create mode 100644 po/ca/docs/konqueror/go-jump.png create mode 100644 po/ca/docs/konqueror/index.docbook create mode 100644 po/ca/docs/konqueror/konqorg.png create mode 100644 po/ca/docs/konqueror/reset.png create mode 100644 po/ca/docs/konqueror/viewproperties-dialog.png create mode 100644 po/ca/fsview.po create mode 100644 po/ca/imgalleryplugin.po create mode 100644 po/ca/kcmbookmarks.po create mode 100644 po/ca/kcmkonq.po create mode 100644 po/ca/kcmkonqhtml.po create mode 100644 po/ca/kcmperformance.po create mode 100644 po/ca/kfmclient.po create mode 100644 po/ca/khtmlsettingsplugin.po create mode 100644 po/ca/khtmltts.po create mode 100644 po/ca/konqueror.po create mode 100644 po/ca/kshellcmdplugin.po create mode 100644 po/ca/libkonq.po create mode 100644 po/ca/searchbarplugin.po create mode 100644 po/ca/uachangerplugin.po create mode 100644 po/ca/webenginepart.po create mode 100644 po/ca@valencia/akregator_konqplugin.po create mode 100644 po/ca@valencia/autorefresh.po create mode 100644 po/ca@valencia/babelfish.po create mode 100644 po/ca@valencia/dirfilterplugin.po create mode 100644 po/ca@valencia/fsview.po create mode 100644 po/ca@valencia/imgalleryplugin.po create mode 100644 po/ca@valencia/kcmbookmarks.po create mode 100644 po/ca@valencia/kcmkonq.po create mode 100644 po/ca@valencia/kcmkonqhtml.po create mode 100644 po/ca@valencia/kcmperformance.po create mode 100644 po/ca@valencia/kfmclient.po create mode 100644 po/ca@valencia/khtmlsettingsplugin.po create mode 100644 po/ca@valencia/khtmltts.po create mode 100644 po/ca@valencia/konqueror.po create mode 100644 po/ca@valencia/kshellcmdplugin.po create mode 100644 po/ca@valencia/libkonq.po create mode 100644 po/ca@valencia/searchbarplugin.po create mode 100644 po/ca@valencia/uachangerplugin.po create mode 100644 po/ca@valencia/webenginepart.po create mode 100644 po/cs/akregator_konqplugin.po create mode 100644 po/cs/autorefresh.po create mode 100644 po/cs/babelfish.po create mode 100644 po/cs/dirfilterplugin.po create mode 100644 po/cs/fsview.po create mode 100644 po/cs/imgalleryplugin.po create mode 100644 po/cs/kcmbookmarks.po create mode 100644 po/cs/kcmkonq.po create mode 100644 po/cs/kcmkonqhtml.po create mode 100644 po/cs/kcmperformance.po create mode 100644 po/cs/kfmclient.po create mode 100644 po/cs/khtmlsettingsplugin.po create mode 100644 po/cs/khtmltts.po create mode 100644 po/cs/konqueror.po create mode 100644 po/cs/kshellcmdplugin.po create mode 100644 po/cs/libkonq.po create mode 100644 po/cs/searchbarplugin.po create mode 100644 po/cs/uachangerplugin.po create mode 100644 po/cs/webenginepart.po create mode 100644 po/da/akregator_konqplugin.po create mode 100644 po/da/autorefresh.po create mode 100644 po/da/babelfish.po create mode 100644 po/da/dirfilterplugin.po create mode 100644 po/da/docs/konqueror/basics.docbook create mode 100644 po/da/docs/konqueror/bookmarks.docbook create mode 100644 po/da/docs/konqueror/browser.docbook create mode 100644 po/da/docs/konqueror/cmndline.png create mode 100644 po/da/docs/konqueror/commands.docbook create mode 100644 po/da/docs/konqueror/config.docbook create mode 100644 po/da/docs/konqueror/credits.docbook create mode 100644 po/da/docs/konqueror/dirtree.png create mode 100644 po/da/docs/konqueror/dragdrop.png create mode 100644 po/da/docs/konqueror/faq.docbook create mode 100644 po/da/docs/konqueror/filemanager.docbook create mode 100644 po/da/docs/konqueror/index.docbook create mode 100644 po/da/docs/konqueror/introduction.docbook create mode 100644 po/da/docs/konqueror/konqorg.png create mode 100644 po/da/docs/konqueror/parts.png create mode 100644 po/da/docs/konqueror/path-complete.docbook create mode 100644 po/da/docs/konqueror/plugins.docbook create mode 100644 po/da/docs/konqueror/save-settings.docbook create mode 100644 po/da/docs/konqueror/shortcut1.png create mode 100644 po/da/docs/konqueror/shortcut2.png create mode 100644 po/da/docs/konqueror/sidebar.docbook create mode 100644 po/da/fsview.po create mode 100644 po/da/imgalleryplugin.po create mode 100644 po/da/kcmbookmarks.po create mode 100644 po/da/kcmkonq.po create mode 100644 po/da/kcmkonqhtml.po create mode 100644 po/da/kcmperformance.po create mode 100644 po/da/kfmclient.po create mode 100644 po/da/khtmlsettingsplugin.po create mode 100644 po/da/khtmltts.po create mode 100644 po/da/konqueror.po create mode 100644 po/da/kshellcmdplugin.po create mode 100644 po/da/libkonq.po create mode 100644 po/da/searchbarplugin.po create mode 100644 po/da/uachangerplugin.po create mode 100644 po/da/webenginepart.po create mode 100644 po/de/akregator_konqplugin.po create mode 100644 po/de/autorefresh.po create mode 100644 po/de/babelfish.po create mode 100644 po/de/dirfilterplugin.po create mode 100644 po/de/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/de/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/de/docs/kcontrol5/history/index.docbook create mode 100644 po/de/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/de/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/de/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/de/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/de/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/de/docs/kcontrol5/performance/index.docbook create mode 100644 po/de/docs/konqueror/cmndline.png create mode 100644 po/de/docs/konqueror/dirtree.png create mode 100644 po/de/docs/konqueror/dragdrop.png create mode 100644 po/de/docs/konqueror/folders.png create mode 100644 po/de/docs/konqueror/index.docbook create mode 100644 po/de/docs/konqueror/konqorg.png create mode 100644 po/de/docs/konqueror/look.png create mode 100644 po/de/docs/konqueror/parts.png create mode 100644 po/de/docs/konqueror/shortcut1.png create mode 100644 po/de/docs/konqueror/shortcut2.png create mode 100644 po/de/docs/konqueror/thumbnails.png create mode 100644 po/de/fsview.po create mode 100644 po/de/imgalleryplugin.po create mode 100644 po/de/kcmbookmarks.po create mode 100644 po/de/kcmkonq.po create mode 100644 po/de/kcmkonqhtml.po create mode 100644 po/de/kcmperformance.po create mode 100644 po/de/kfmclient.po create mode 100644 po/de/khtmlsettingsplugin.po create mode 100644 po/de/khtmltts.po create mode 100644 po/de/konqueror.po create mode 100644 po/de/kshellcmdplugin.po create mode 100644 po/de/libkonq.po create mode 100644 po/de/searchbarplugin.po create mode 100644 po/de/uachangerplugin.po create mode 100644 po/de/webenginepart.po create mode 100644 po/el/akregator_konqplugin.po create mode 100644 po/el/autorefresh.po create mode 100644 po/el/babelfish.po create mode 100644 po/el/dirfilterplugin.po create mode 100644 po/el/docs/konqueror/basics.docbook create mode 100644 po/el/docs/konqueror/bookmarks.docbook create mode 100644 po/el/docs/konqueror/browser.docbook create mode 100644 po/el/docs/konqueror/cmndline.png create mode 100644 po/el/docs/konqueror/commands.docbook create mode 100644 po/el/docs/konqueror/config.docbook create mode 100644 po/el/docs/konqueror/credits.docbook create mode 100644 po/el/docs/konqueror/dirtree.png create mode 100644 po/el/docs/konqueror/dragdrop.png create mode 100644 po/el/docs/konqueror/faq.docbook create mode 100644 po/el/docs/konqueror/filemanager.docbook create mode 100644 po/el/docs/konqueror/folders.png create mode 100644 po/el/docs/konqueror/index.docbook create mode 100644 po/el/docs/konqueror/introduction.docbook create mode 100644 po/el/docs/konqueror/konqorg.png create mode 100644 po/el/docs/konqueror/look.png create mode 100644 po/el/docs/konqueror/parts.png create mode 100644 po/el/docs/konqueror/path-complete.docbook create mode 100644 po/el/docs/konqueror/plugins.docbook create mode 100644 po/el/docs/konqueror/save-settings.docbook create mode 100644 po/el/docs/konqueror/shortcut1.png create mode 100644 po/el/docs/konqueror/shortcut2.png create mode 100644 po/el/docs/konqueror/sidebar.docbook create mode 100644 po/el/docs/konqueror/thumbnails.png create mode 100644 po/el/docs/konqueror/view-extensions.docbook create mode 100644 po/el/docs/konqueror/viewproperties-dialog.png create mode 100644 po/el/fsview.po create mode 100644 po/el/imgalleryplugin.po create mode 100644 po/el/kcmbookmarks.po create mode 100644 po/el/kcmkonq.po create mode 100644 po/el/kcmkonqhtml.po create mode 100644 po/el/kcmperformance.po create mode 100644 po/el/kfmclient.po create mode 100644 po/el/khtmlsettingsplugin.po create mode 100644 po/el/khtmltts.po create mode 100644 po/el/konqueror.po create mode 100644 po/el/kshellcmdplugin.po create mode 100644 po/el/libkonq.po create mode 100644 po/el/searchbarplugin.po create mode 100644 po/el/uachangerplugin.po create mode 100644 po/el/webenginepart.po create mode 100644 po/en_GB/akregator_konqplugin.po create mode 100644 po/en_GB/autorefresh.po create mode 100644 po/en_GB/babelfish.po create mode 100644 po/en_GB/dirfilterplugin.po create mode 100644 po/en_GB/docs/konqueror/basics.docbook create mode 100644 po/en_GB/docs/konqueror/bookmarks.docbook create mode 100644 po/en_GB/docs/konqueror/browser.docbook create mode 100644 po/en_GB/docs/konqueror/commands.docbook create mode 100644 po/en_GB/docs/konqueror/config.docbook create mode 100644 po/en_GB/docs/konqueror/credits.docbook create mode 100644 po/en_GB/docs/konqueror/faq.docbook create mode 100644 po/en_GB/docs/konqueror/filemanager.docbook create mode 100644 po/en_GB/docs/konqueror/index.docbook create mode 100644 po/en_GB/docs/konqueror/introduction.docbook create mode 100644 po/en_GB/docs/konqueror/path-complete.docbook create mode 100644 po/en_GB/docs/konqueror/plugins.docbook create mode 100644 po/en_GB/docs/konqueror/save-settings.docbook create mode 100644 po/en_GB/docs/konqueror/sidebar.docbook create mode 100644 po/en_GB/fsview.po create mode 100644 po/en_GB/imgalleryplugin.po create mode 100644 po/en_GB/kcmbookmarks.po create mode 100644 po/en_GB/kcmkonq.po create mode 100644 po/en_GB/kcmkonqhtml.po create mode 100644 po/en_GB/kcmperformance.po create mode 100644 po/en_GB/kfmclient.po create mode 100644 po/en_GB/khtmlsettingsplugin.po create mode 100644 po/en_GB/khtmltts.po create mode 100644 po/en_GB/konqueror.po create mode 100644 po/en_GB/kshellcmdplugin.po create mode 100644 po/en_GB/libkonq.po create mode 100644 po/en_GB/searchbarplugin.po create mode 100644 po/en_GB/uachangerplugin.po create mode 100644 po/en_GB/webenginepart.po create mode 100644 po/eo/akregator_konqplugin.po create mode 100644 po/eo/autorefresh.po create mode 100644 po/eo/babelfish.po create mode 100644 po/eo/dirfilterplugin.po create mode 100644 po/eo/fsview.po create mode 100644 po/eo/imgalleryplugin.po create mode 100644 po/eo/kcmbookmarks.po create mode 100644 po/eo/kcmkonq.po create mode 100644 po/eo/kcmkonqhtml.po create mode 100644 po/eo/kcmperformance.po create mode 100644 po/eo/kfmclient.po create mode 100644 po/eo/khtmlsettingsplugin.po create mode 100644 po/eo/khtmltts.po create mode 100644 po/eo/konqueror.po create mode 100644 po/eo/kshellcmdplugin.po create mode 100644 po/eo/libkonq.po create mode 100644 po/eo/searchbarplugin.po create mode 100644 po/eo/uachangerplugin.po create mode 100644 po/eo/webenginepart.po create mode 100644 po/es/akregator_konqplugin.po create mode 100644 po/es/autorefresh.po create mode 100644 po/es/babelfish.po create mode 100644 po/es/dirfilterplugin.po create mode 100644 po/es/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/es/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/es/docs/kcontrol5/history/index.docbook create mode 100644 po/es/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/es/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/es/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/es/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/es/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/es/docs/kcontrol5/performance/index.docbook create mode 100644 po/es/docs/konqueror/basics.docbook create mode 100644 po/es/docs/konqueror/bookmarks.docbook create mode 100644 po/es/docs/konqueror/browser.docbook create mode 100644 po/es/docs/konqueror/commands.docbook create mode 100644 po/es/docs/konqueror/config.docbook create mode 100644 po/es/docs/konqueror/credits.docbook create mode 100644 po/es/docs/konqueror/faq.docbook create mode 100644 po/es/docs/konqueror/filemanager.docbook create mode 100644 po/es/docs/konqueror/index.docbook create mode 100644 po/es/docs/konqueror/introduction.docbook create mode 100644 po/es/docs/konqueror/path-complete.docbook create mode 100644 po/es/docs/konqueror/plugins.docbook create mode 100644 po/es/docs/konqueror/save-settings.docbook create mode 100644 po/es/docs/konqueror/sidebar.docbook create mode 100644 po/es/docs/konqueror/view-extensions.docbook create mode 100644 po/es/fsview.po create mode 100644 po/es/imgalleryplugin.po create mode 100644 po/es/kcmbookmarks.po create mode 100644 po/es/kcmkonq.po create mode 100644 po/es/kcmkonqhtml.po create mode 100644 po/es/kcmperformance.po create mode 100644 po/es/kfmclient.po create mode 100644 po/es/khtmlsettingsplugin.po create mode 100644 po/es/khtmltts.po create mode 100644 po/es/konqueror.po create mode 100644 po/es/kshellcmdplugin.po create mode 100644 po/es/libkonq.po create mode 100644 po/es/searchbarplugin.po create mode 100644 po/es/uachangerplugin.po create mode 100644 po/es/webenginepart.po create mode 100644 po/et/akregator_konqplugin.po create mode 100644 po/et/autorefresh.po create mode 100644 po/et/babelfish.po create mode 100644 po/et/dirfilterplugin.po create mode 100644 po/et/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/et/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/et/docs/kcontrol5/history/index.docbook create mode 100644 po/et/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/et/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/et/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/et/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/et/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/et/docs/kcontrol5/performance/index.docbook create mode 100644 po/et/fsview.po create mode 100644 po/et/imgalleryplugin.po create mode 100644 po/et/kcmbookmarks.po create mode 100644 po/et/kcmkonq.po create mode 100644 po/et/kcmkonqhtml.po create mode 100644 po/et/kcmperformance.po create mode 100644 po/et/kfmclient.po create mode 100644 po/et/khtmlsettingsplugin.po create mode 100644 po/et/khtmltts.po create mode 100644 po/et/konqueror.po create mode 100644 po/et/kshellcmdplugin.po create mode 100644 po/et/libkonq.po create mode 100644 po/et/searchbarplugin.po create mode 100644 po/et/uachangerplugin.po create mode 100644 po/et/webenginepart.po create mode 100644 po/eu/akregator_konqplugin.po create mode 100644 po/eu/autorefresh.po create mode 100644 po/eu/babelfish.po create mode 100644 po/eu/dirfilterplugin.po create mode 100644 po/eu/fsview.po create mode 100644 po/eu/imgalleryplugin.po create mode 100644 po/eu/kcmbookmarks.po create mode 100644 po/eu/kcmkonq.po create mode 100644 po/eu/kcmkonqhtml.po create mode 100644 po/eu/kcmperformance.po create mode 100644 po/eu/kfmclient.po create mode 100644 po/eu/khtmlsettingsplugin.po create mode 100644 po/eu/khtmltts.po create mode 100644 po/eu/konqueror.po create mode 100644 po/eu/kshellcmdplugin.po create mode 100644 po/eu/libkonq.po create mode 100644 po/eu/searchbarplugin.po create mode 100644 po/eu/uachangerplugin.po create mode 100644 po/eu/webenginepart.po create mode 100644 po/fa/akregator_konqplugin.po create mode 100644 po/fa/autorefresh.po create mode 100644 po/fa/babelfish.po create mode 100644 po/fa/dirfilterplugin.po create mode 100644 po/fa/fsview.po create mode 100644 po/fa/imgalleryplugin.po create mode 100644 po/fa/kcmbookmarks.po create mode 100644 po/fa/kcmkonq.po create mode 100644 po/fa/kcmkonqhtml.po create mode 100644 po/fa/kcmperformance.po create mode 100644 po/fa/kfmclient.po create mode 100644 po/fa/khtmlsettingsplugin.po create mode 100644 po/fa/khtmltts.po create mode 100644 po/fa/konqueror.po create mode 100644 po/fa/kshellcmdplugin.po create mode 100644 po/fa/libkonq.po create mode 100644 po/fa/searchbarplugin.po create mode 100644 po/fa/uachangerplugin.po create mode 100644 po/fa/webenginepart.po create mode 100644 po/fi/akregator_konqplugin.po create mode 100644 po/fi/autorefresh.po create mode 100644 po/fi/babelfish.po create mode 100644 po/fi/dirfilterplugin.po create mode 100644 po/fi/fsview.po create mode 100644 po/fi/imgalleryplugin.po create mode 100644 po/fi/kcmbookmarks.po create mode 100644 po/fi/kcmkonq.po create mode 100644 po/fi/kcmkonqhtml.po create mode 100644 po/fi/kcmperformance.po create mode 100644 po/fi/kfmclient.po create mode 100644 po/fi/khtmlsettingsplugin.po create mode 100644 po/fi/khtmltts.po create mode 100644 po/fi/konqueror.po create mode 100644 po/fi/kshellcmdplugin.po create mode 100644 po/fi/libkonq.po create mode 100644 po/fi/searchbarplugin.po create mode 100644 po/fi/uachangerplugin.po create mode 100644 po/fi/webenginepart.po create mode 100644 po/fr/akregator_konqplugin.po create mode 100644 po/fr/autorefresh.po create mode 100644 po/fr/babelfish.po create mode 100644 po/fr/dirfilterplugin.po create mode 100644 po/fr/docs/konqueror/basics.docbook create mode 100644 po/fr/docs/konqueror/bookmarks.docbook create mode 100644 po/fr/docs/konqueror/browser.docbook create mode 100644 po/fr/docs/konqueror/cmndline.png create mode 100644 po/fr/docs/konqueror/commands.docbook create mode 100644 po/fr/docs/konqueror/config.docbook create mode 100644 po/fr/docs/konqueror/credits.docbook create mode 100644 po/fr/docs/konqueror/dirtree.png create mode 100644 po/fr/docs/konqueror/dragdrop.png create mode 100644 po/fr/docs/konqueror/faq.docbook create mode 100644 po/fr/docs/konqueror/filemanager.docbook create mode 100644 po/fr/docs/konqueror/index.docbook create mode 100644 po/fr/docs/konqueror/introduction.docbook create mode 100644 po/fr/docs/konqueror/konqorg.png create mode 100644 po/fr/docs/konqueror/parts.png create mode 100644 po/fr/docs/konqueror/path-complete.docbook create mode 100644 po/fr/docs/konqueror/plugins.docbook create mode 100644 po/fr/docs/konqueror/save-settings.docbook create mode 100644 po/fr/docs/konqueror/shortcut1.png create mode 100644 po/fr/docs/konqueror/shortcut2.png create mode 100644 po/fr/docs/konqueror/sidebar.docbook create mode 100644 po/fr/docs/konqueror/view-extensions.docbook create mode 100644 po/fr/fsview.po create mode 100644 po/fr/imgalleryplugin.po create mode 100644 po/fr/kcmbookmarks.po create mode 100644 po/fr/kcmkonq.po create mode 100644 po/fr/kcmkonqhtml.po create mode 100644 po/fr/kcmperformance.po create mode 100644 po/fr/kfmclient.po create mode 100644 po/fr/khtmlsettingsplugin.po create mode 100644 po/fr/khtmltts.po create mode 100644 po/fr/konqueror.po create mode 100644 po/fr/kshellcmdplugin.po create mode 100644 po/fr/libkonq.po create mode 100644 po/fr/searchbarplugin.po create mode 100644 po/fr/uachangerplugin.po create mode 100644 po/fr/webenginepart.po create mode 100644 po/ga/akregator_konqplugin.po create mode 100644 po/ga/autorefresh.po create mode 100644 po/ga/babelfish.po create mode 100644 po/ga/dirfilterplugin.po create mode 100644 po/ga/fsview.po create mode 100644 po/ga/imgalleryplugin.po create mode 100644 po/ga/kcmbookmarks.po create mode 100644 po/ga/kcmkonq.po create mode 100644 po/ga/kcmkonqhtml.po create mode 100644 po/ga/kcmperformance.po create mode 100644 po/ga/kfmclient.po create mode 100644 po/ga/khtmlsettingsplugin.po create mode 100644 po/ga/khtmltts.po create mode 100644 po/ga/konqueror.po create mode 100644 po/ga/kshellcmdplugin.po create mode 100644 po/ga/libkonq.po create mode 100644 po/ga/searchbarplugin.po create mode 100644 po/ga/uachangerplugin.po create mode 100644 po/ga/webenginepart.po create mode 100644 po/gl/akregator_konqplugin.po create mode 100644 po/gl/autorefresh.po create mode 100644 po/gl/babelfish.po create mode 100644 po/gl/dirfilterplugin.po create mode 100644 po/gl/fsview.po create mode 100644 po/gl/imgalleryplugin.po create mode 100644 po/gl/kcmbookmarks.po create mode 100644 po/gl/kcmkonq.po create mode 100644 po/gl/kcmkonqhtml.po create mode 100644 po/gl/kcmperformance.po create mode 100644 po/gl/kfmclient.po create mode 100644 po/gl/khtmlsettingsplugin.po create mode 100644 po/gl/khtmltts.po create mode 100644 po/gl/konqueror.po create mode 100644 po/gl/kshellcmdplugin.po create mode 100644 po/gl/libkonq.po create mode 100644 po/gl/searchbarplugin.po create mode 100644 po/gl/uachangerplugin.po create mode 100644 po/gl/webenginepart.po create mode 100644 po/he/akregator_konqplugin.po create mode 100644 po/he/autorefresh.po create mode 100644 po/he/babelfish.po create mode 100644 po/he/dirfilterplugin.po create mode 100644 po/he/fsview.po create mode 100644 po/he/imgalleryplugin.po create mode 100644 po/he/kcmbookmarks.po create mode 100644 po/he/kcmkonq.po create mode 100644 po/he/kcmkonqhtml.po create mode 100644 po/he/kcmperformance.po create mode 100644 po/he/kfmclient.po create mode 100644 po/he/khtmlsettingsplugin.po create mode 100644 po/he/khtmltts.po create mode 100644 po/he/konqueror.po create mode 100644 po/he/kshellcmdplugin.po create mode 100644 po/he/libkonq.po create mode 100644 po/he/searchbarplugin.po create mode 100644 po/he/uachangerplugin.po create mode 100644 po/hi/akregator_konqplugin.po create mode 100644 po/hi/autorefresh.po create mode 100644 po/hi/babelfish.po create mode 100644 po/hi/dirfilterplugin.po create mode 100644 po/hi/fsview.po create mode 100644 po/hi/imgalleryplugin.po create mode 100644 po/hi/kcmbookmarks.po create mode 100644 po/hi/kcmkonq.po create mode 100644 po/hi/kcmkonqhtml.po create mode 100644 po/hi/kcmperformance.po create mode 100644 po/hi/kfmclient.po create mode 100644 po/hi/khtmlsettingsplugin.po create mode 100644 po/hi/khtmltts.po create mode 100644 po/hi/konqueror.po create mode 100644 po/hi/kshellcmdplugin.po create mode 100644 po/hi/libkonq.po create mode 100644 po/hi/searchbarplugin.po create mode 100644 po/hi/uachangerplugin.po create mode 100644 po/hr/akregator_konqplugin.po create mode 100644 po/hr/autorefresh.po create mode 100644 po/hr/babelfish.po create mode 100644 po/hr/dirfilterplugin.po create mode 100644 po/hr/fsview.po create mode 100644 po/hr/imgalleryplugin.po create mode 100644 po/hr/kcmbookmarks.po create mode 100644 po/hr/kcmkonq.po create mode 100644 po/hr/kcmkonqhtml.po create mode 100644 po/hr/kcmperformance.po create mode 100644 po/hr/kfmclient.po create mode 100644 po/hr/khtmlsettingsplugin.po create mode 100644 po/hr/khtmltts.po create mode 100644 po/hr/konqueror.po create mode 100644 po/hr/kshellcmdplugin.po create mode 100644 po/hr/libkonq.po create mode 100644 po/hr/searchbarplugin.po create mode 100644 po/hr/uachangerplugin.po create mode 100644 po/hu/akregator_konqplugin.po create mode 100644 po/hu/autorefresh.po create mode 100644 po/hu/babelfish.po create mode 100644 po/hu/dirfilterplugin.po create mode 100644 po/hu/fsview.po create mode 100644 po/hu/imgalleryplugin.po create mode 100644 po/hu/kcmbookmarks.po create mode 100644 po/hu/kcmkonq.po create mode 100644 po/hu/kcmkonqhtml.po create mode 100644 po/hu/kcmperformance.po create mode 100644 po/hu/kfmclient.po create mode 100644 po/hu/khtmlsettingsplugin.po create mode 100644 po/hu/khtmltts.po create mode 100644 po/hu/konqueror.po create mode 100644 po/hu/kshellcmdplugin.po create mode 100644 po/hu/libkonq.po create mode 100644 po/hu/searchbarplugin.po create mode 100644 po/hu/uachangerplugin.po create mode 100644 po/hu/webenginepart.po create mode 100644 po/ia/akregator_konqplugin.po create mode 100644 po/ia/autorefresh.po create mode 100644 po/ia/babelfish.po create mode 100644 po/ia/dirfilterplugin.po create mode 100644 po/ia/fsview.po create mode 100644 po/ia/imgalleryplugin.po create mode 100644 po/ia/kcmbookmarks.po create mode 100644 po/ia/kcmkonq.po create mode 100644 po/ia/kcmkonqhtml.po create mode 100644 po/ia/kcmperformance.po create mode 100644 po/ia/kfmclient.po create mode 100644 po/ia/khtmlsettingsplugin.po create mode 100644 po/ia/khtmltts.po create mode 100644 po/ia/konqueror.po create mode 100644 po/ia/kshellcmdplugin.po create mode 100644 po/ia/libkonq.po create mode 100644 po/ia/searchbarplugin.po create mode 100644 po/ia/uachangerplugin.po create mode 100644 po/ia/webenginepart.po create mode 100644 po/id/akregator_konqplugin.po create mode 100644 po/id/autorefresh.po create mode 100644 po/id/babelfish.po create mode 100644 po/id/dirfilterplugin.po create mode 100644 po/id/fsview.po create mode 100644 po/id/imgalleryplugin.po create mode 100644 po/id/kcmbookmarks.po create mode 100644 po/id/kcmkonq.po create mode 100644 po/id/kcmkonqhtml.po create mode 100644 po/id/kcmperformance.po create mode 100644 po/id/kfmclient.po create mode 100644 po/id/khtmlsettingsplugin.po create mode 100644 po/id/khtmltts.po create mode 100644 po/id/konqueror.po create mode 100644 po/id/kshellcmdplugin.po create mode 100644 po/id/libkonq.po create mode 100644 po/id/searchbarplugin.po create mode 100644 po/id/uachangerplugin.po create mode 100644 po/id/webenginepart.po create mode 100644 po/is/akregator_konqplugin.po create mode 100644 po/is/autorefresh.po create mode 100644 po/is/babelfish.po create mode 100644 po/is/dirfilterplugin.po create mode 100644 po/is/fsview.po create mode 100644 po/is/imgalleryplugin.po create mode 100644 po/is/kcmbookmarks.po create mode 100644 po/is/kcmkonq.po create mode 100644 po/is/kcmkonqhtml.po create mode 100644 po/is/kcmperformance.po create mode 100644 po/is/kfmclient.po create mode 100644 po/is/khtmlsettingsplugin.po create mode 100644 po/is/khtmltts.po create mode 100644 po/is/konqueror.po create mode 100644 po/is/kshellcmdplugin.po create mode 100644 po/is/libkonq.po create mode 100644 po/is/searchbarplugin.po create mode 100644 po/is/uachangerplugin.po create mode 100644 po/it/akregator_konqplugin.po create mode 100644 po/it/autorefresh.po create mode 100644 po/it/babelfish.po create mode 100644 po/it/dirfilterplugin.po create mode 100644 po/it/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/it/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/it/docs/kcontrol5/history/index.docbook create mode 100644 po/it/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/it/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/it/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/it/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/it/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/it/docs/kcontrol5/performance/index.docbook create mode 100644 po/it/docs/konqueror/index.docbook create mode 100644 po/it/fsview.po create mode 100644 po/it/imgalleryplugin.po create mode 100644 po/it/kcmbookmarks.po create mode 100644 po/it/kcmkonq.po create mode 100644 po/it/kcmkonqhtml.po create mode 100644 po/it/kcmperformance.po create mode 100644 po/it/kfmclient.po create mode 100644 po/it/khtmlsettingsplugin.po create mode 100644 po/it/khtmltts.po create mode 100644 po/it/konqueror.po create mode 100644 po/it/kshellcmdplugin.po create mode 100644 po/it/libkonq.po create mode 100644 po/it/searchbarplugin.po create mode 100644 po/it/uachangerplugin.po create mode 100644 po/it/webenginepart.po create mode 100644 po/ja/akregator_konqplugin.po create mode 100644 po/ja/autorefresh.po create mode 100644 po/ja/babelfish.po create mode 100644 po/ja/dirfilterplugin.po create mode 100644 po/ja/fsview.po create mode 100644 po/ja/imgalleryplugin.po create mode 100644 po/ja/kcmbookmarks.po create mode 100644 po/ja/kcmkonq.po create mode 100644 po/ja/kcmkonqhtml.po create mode 100644 po/ja/kcmperformance.po create mode 100644 po/ja/kfmclient.po create mode 100644 po/ja/khtmlsettingsplugin.po create mode 100644 po/ja/khtmltts.po create mode 100644 po/ja/konqueror.po create mode 100644 po/ja/kshellcmdplugin.po create mode 100644 po/ja/libkonq.po create mode 100644 po/ja/searchbarplugin.po create mode 100644 po/ja/uachangerplugin.po create mode 100644 po/ja/webenginepart.po create mode 100644 po/kk/akregator_konqplugin.po create mode 100644 po/kk/autorefresh.po create mode 100644 po/kk/babelfish.po create mode 100644 po/kk/dirfilterplugin.po create mode 100644 po/kk/fsview.po create mode 100644 po/kk/imgalleryplugin.po create mode 100644 po/kk/kcmbookmarks.po create mode 100644 po/kk/kcmkonq.po create mode 100644 po/kk/kcmkonqhtml.po create mode 100644 po/kk/kcmperformance.po create mode 100644 po/kk/kfmclient.po create mode 100644 po/kk/khtmlsettingsplugin.po create mode 100644 po/kk/khtmltts.po create mode 100644 po/kk/konqueror.po create mode 100644 po/kk/kshellcmdplugin.po create mode 100644 po/kk/libkonq.po create mode 100644 po/kk/searchbarplugin.po create mode 100644 po/kk/uachangerplugin.po create mode 100644 po/kk/webenginepart.po create mode 100644 po/km/akregator_konqplugin.po create mode 100644 po/km/autorefresh.po create mode 100644 po/km/babelfish.po create mode 100644 po/km/dirfilterplugin.po create mode 100644 po/km/fsview.po create mode 100644 po/km/imgalleryplugin.po create mode 100644 po/km/kcmbookmarks.po create mode 100644 po/km/kcmkonq.po create mode 100644 po/km/kcmkonqhtml.po create mode 100644 po/km/kcmperformance.po create mode 100644 po/km/kfmclient.po create mode 100644 po/km/khtmlsettingsplugin.po create mode 100644 po/km/khtmltts.po create mode 100644 po/km/konqueror.po create mode 100644 po/km/kshellcmdplugin.po create mode 100644 po/km/libkonq.po create mode 100644 po/km/searchbarplugin.po create mode 100644 po/km/uachangerplugin.po create mode 100644 po/km/webenginepart.po create mode 100644 po/ko/akregator_konqplugin.po create mode 100644 po/ko/autorefresh.po create mode 100644 po/ko/babelfish.po create mode 100644 po/ko/dirfilterplugin.po create mode 100644 po/ko/fsview.po create mode 100644 po/ko/imgalleryplugin.po create mode 100644 po/ko/kcmbookmarks.po create mode 100644 po/ko/kcmkonq.po create mode 100644 po/ko/kcmkonqhtml.po create mode 100644 po/ko/kcmperformance.po create mode 100644 po/ko/kfmclient.po create mode 100644 po/ko/khtmlsettingsplugin.po create mode 100644 po/ko/khtmltts.po create mode 100644 po/ko/konqueror.po create mode 100644 po/ko/kshellcmdplugin.po create mode 100644 po/ko/libkonq.po create mode 100644 po/ko/searchbarplugin.po create mode 100644 po/ko/uachangerplugin.po create mode 100644 po/ko/webenginepart.po create mode 100644 po/lt/akregator_konqplugin.po create mode 100644 po/lt/autorefresh.po create mode 100644 po/lt/babelfish.po create mode 100644 po/lt/dirfilterplugin.po create mode 100644 po/lt/docs/konqueror/basics.docbook create mode 100644 po/lt/docs/konqueror/bookmarks.docbook create mode 100644 po/lt/docs/konqueror/browser.docbook create mode 100644 po/lt/docs/konqueror/config.docbook create mode 100644 po/lt/docs/konqueror/filemanager.docbook create mode 100644 po/lt/docs/konqueror/introduction.docbook create mode 100644 po/lt/docs/konqueror/plugins.docbook create mode 100644 po/lt/docs/konqueror/save-settings.docbook create mode 100644 po/lt/docs/konqueror/sidebar.docbook create mode 100644 po/lt/docs/konqueror/view-extensions.docbook create mode 100644 po/lt/fsview.po create mode 100644 po/lt/imgalleryplugin.po create mode 100644 po/lt/kcmbookmarks.po create mode 100644 po/lt/kcmkonq.po create mode 100644 po/lt/kcmkonqhtml.po create mode 100644 po/lt/kcmperformance.po create mode 100644 po/lt/kfmclient.po create mode 100644 po/lt/khtmlsettingsplugin.po create mode 100644 po/lt/khtmltts.po create mode 100644 po/lt/konqueror.po create mode 100644 po/lt/kshellcmdplugin.po create mode 100644 po/lt/libkonq.po create mode 100644 po/lt/searchbarplugin.po create mode 100644 po/lt/uachangerplugin.po create mode 100644 po/lt/webenginepart.po create mode 100644 po/lv/akregator_konqplugin.po create mode 100644 po/lv/autorefresh.po create mode 100644 po/lv/babelfish.po create mode 100644 po/lv/dirfilterplugin.po create mode 100644 po/lv/fsview.po create mode 100644 po/lv/imgalleryplugin.po create mode 100644 po/lv/kcmbookmarks.po create mode 100644 po/lv/kcmkonq.po create mode 100644 po/lv/kcmkonqhtml.po create mode 100644 po/lv/kcmperformance.po create mode 100644 po/lv/kfmclient.po create mode 100644 po/lv/khtmlsettingsplugin.po create mode 100644 po/lv/khtmltts.po create mode 100644 po/lv/konqueror.po create mode 100644 po/lv/kshellcmdplugin.po create mode 100644 po/lv/libkonq.po create mode 100644 po/lv/searchbarplugin.po create mode 100644 po/lv/uachangerplugin.po create mode 100644 po/ml/akregator_konqplugin.po create mode 100644 po/ml/autorefresh.po create mode 100644 po/ml/babelfish.po create mode 100644 po/ml/dirfilterplugin.po create mode 100644 po/ml/fsview.po create mode 100644 po/ml/imgalleryplugin.po create mode 100644 po/ml/kcmbookmarks.po create mode 100644 po/ml/kcmkonq.po create mode 100644 po/ml/kcmkonqhtml.po create mode 100644 po/ml/kcmperformance.po create mode 100644 po/ml/kfmclient.po create mode 100644 po/ml/khtmlsettingsplugin.po create mode 100644 po/ml/khtmltts.po create mode 100644 po/ml/konqueror.po create mode 100644 po/ml/kshellcmdplugin.po create mode 100644 po/ml/libkonq.po create mode 100644 po/ml/searchbarplugin.po create mode 100644 po/ml/uachangerplugin.po create mode 100644 po/ml/webenginepart.po create mode 100644 po/mr/akregator_konqplugin.po create mode 100644 po/mr/autorefresh.po create mode 100644 po/mr/babelfish.po create mode 100644 po/mr/dirfilterplugin.po create mode 100644 po/mr/fsview.po create mode 100644 po/mr/imgalleryplugin.po create mode 100644 po/mr/kcmbookmarks.po create mode 100644 po/mr/kcmkonq.po create mode 100644 po/mr/kcmkonqhtml.po create mode 100644 po/mr/kcmperformance.po create mode 100644 po/mr/kfmclient.po create mode 100644 po/mr/khtmlsettingsplugin.po create mode 100644 po/mr/khtmltts.po create mode 100644 po/mr/konqueror.po create mode 100644 po/mr/kshellcmdplugin.po create mode 100644 po/mr/libkonq.po create mode 100644 po/mr/searchbarplugin.po create mode 100644 po/mr/uachangerplugin.po create mode 100644 po/mr/webenginepart.po create mode 100644 po/nb/akregator_konqplugin.po create mode 100644 po/nb/autorefresh.po create mode 100644 po/nb/babelfish.po create mode 100644 po/nb/dirfilterplugin.po create mode 100644 po/nb/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/nb/docs/kcontrol5/history/index.docbook create mode 100644 po/nb/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/nb/docs/konqueror/basics.docbook create mode 100644 po/nb/docs/konqueror/bookmarks.docbook create mode 100644 po/nb/docs/konqueror/browser.docbook create mode 100644 po/nb/docs/konqueror/commands.docbook create mode 100644 po/nb/docs/konqueror/config.docbook create mode 100644 po/nb/docs/konqueror/credits.docbook create mode 100644 po/nb/docs/konqueror/faq.docbook create mode 100644 po/nb/docs/konqueror/filemanager.docbook create mode 100644 po/nb/docs/konqueror/introduction.docbook create mode 100644 po/nb/docs/konqueror/path-complete.docbook create mode 100644 po/nb/docs/konqueror/plugins.docbook create mode 100644 po/nb/docs/konqueror/save-settings.docbook create mode 100644 po/nb/docs/konqueror/sidebar.docbook create mode 100644 po/nb/docs/konqueror/view-extensions.docbook create mode 100644 po/nb/fsview.po create mode 100644 po/nb/imgalleryplugin.po create mode 100644 po/nb/kcmbookmarks.po create mode 100644 po/nb/kcmkonq.po create mode 100644 po/nb/kcmkonqhtml.po create mode 100644 po/nb/kcmperformance.po create mode 100644 po/nb/kfmclient.po create mode 100644 po/nb/khtmlsettingsplugin.po create mode 100644 po/nb/khtmltts.po create mode 100644 po/nb/konqueror.po create mode 100644 po/nb/kshellcmdplugin.po create mode 100644 po/nb/libkonq.po create mode 100644 po/nb/searchbarplugin.po create mode 100644 po/nb/uachangerplugin.po create mode 100644 po/nb/webenginepart.po create mode 100644 po/nds/akregator_konqplugin.po create mode 100644 po/nds/autorefresh.po create mode 100644 po/nds/babelfish.po create mode 100644 po/nds/dirfilterplugin.po create mode 100644 po/nds/fsview.po create mode 100644 po/nds/imgalleryplugin.po create mode 100644 po/nds/kcmbookmarks.po create mode 100644 po/nds/kcmkonq.po create mode 100644 po/nds/kcmkonqhtml.po create mode 100644 po/nds/kcmperformance.po create mode 100644 po/nds/kfmclient.po create mode 100644 po/nds/khtmlsettingsplugin.po create mode 100644 po/nds/khtmltts.po create mode 100644 po/nds/konqueror.po create mode 100644 po/nds/kshellcmdplugin.po create mode 100644 po/nds/libkonq.po create mode 100644 po/nds/searchbarplugin.po create mode 100644 po/nds/uachangerplugin.po create mode 100644 po/nds/webenginepart.po create mode 100644 po/nl/akregator_konqplugin.po create mode 100644 po/nl/autorefresh.po create mode 100644 po/nl/babelfish.po create mode 100644 po/nl/dirfilterplugin.po create mode 100644 po/nl/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/nl/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/nl/docs/kcontrol5/history/index.docbook create mode 100644 po/nl/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/nl/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/nl/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/nl/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/nl/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/nl/docs/kcontrol5/performance/index.docbook create mode 100644 po/nl/docs/konqueror/basics.docbook create mode 100644 po/nl/docs/konqueror/bookmarks.docbook create mode 100644 po/nl/docs/konqueror/browser.docbook create mode 100644 po/nl/docs/konqueror/cmndline.png create mode 100644 po/nl/docs/konqueror/commands.docbook create mode 100644 po/nl/docs/konqueror/config.docbook create mode 100644 po/nl/docs/konqueror/credits.docbook create mode 100644 po/nl/docs/konqueror/dirtree.png create mode 100644 po/nl/docs/konqueror/dragdrop.png create mode 100644 po/nl/docs/konqueror/faq.docbook create mode 100644 po/nl/docs/konqueror/filemanager.docbook create mode 100644 po/nl/docs/konqueror/index.docbook create mode 100644 po/nl/docs/konqueror/introduction.docbook create mode 100644 po/nl/docs/konqueror/konqorg.png create mode 100644 po/nl/docs/konqueror/parts.png create mode 100644 po/nl/docs/konqueror/path-complete.docbook create mode 100644 po/nl/docs/konqueror/plugins.docbook create mode 100644 po/nl/docs/konqueror/save-settings.docbook create mode 100644 po/nl/docs/konqueror/shortcut1.png create mode 100644 po/nl/docs/konqueror/shortcut2.png create mode 100644 po/nl/docs/konqueror/sidebar.docbook create mode 100644 po/nl/docs/konqueror/view-extensions.docbook create mode 100644 po/nl/fsview.po create mode 100644 po/nl/imgalleryplugin.po create mode 100644 po/nl/kcmbookmarks.po create mode 100644 po/nl/kcmkonq.po create mode 100644 po/nl/kcmkonqhtml.po create mode 100644 po/nl/kcmperformance.po create mode 100644 po/nl/kfmclient.po create mode 100644 po/nl/khtmlsettingsplugin.po create mode 100644 po/nl/khtmltts.po create mode 100644 po/nl/konqueror.po create mode 100644 po/nl/kshellcmdplugin.po create mode 100644 po/nl/libkonq.po create mode 100644 po/nl/searchbarplugin.po create mode 100644 po/nl/uachangerplugin.po create mode 100644 po/nl/webenginepart.po create mode 100644 po/nn/akregator_konqplugin.po create mode 100644 po/nn/autorefresh.po create mode 100644 po/nn/babelfish.po create mode 100644 po/nn/dirfilterplugin.po create mode 100644 po/nn/fsview.po create mode 100644 po/nn/imgalleryplugin.po create mode 100644 po/nn/kcmbookmarks.po create mode 100644 po/nn/kcmkonq.po create mode 100644 po/nn/kcmkonqhtml.po create mode 100644 po/nn/kcmperformance.po create mode 100644 po/nn/kfmclient.po create mode 100644 po/nn/khtmlsettingsplugin.po create mode 100644 po/nn/khtmltts.po create mode 100644 po/nn/konqueror.po create mode 100644 po/nn/kshellcmdplugin.po create mode 100644 po/nn/libkonq.po create mode 100644 po/nn/searchbarplugin.po create mode 100644 po/nn/uachangerplugin.po create mode 100644 po/nn/webenginepart.po create mode 100644 po/pa/akregator_konqplugin.po create mode 100644 po/pa/autorefresh.po create mode 100644 po/pa/babelfish.po create mode 100644 po/pa/dirfilterplugin.po create mode 100644 po/pa/fsview.po create mode 100644 po/pa/imgalleryplugin.po create mode 100644 po/pa/kcmbookmarks.po create mode 100644 po/pa/kcmkonq.po create mode 100644 po/pa/kcmkonqhtml.po create mode 100644 po/pa/kcmperformance.po create mode 100644 po/pa/kfmclient.po create mode 100644 po/pa/khtmlsettingsplugin.po create mode 100644 po/pa/khtmltts.po create mode 100644 po/pa/konqueror.po create mode 100644 po/pa/kshellcmdplugin.po create mode 100644 po/pa/libkonq.po create mode 100644 po/pa/searchbarplugin.po create mode 100644 po/pa/uachangerplugin.po create mode 100644 po/pa/webenginepart.po create mode 100644 po/pl/akregator_konqplugin.po create mode 100644 po/pl/autorefresh.po create mode 100644 po/pl/babelfish.po create mode 100644 po/pl/dirfilterplugin.po create mode 100644 po/pl/docs/konqueror/basics.docbook create mode 100644 po/pl/docs/konqueror/bookmarks.docbook create mode 100644 po/pl/docs/konqueror/browser.docbook create mode 100644 po/pl/docs/konqueror/cmndline.png create mode 100644 po/pl/docs/konqueror/commands.docbook create mode 100644 po/pl/docs/konqueror/config.docbook create mode 100644 po/pl/docs/konqueror/credits.docbook create mode 100644 po/pl/docs/konqueror/dirtree.png create mode 100644 po/pl/docs/konqueror/dragdrop.png create mode 100644 po/pl/docs/konqueror/faq.docbook create mode 100644 po/pl/docs/konqueror/filemanager.docbook create mode 100644 po/pl/docs/konqueror/index.docbook create mode 100644 po/pl/docs/konqueror/introduction.docbook create mode 100644 po/pl/docs/konqueror/konqorg.png create mode 100644 po/pl/docs/konqueror/parts.png create mode 100644 po/pl/docs/konqueror/path-complete.docbook create mode 100644 po/pl/docs/konqueror/plugins.docbook create mode 100644 po/pl/docs/konqueror/save-settings.docbook create mode 100644 po/pl/docs/konqueror/shortcut1.png create mode 100644 po/pl/docs/konqueror/shortcut2.png create mode 100644 po/pl/docs/konqueror/sidebar.docbook create mode 100644 po/pl/fsview.po create mode 100644 po/pl/imgalleryplugin.po create mode 100644 po/pl/kcmbookmarks.po create mode 100644 po/pl/kcmkonq.po create mode 100644 po/pl/kcmkonqhtml.po create mode 100644 po/pl/kcmperformance.po create mode 100644 po/pl/kfmclient.po create mode 100644 po/pl/khtmlsettingsplugin.po create mode 100644 po/pl/khtmltts.po create mode 100644 po/pl/konqueror.po create mode 100644 po/pl/kshellcmdplugin.po create mode 100644 po/pl/libkonq.po create mode 100644 po/pl/searchbarplugin.po create mode 100644 po/pl/uachangerplugin.po create mode 100644 po/pl/webenginepart.po create mode 100644 po/pt/akregator_konqplugin.po create mode 100644 po/pt/autorefresh.po create mode 100644 po/pt/babelfish.po create mode 100644 po/pt/dirfilterplugin.po create mode 100644 po/pt/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/pt/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/pt/docs/kcontrol5/history/index.docbook create mode 100644 po/pt/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/pt/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/pt/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/pt/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/pt/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/pt/docs/kcontrol5/performance/index.docbook create mode 100644 po/pt/docs/konqueror/basics.docbook create mode 100644 po/pt/docs/konqueror/bookmarks.docbook create mode 100644 po/pt/docs/konqueror/browser.docbook create mode 100644 po/pt/docs/konqueror/commands.docbook create mode 100644 po/pt/docs/konqueror/config.docbook create mode 100644 po/pt/docs/konqueror/credits.docbook create mode 100644 po/pt/docs/konqueror/faq.docbook create mode 100644 po/pt/docs/konqueror/filemanager.docbook create mode 100644 po/pt/docs/konqueror/index.docbook create mode 100644 po/pt/docs/konqueror/introduction.docbook create mode 100644 po/pt/docs/konqueror/path-complete.docbook create mode 100644 po/pt/docs/konqueror/plugins.docbook create mode 100644 po/pt/docs/konqueror/save-settings.docbook create mode 100644 po/pt/docs/konqueror/sidebar.docbook create mode 100644 po/pt/docs/konqueror/view-extensions.docbook create mode 100644 po/pt/fsview.po create mode 100644 po/pt/imgalleryplugin.po create mode 100644 po/pt/kcmbookmarks.po create mode 100644 po/pt/kcmkonq.po create mode 100644 po/pt/kcmkonqhtml.po create mode 100644 po/pt/kcmperformance.po create mode 100644 po/pt/kfmclient.po create mode 100644 po/pt/khtmlsettingsplugin.po create mode 100644 po/pt/khtmltts.po create mode 100644 po/pt/konqueror.po create mode 100644 po/pt/kshellcmdplugin.po create mode 100644 po/pt/libkonq.po create mode 100644 po/pt/searchbarplugin.po create mode 100644 po/pt/uachangerplugin.po create mode 100644 po/pt/webenginepart.po create mode 100644 po/pt_BR/akregator_konqplugin.po create mode 100644 po/pt_BR/autorefresh.po create mode 100644 po/pt_BR/babelfish.po create mode 100644 po/pt_BR/dirfilterplugin.po create mode 100644 po/pt_BR/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/history/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/pt_BR/docs/kcontrol5/performance/index.docbook create mode 100644 po/pt_BR/docs/konqueror/cmndline.png create mode 100644 po/pt_BR/docs/konqueror/dirtree.png create mode 100644 po/pt_BR/docs/konqueror/dragdrop.png create mode 100644 po/pt_BR/docs/konqueror/folders.png create mode 100644 po/pt_BR/docs/konqueror/index.docbook create mode 100644 po/pt_BR/docs/konqueror/konqorg.png create mode 100644 po/pt_BR/docs/konqueror/look.png create mode 100644 po/pt_BR/docs/konqueror/parts.png create mode 100644 po/pt_BR/docs/konqueror/shortcut1.png create mode 100644 po/pt_BR/docs/konqueror/shortcut2.png create mode 100644 po/pt_BR/docs/konqueror/thumbnails.png create mode 100644 po/pt_BR/docs/konqueror/viewproperties-dialog.png create mode 100644 po/pt_BR/fsview.po create mode 100644 po/pt_BR/imgalleryplugin.po create mode 100644 po/pt_BR/kcmbookmarks.po create mode 100644 po/pt_BR/kcmkonq.po create mode 100644 po/pt_BR/kcmkonqhtml.po create mode 100644 po/pt_BR/kcmperformance.po create mode 100644 po/pt_BR/kfmclient.po create mode 100644 po/pt_BR/khtmlsettingsplugin.po create mode 100644 po/pt_BR/khtmltts.po create mode 100644 po/pt_BR/konqueror.po create mode 100644 po/pt_BR/kshellcmdplugin.po create mode 100644 po/pt_BR/libkonq.po create mode 100644 po/pt_BR/searchbarplugin.po create mode 100644 po/pt_BR/uachangerplugin.po create mode 100644 po/pt_BR/webenginepart.po create mode 100644 po/ro/akregator_konqplugin.po create mode 100644 po/ro/autorefresh.po create mode 100644 po/ro/babelfish.po create mode 100644 po/ro/dirfilterplugin.po create mode 100644 po/ro/fsview.po create mode 100644 po/ro/imgalleryplugin.po create mode 100644 po/ro/kcmbookmarks.po create mode 100644 po/ro/kcmkonq.po create mode 100644 po/ro/kcmkonqhtml.po create mode 100644 po/ro/kcmperformance.po create mode 100644 po/ro/kfmclient.po create mode 100644 po/ro/khtmlsettingsplugin.po create mode 100644 po/ro/khtmltts.po create mode 100644 po/ro/konqueror.po create mode 100644 po/ro/kshellcmdplugin.po create mode 100644 po/ro/libkonq.po create mode 100644 po/ro/searchbarplugin.po create mode 100644 po/ro/uachangerplugin.po create mode 100644 po/ro/webenginepart.po create mode 100644 po/ru/akregator_konqplugin.po create mode 100644 po/ru/autorefresh.po create mode 100644 po/ru/babelfish.po create mode 100644 po/ru/dirfilterplugin.po create mode 100644 po/ru/docs/konqueror/basics.docbook create mode 100644 po/ru/docs/konqueror/bookmarks.docbook create mode 100644 po/ru/docs/konqueror/browser.docbook create mode 100644 po/ru/docs/konqueror/cmndline.png create mode 100644 po/ru/docs/konqueror/commands.docbook create mode 100644 po/ru/docs/konqueror/config.docbook create mode 100644 po/ru/docs/konqueror/credits.docbook create mode 100644 po/ru/docs/konqueror/dirtree.png create mode 100644 po/ru/docs/konqueror/dragdrop.png create mode 100644 po/ru/docs/konqueror/faq.docbook create mode 100644 po/ru/docs/konqueror/filemanager.docbook create mode 100644 po/ru/docs/konqueror/index.docbook create mode 100644 po/ru/docs/konqueror/introduction.docbook create mode 100644 po/ru/docs/konqueror/konqorg.png create mode 100644 po/ru/docs/konqueror/parts.png create mode 100644 po/ru/docs/konqueror/path-complete.docbook create mode 100644 po/ru/docs/konqueror/plugins.docbook create mode 100644 po/ru/docs/konqueror/save-settings.docbook create mode 100644 po/ru/docs/konqueror/shortcut1.png create mode 100644 po/ru/docs/konqueror/shortcut2.png create mode 100644 po/ru/docs/konqueror/sidebar.docbook create mode 100644 po/ru/fsview.po create mode 100644 po/ru/imgalleryplugin.po create mode 100644 po/ru/kcmbookmarks.po create mode 100644 po/ru/kcmkonq.po create mode 100644 po/ru/kcmkonqhtml.po create mode 100644 po/ru/kcmperformance.po create mode 100644 po/ru/kfmclient.po create mode 100644 po/ru/khtmlsettingsplugin.po create mode 100644 po/ru/khtmltts.po create mode 100644 po/ru/konqueror.po create mode 100644 po/ru/kshellcmdplugin.po create mode 100644 po/ru/libkonq.po create mode 100644 po/ru/searchbarplugin.po create mode 100644 po/ru/uachangerplugin.po create mode 100644 po/ru/webenginepart.po create mode 100644 po/sk/akregator_konqplugin.po create mode 100644 po/sk/autorefresh.po create mode 100644 po/sk/babelfish.po create mode 100644 po/sk/dirfilterplugin.po create mode 100644 po/sk/fsview.po create mode 100644 po/sk/imgalleryplugin.po create mode 100644 po/sk/kcmbookmarks.po create mode 100644 po/sk/kcmkonq.po create mode 100644 po/sk/kcmkonqhtml.po create mode 100644 po/sk/kcmperformance.po create mode 100644 po/sk/kfmclient.po create mode 100644 po/sk/khtmlsettingsplugin.po create mode 100644 po/sk/khtmltts.po create mode 100644 po/sk/konqueror.po create mode 100644 po/sk/kshellcmdplugin.po create mode 100644 po/sk/libkonq.po create mode 100644 po/sk/searchbarplugin.po create mode 100644 po/sk/uachangerplugin.po create mode 100644 po/sk/webenginepart.po create mode 100644 po/sl/akregator_konqplugin.po create mode 100644 po/sl/autorefresh.po create mode 100644 po/sl/babelfish.po create mode 100644 po/sl/dirfilterplugin.po create mode 100644 po/sl/docs/konqueror/cmndline.png create mode 100644 po/sl/docs/konqueror/dirtree.png create mode 100644 po/sl/docs/konqueror/dragdrop.png create mode 100644 po/sl/docs/konqueror/filetype1.png create mode 100644 po/sl/docs/konqueror/filetype3.png create mode 100644 po/sl/docs/konqueror/filetype4.png create mode 100644 po/sl/docs/konqueror/konqdoc5.png create mode 100644 po/sl/docs/konqueror/konqdoc9.png create mode 100644 po/sl/docs/konqueror/konqorg.png create mode 100644 po/sl/docs/konqueror/parts.png create mode 100644 po/sl/docs/konqueror/samba.png create mode 100644 po/sl/fsview.po create mode 100644 po/sl/imgalleryplugin.po create mode 100644 po/sl/kcmbookmarks.po create mode 100644 po/sl/kcmkonq.po create mode 100644 po/sl/kcmkonqhtml.po create mode 100644 po/sl/kcmperformance.po create mode 100644 po/sl/kfmclient.po create mode 100644 po/sl/khtmlsettingsplugin.po create mode 100644 po/sl/khtmltts.po create mode 100644 po/sl/konqueror.po create mode 100644 po/sl/kshellcmdplugin.po create mode 100644 po/sl/libkonq.po create mode 100644 po/sl/searchbarplugin.po create mode 100644 po/sl/uachangerplugin.po create mode 100644 po/sl/webenginepart.po create mode 100644 po/sr/akregator_konqplugin.po create mode 100644 po/sr/autorefresh.po create mode 100644 po/sr/babelfish.po create mode 100644 po/sr/dirfilterplugin.po create mode 100644 po/sr/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/sr/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/sr/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/sr/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/sr/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/sr/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/sr/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/sr/docs/kcontrol5/performance/index.docbook create mode 100644 po/sr/docs/konqueror/basics.docbook create mode 100644 po/sr/docs/konqueror/bookmarks.docbook create mode 100644 po/sr/docs/konqueror/browser.docbook create mode 100644 po/sr/docs/konqueror/commands.docbook create mode 100644 po/sr/docs/konqueror/config.docbook create mode 100644 po/sr/docs/konqueror/credits.docbook create mode 100644 po/sr/docs/konqueror/faq.docbook create mode 100644 po/sr/docs/konqueror/filemanager.docbook create mode 100644 po/sr/docs/konqueror/index.docbook create mode 100644 po/sr/docs/konqueror/introduction.docbook create mode 100644 po/sr/docs/konqueror/l10n-track create mode 100644 po/sr/docs/konqueror/path-complete.docbook create mode 100644 po/sr/docs/konqueror/plugins.docbook create mode 100644 po/sr/docs/konqueror/save-settings.docbook create mode 100644 po/sr/docs/konqueror/sidebar.docbook create mode 100644 po/sr/docs/konqueror/view-extensions.docbook create mode 100644 po/sr/fsview.po create mode 100644 po/sr/imgalleryplugin.po create mode 100644 po/sr/kcmbookmarks.po create mode 100644 po/sr/kcmkonq.po create mode 100644 po/sr/kcmkonqhtml.po create mode 100644 po/sr/kcmperformance.po create mode 100644 po/sr/kfmclient.po create mode 100644 po/sr/khtmlsettingsplugin.po create mode 100644 po/sr/khtmltts.po create mode 100644 po/sr/konqueror.po create mode 100644 po/sr/kshellcmdplugin.po create mode 100644 po/sr/libkonq.po create mode 100644 po/sr/searchbarplugin.po create mode 100644 po/sr/uachangerplugin.po create mode 100644 po/sr/webenginepart.po create mode 100644 po/sv/akregator_konqplugin.po create mode 100644 po/sv/autorefresh.po create mode 100644 po/sv/babelfish.po create mode 100644 po/sv/dirfilterplugin.po create mode 100644 po/sv/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/sv/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/sv/docs/kcontrol5/history/index.docbook create mode 100644 po/sv/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/sv/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/sv/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/sv/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/sv/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/sv/docs/kcontrol5/performance/index.docbook create mode 100644 po/sv/docs/konqueror/cmndline.png create mode 100644 po/sv/docs/konqueror/dirtree.png create mode 100644 po/sv/docs/konqueror/dragdrop.png create mode 100644 po/sv/docs/konqueror/index.docbook create mode 100644 po/sv/docs/konqueror/konqorg.png create mode 100644 po/sv/docs/konqueror/parts.png create mode 100644 po/sv/docs/konqueror/shortcut1.png create mode 100644 po/sv/docs/konqueror/shortcut2.png create mode 100644 po/sv/fsview.po create mode 100644 po/sv/imgalleryplugin.po create mode 100644 po/sv/kcmbookmarks.po create mode 100644 po/sv/kcmkonq.po create mode 100644 po/sv/kcmkonqhtml.po create mode 100644 po/sv/kcmperformance.po create mode 100644 po/sv/kfmclient.po create mode 100644 po/sv/khtmlsettingsplugin.po create mode 100644 po/sv/khtmltts.po create mode 100644 po/sv/konqueror.po create mode 100644 po/sv/kshellcmdplugin.po create mode 100644 po/sv/libkonq.po create mode 100644 po/sv/searchbarplugin.po create mode 100644 po/sv/uachangerplugin.po create mode 100644 po/sv/webenginepart.po create mode 100644 po/tr/akregator_konqplugin.po create mode 100644 po/tr/autorefresh.po create mode 100644 po/tr/babelfish.po create mode 100644 po/tr/dirfilterplugin.po create mode 100644 po/tr/fsview.po create mode 100644 po/tr/imgalleryplugin.po create mode 100644 po/tr/kcmbookmarks.po create mode 100644 po/tr/kcmkonq.po create mode 100644 po/tr/kcmkonqhtml.po create mode 100644 po/tr/kcmperformance.po create mode 100644 po/tr/kfmclient.po create mode 100644 po/tr/khtmlsettingsplugin.po create mode 100644 po/tr/khtmltts.po create mode 100644 po/tr/konqueror.po create mode 100644 po/tr/kshellcmdplugin.po create mode 100644 po/tr/libkonq.po create mode 100644 po/tr/searchbarplugin.po create mode 100644 po/tr/uachangerplugin.po create mode 100644 po/tr/webenginepart.po create mode 100644 po/ug/akregator_konqplugin.po create mode 100644 po/ug/autorefresh.po create mode 100644 po/ug/babelfish.po create mode 100644 po/ug/dirfilterplugin.po create mode 100644 po/ug/fsview.po create mode 100644 po/ug/imgalleryplugin.po create mode 100644 po/ug/kcmbookmarks.po create mode 100644 po/ug/kcmkonq.po create mode 100644 po/ug/kcmkonqhtml.po create mode 100644 po/ug/kcmperformance.po create mode 100644 po/ug/kfmclient.po create mode 100644 po/ug/khtmlsettingsplugin.po create mode 100644 po/ug/khtmltts.po create mode 100644 po/ug/konqueror.po create mode 100644 po/ug/kshellcmdplugin.po create mode 100644 po/ug/libkonq.po create mode 100644 po/ug/searchbarplugin.po create mode 100644 po/ug/uachangerplugin.po create mode 100644 po/ug/webenginepart.po create mode 100644 po/uk/akregator_konqplugin.po create mode 100644 po/uk/autorefresh.po create mode 100644 po/uk/babelfish.po create mode 100644 po/uk/dirfilterplugin.po create mode 100644 po/uk/docs/kcontrol5/bookmarks/index.docbook create mode 100644 po/uk/docs/kcontrol5/filemanager/index.docbook create mode 100644 po/uk/docs/kcontrol5/history/index.docbook create mode 100644 po/uk/docs/kcontrol5/kcmcss/index.docbook create mode 100644 po/uk/docs/kcontrol5/khtml-adblock/index.docbook create mode 100644 po/uk/docs/kcontrol5/khtml-behavior/index.docbook create mode 100644 po/uk/docs/kcontrol5/khtml-general/index.docbook create mode 100644 po/uk/docs/kcontrol5/khtml-java-js/index.docbook create mode 100644 po/uk/docs/kcontrol5/performance/index.docbook create mode 100644 po/uk/docs/konqueror/cmndline.png create mode 100644 po/uk/docs/konqueror/dirtree.png create mode 100644 po/uk/docs/konqueror/dragdrop.png create mode 100644 po/uk/docs/konqueror/folders.png create mode 100644 po/uk/docs/konqueror/index.docbook create mode 100644 po/uk/docs/konqueror/konqorg.png create mode 100644 po/uk/docs/konqueror/look.png create mode 100644 po/uk/docs/konqueror/parts.png create mode 100644 po/uk/docs/konqueror/shortcut1.png create mode 100644 po/uk/docs/konqueror/shortcut2.png create mode 100644 po/uk/docs/konqueror/thumbnails.png create mode 100644 po/uk/docs/konqueror/viewproperties-dialog.png create mode 100644 po/uk/fsview.po create mode 100644 po/uk/imgalleryplugin.po create mode 100644 po/uk/kcmbookmarks.po create mode 100644 po/uk/kcmkonq.po create mode 100644 po/uk/kcmkonqhtml.po create mode 100644 po/uk/kcmperformance.po create mode 100644 po/uk/kfmclient.po create mode 100644 po/uk/khtmlsettingsplugin.po create mode 100644 po/uk/khtmltts.po create mode 100644 po/uk/konqueror.po create mode 100644 po/uk/kshellcmdplugin.po create mode 100644 po/uk/libkonq.po create mode 100644 po/uk/searchbarplugin.po create mode 100644 po/uk/uachangerplugin.po create mode 100644 po/uk/webenginepart.po create mode 100644 po/wa/akregator_konqplugin.po create mode 100644 po/wa/autorefresh.po create mode 100644 po/wa/babelfish.po create mode 100644 po/wa/dirfilterplugin.po create mode 100644 po/wa/fsview.po create mode 100644 po/wa/imgalleryplugin.po create mode 100644 po/wa/kcmbookmarks.po create mode 100644 po/wa/kcmkonq.po create mode 100644 po/wa/kcmkonqhtml.po create mode 100644 po/wa/kcmperformance.po create mode 100644 po/wa/kfmclient.po create mode 100644 po/wa/khtmltts.po create mode 100644 po/wa/konqueror.po create mode 100644 po/wa/kshellcmdplugin.po create mode 100644 po/wa/libkonq.po create mode 100644 po/wa/uachangerplugin.po create mode 100644 po/zh_CN/akregator_konqplugin.po create mode 100644 po/zh_CN/autorefresh.po create mode 100644 po/zh_CN/babelfish.po create mode 100644 po/zh_CN/dirfilterplugin.po create mode 100644 po/zh_CN/fsview.po create mode 100644 po/zh_CN/imgalleryplugin.po create mode 100644 po/zh_CN/kcmbookmarks.po create mode 100644 po/zh_CN/kcmkonq.po create mode 100644 po/zh_CN/kcmkonqhtml.po create mode 100644 po/zh_CN/kcmperformance.po create mode 100644 po/zh_CN/kfmclient.po create mode 100644 po/zh_CN/khtmlsettingsplugin.po create mode 100644 po/zh_CN/khtmltts.po create mode 100644 po/zh_CN/konqueror.po create mode 100644 po/zh_CN/kshellcmdplugin.po create mode 100644 po/zh_CN/libkonq.po create mode 100644 po/zh_CN/searchbarplugin.po create mode 100644 po/zh_CN/uachangerplugin.po create mode 100644 po/zh_CN/webenginepart.po create mode 100644 po/zh_TW/akregator_konqplugin.po create mode 100644 po/zh_TW/autorefresh.po create mode 100644 po/zh_TW/babelfish.po create mode 100644 po/zh_TW/dirfilterplugin.po create mode 100644 po/zh_TW/fsview.po create mode 100644 po/zh_TW/imgalleryplugin.po create mode 100644 po/zh_TW/kcmbookmarks.po create mode 100644 po/zh_TW/kcmkonq.po create mode 100644 po/zh_TW/kcmkonqhtml.po create mode 100644 po/zh_TW/kcmperformance.po create mode 100644 po/zh_TW/kfmclient.po create mode 100644 po/zh_TW/khtmlsettingsplugin.po create mode 100644 po/zh_TW/khtmltts.po create mode 100644 po/zh_TW/konqueror.po create mode 100644 po/zh_TW/kshellcmdplugin.po create mode 100644 po/zh_TW/libkonq.po create mode 100644 po/zh_TW/searchbarplugin.po create mode 100644 po/zh_TW/uachangerplugin.po create mode 100644 po/zh_TW/webenginepart.po create mode 100644 settings/CMakeLists.txt create mode 100644 settings/bookmarks/CMakeLists.txt create mode 100644 settings/bookmarks/Messages.sh create mode 100644 settings/bookmarks/bookmarks.cpp create mode 100644 settings/bookmarks/bookmarks.desktop create mode 100644 settings/bookmarks/bookmarks.h create mode 100644 settings/bookmarks/bookmarks.ui create mode 100644 settings/bookmarks/main.cpp create mode 100644 settings/konq/CMakeLists.txt create mode 100644 settings/konq/Messages.sh create mode 100644 settings/konq/README create mode 100644 settings/konq/behaviour.cpp create mode 100644 settings/konq/behaviour.h create mode 100644 settings/konq/fileappearance.desktop create mode 100644 settings/konq/filebehavior.desktop create mode 100644 settings/konq/kcustommenueditor.cpp create mode 100644 settings/konq/kcustommenueditor.h create mode 100644 settings/konq/konqkcmfactory.cpp create mode 100644 settings/konq/konqkcmfactory.h create mode 100644 settings/konq/onlyone.png create mode 100644 settings/konq/overlapping.png create mode 100644 settings/konq/tests/kcustommenueditortest.cpp create mode 100644 settings/konq/webappearance.desktop create mode 100644 settings/konq/webbehavior.desktop create mode 100644 settings/konqhtml/CMakeLists.txt create mode 100644 settings/konqhtml/Messages.sh create mode 100644 settings/konqhtml/advancedTabOptions.ui create mode 100644 settings/konqhtml/appearance.cpp create mode 100644 settings/konqhtml/appearance.h create mode 100644 settings/konqhtml/css/cssconfig.ui create mode 100644 settings/konqhtml/css/csscustom.ui create mode 100644 settings/konqhtml/css/kcmcss.cpp create mode 100644 settings/konqhtml/css/kcmcss.desktop create mode 100644 settings/konqhtml/css/kcmcss.h create mode 100644 settings/konqhtml/css/template.cpp create mode 100644 settings/konqhtml/css/template.css create mode 100644 settings/konqhtml/css/template.h create mode 100644 settings/konqhtml/domainlistview.cpp create mode 100644 settings/konqhtml/domainlistview.h create mode 100644 settings/konqhtml/filteropts.cpp create mode 100644 settings/konqhtml/filteropts.h create mode 100644 settings/konqhtml/generalopts.cpp create mode 100644 settings/konqhtml/generalopts.h create mode 100644 settings/konqhtml/htmlopts.cpp create mode 100644 settings/konqhtml/htmlopts.h create mode 100644 settings/konqhtml/javaopts.cpp create mode 100644 settings/konqhtml/javaopts.h create mode 100644 settings/konqhtml/jsopts.cpp create mode 100644 settings/konqhtml/jsopts.h create mode 100644 settings/konqhtml/jspolicies.cpp create mode 100644 settings/konqhtml/jspolicies.h create mode 100644 settings/konqhtml/khtml_appearance.desktop create mode 100644 settings/konqhtml/khtml_behavior.desktop create mode 100644 settings/konqhtml/khtml_filter.desktop create mode 100644 settings/konqhtml/khtml_general.desktop create mode 100644 settings/konqhtml/khtml_java_js.desktop create mode 100644 settings/konqhtml/khttpoptdlg.cpp create mode 100644 settings/konqhtml/khttpoptdlg.h create mode 100644 settings/konqhtml/main.cpp create mode 100644 settings/konqhtml/main.h create mode 100644 settings/konqhtml/nsconfigwidget.ui create mode 100644 settings/konqhtml/pluginopts.cpp create mode 100644 settings/konqhtml/pluginopts.h create mode 100644 settings/konqhtml/policies.cpp create mode 100644 settings/konqhtml/policies.h create mode 100644 settings/konqhtml/policydlg.cpp create mode 100644 settings/konqhtml/policydlg.h create mode 100644 settings/performance/CMakeLists.txt create mode 100644 settings/performance/Messages.sh create mode 100644 settings/performance/kcmkonqyperformance.desktop create mode 100644 settings/performance/kcmperformance.cpp create mode 100644 settings/performance/kcmperformance.desktop create mode 100644 settings/performance/kcmperformance.h create mode 100644 settings/performance/konqueror.cpp create mode 100644 settings/performance/konqueror.h create mode 100644 settings/performance/konqueror_ui.ui create mode 100644 settings/performance/system.cpp create mode 100644 settings/performance/system.h create mode 100644 settings/performance/system_ui.ui create mode 100644 sidebar/CMakeLists.txt create mode 100644 sidebar/default_entries/CMakeLists.txt create mode 100644 sidebar/default_entries/bookmarks.desktop create mode 100644 sidebar/default_entries/history.desktop create mode 100644 sidebar/default_entries/home.desktop create mode 100644 sidebar/default_entries/places.desktop create mode 100644 sidebar/default_entries/remote.desktop create mode 100644 sidebar/default_entries/root.desktop create mode 100644 sidebar/default_entries/services.desktop create mode 100644 sidebar/history_module/CMakeLists.txt create mode 100644 sidebar/history_module/history_dlg.ui create mode 100644 sidebar/history_module/history_module.cpp create mode 100644 sidebar/history_module/history_module.h create mode 100644 sidebar/history_module/kcmhistory.cpp create mode 100644 sidebar/history_module/kcmhistory.desktop create mode 100644 sidebar/history_module/kcmhistory.h create mode 100644 sidebar/history_module/konqsidebar_history.desktop create mode 100644 sidebar/konq_sidebartng.desktop create mode 100644 sidebar/konqmultitabbar.cpp create mode 100644 sidebar/konqmultitabbar.h create mode 100644 sidebar/konqsidebarplugin.cpp create mode 100644 sidebar/konqsidebarplugin.h create mode 100644 sidebar/konqsidebartngrc create mode 100644 sidebar/module_manager.cpp create mode 100644 sidebar/module_manager.h create mode 100644 sidebar/places_module/CMakeLists.txt create mode 100644 sidebar/places_module/konqsidebar_places.desktop create mode 100644 sidebar/places_module/places_module.cpp create mode 100644 sidebar/places_module/places_module.h create mode 100644 sidebar/sidebar_part.cpp create mode 100644 sidebar/sidebar_part.h create mode 100644 sidebar/sidebar_widget.cpp create mode 100644 sidebar/sidebar_widget.h create mode 100644 sidebar/test/CMakeLists.txt create mode 100644 sidebar/test/konqsidebartest.cpp create mode 100644 sidebar/test/konqsidebartest.h create mode 100644 sidebar/test/modulemanagertest.cpp create mode 100644 sidebar/test/test.desktop create mode 100644 sidebar/trees/CMakeLists.txt create mode 100644 sidebar/trees/bookmark_module/CMakeLists.txt create mode 100644 sidebar/trees/bookmark_module/bookmark_item.cpp create mode 100644 sidebar/trees/bookmark_module/bookmark_item.h create mode 100644 sidebar/trees/bookmark_module/bookmark_module.cpp create mode 100644 sidebar/trees/bookmark_module/bookmark_module.h create mode 100644 sidebar/trees/dirtree_module/CMakeLists.txt create mode 100644 sidebar/trees/dirtree_module/dirtree_item.cpp create mode 100644 sidebar/trees/dirtree_module/dirtree_item.h create mode 100644 sidebar/trees/dirtree_module/dirtree_module.cpp create mode 100644 sidebar/trees/dirtree_module/dirtree_module.h create mode 100644 sidebar/trees/init/CMakeLists.txt create mode 100644 sidebar/trees/init/README create mode 100644 sidebar/trees/init/bookmarks_module.desktop create mode 100644 sidebar/trees/init/dirtree_module.desktop create mode 100644 sidebar/trees/init/remote/.directory create mode 100644 sidebar/trees/init/remote/CMakeLists.txt create mode 100644 sidebar/trees/init/remote/ftp/.directory create mode 100644 sidebar/trees/init/remote/ftp/CMakeLists.txt create mode 100644 sidebar/trees/init/remote/ftp/kde_ftp.desktop create mode 100644 sidebar/trees/init/remote/web/.directory create mode 100644 sidebar/trees/init/remote/web/CMakeLists.txt create mode 100644 sidebar/trees/init/remote/web/apps_web.desktop create mode 100644 sidebar/trees/init/remote/web/dot_web.desktop create mode 100644 sidebar/trees/init/remote/web/kde_web.desktop create mode 100644 sidebar/trees/init/remote/web/look_web.desktop create mode 100644 sidebar/trees/init/services/.directory create mode 100644 sidebar/trees/init/services/CMakeLists.txt create mode 100644 sidebar/trees/init/services/applications.desktop create mode 100644 sidebar/trees/init/services/printsystem.desktop create mode 100644 sidebar/trees/init/services/settings.desktop create mode 100644 sidebar/trees/konq_sidebartree.cpp create mode 100644 sidebar/trees/konq_sidebartree.h create mode 100644 sidebar/trees/konq_sidebartreeitem.cpp create mode 100644 sidebar/trees/konq_sidebartreeitem.h create mode 100644 sidebar/trees/konq_sidebartreemodule.h create mode 100644 sidebar/trees/konq_sidebartreetoplevelitem.cpp create mode 100644 sidebar/trees/konq_sidebartreetoplevelitem.h create mode 100644 sidebar/trees/konqsidebar_oldtreemodule.cpp create mode 100644 sidebar/trees/konqsidebar_oldtreemodule.h create mode 100644 sidebar/trees/konqsidebar_tree.desktop create mode 100644 sidebar/web_module/CMakeLists.txt create mode 100644 sidebar/web_module/TODO create mode 100644 sidebar/web_module/konqsidebar_web.desktop create mode 100644 sidebar/web_module/test_websidebar.html create mode 100644 sidebar/web_module/web_module.cpp create mode 100644 sidebar/web_module/web_module.h create mode 100644 src/CMakeLists.txt create mode 100644 src/KonqMainWindowAdaptor.cpp create mode 100644 src/KonqMainWindowAdaptor.h create mode 100644 src/KonqViewAdaptor.cpp create mode 100644 src/KonqViewAdaptor.h create mode 100644 src/KonquerorAdaptor.cpp create mode 100644 src/KonquerorAdaptor.h create mode 100644 src/delayedinitializer.cpp create mode 100644 src/delayedinitializer.h create mode 100644 src/htmldefaults.h create mode 100644 src/konqactions.cpp create mode 100644 src/konqactions.h create mode 100644 src/konqanimatedlogo.cpp create mode 100644 src/konqanimatedlogo_p.h create mode 100644 src/konqapplication.cpp create mode 100644 src/konqapplication.h create mode 100644 src/konqbookmarkbar.cpp create mode 100644 src/konqbookmarkbar.h create mode 100644 src/konqbookmarkmenu.cpp create mode 100644 src/konqbookmarkmenu.h create mode 100644 src/konqbookmarkmenu_p.h create mode 100644 src/konqcloseditem.cpp create mode 100644 src/konqcloseditem.h create mode 100644 src/konqclosedwindowsmanager.cpp create mode 100644 src/konqclosedwindowsmanager.h create mode 100644 src/konqcombo.cpp create mode 100644 src/konqcombo.h create mode 100644 src/konqdraggablelabel.cpp create mode 100644 src/konqdraggablelabel.h create mode 100644 src/konqextendedbookmarkowner.h create mode 100644 src/konqextensionmanager.cpp create mode 100644 src/konqextensionmanager.h create mode 100644 src/konqfactory.cpp create mode 100644 src/konqfactory.h create mode 100644 src/konqframe.cpp create mode 100644 src/konqframe.h create mode 100644 src/konqframecontainer.cpp create mode 100644 src/konqframecontainer.h create mode 100644 src/konqframestatusbar.cpp create mode 100644 src/konqframestatusbar.h create mode 100644 src/konqframevisitor.cpp create mode 100644 src/konqframevisitor.h create mode 100644 src/konqguiclients.cpp create mode 100644 src/konqguiclients.h create mode 100644 src/konqhistory.h create mode 100644 src/konqhistorydialog.cpp create mode 100644 src/konqhistorydialog.h create mode 100644 src/konqhistorymanager.cpp create mode 100644 src/konqhistorymanager.h create mode 100644 src/konqhistorymodel.cpp create mode 100644 src/konqhistorymodel.h create mode 100644 src/konqhistoryproxymodel.cpp create mode 100644 src/konqhistoryproxymodel.h create mode 100644 src/konqhistorysettings.cpp create mode 100644 src/konqhistorysettings.h create mode 100644 src/konqhistoryview.cpp create mode 100644 src/konqhistoryview.h create mode 100644 src/konqmain.cpp create mode 100644 src/konqmainwindow.cpp create mode 100644 src/konqmainwindow.h create mode 100644 src/konqmainwindowfactory.cpp create mode 100644 src/konqmainwindowfactory.h create mode 100644 src/konqmisc.cpp create mode 100644 src/konqmisc.h create mode 100644 src/konqmouseeventfilter.cpp create mode 100644 src/konqmouseeventfilter.h create mode 100644 src/konqnewsessiondlg_base.ui create mode 100644 src/konqopenurlrequest.h create mode 100644 src/konqpixmapprovider.cpp create mode 100644 src/konqpixmapprovider.h create mode 100644 src/konqprivate_export.h create mode 100644 src/konqrun.cpp create mode 100644 src/konqrun.h create mode 100644 src/konqsessiondlg.cpp create mode 100644 src/konqsessiondlg.h create mode 100644 src/konqsessiondlg_base.ui create mode 100644 src/konqsessionmanager.cpp create mode 100644 src/konqsessionmanager.h create mode 100644 src/konqsettings.cpp create mode 100644 src/konqsettings.h create mode 100644 src/konqsettingsxt.kcfgc create mode 100644 src/konqstatusbarmessagelabel.cpp create mode 100644 src/konqstatusbarmessagelabel.h create mode 100644 src/konqtabs.cpp create mode 100644 src/konqtabs.h create mode 100644 src/konqueror.kcfg create mode 100644 src/konqueror.qrc create mode 100644 src/konqueror.rc create mode 100644 src/konqundomanager.cpp create mode 100644 src/konqundomanager.h create mode 100644 src/konqurl.cpp create mode 100644 src/konqurl.h create mode 100644 src/konqview.cpp create mode 100644 src/konqview.h create mode 100644 src/konqviewmanager.cpp create mode 100644 src/konqviewmanager.h create mode 100644 src/ksortfilterproxymodel.cpp create mode 100644 src/ksortfilterproxymodel.h create mode 100644 src/ktabbar.cpp create mode 100644 src/ktabbar.h create mode 100644 src/ktabwidget.cpp create mode 100644 src/ktabwidget.h create mode 100644 src/org.kde.Konqueror.HistoryManager.xml create mode 100644 src/org.kde.Konqueror.Main.xml create mode 100644 src/org.kde.Konqueror.MainWindow.xml create mode 100644 src/org.kde.Konqueror.SessionManager.xml create mode 100644 src/org.kde.Konqueror.UndoManager.xml create mode 100644 src/tests/CMakeLists.txt create mode 100644 src/tests/centralwidget.cpp create mode 100644 src/tests/centralwidget.h create mode 100644 webenginepart/CMakeLists.txt create mode 100644 webenginepart/COPYING.LIB create mode 100644 webenginepart/Mainpage.dox create mode 100644 webenginepart/Messages.sh create mode 100644 webenginepart/README create mode 100644 webenginepart/TODO create mode 100644 webenginepart/autotests/CMakeLists.txt create mode 100644 webenginepart/autotests/data/hello.html create mode 100644 webenginepart/autotests/data/page-with-link.html create mode 100644 webenginepart/autotests/webengine_partapi_test.cpp create mode 100644 webenginepart/autotests/webengine_testutils.h create mode 100644 webenginepart/autotests/webenginepartcookiejar_test.cpp create mode 100644 webenginepart/autotests/webenginepartcookiejar_test.h create mode 100644 webenginepart/icons/128-apps-webengine.png create mode 100644 webenginepart/icons/16-apps-webengine.png create mode 100644 webenginepart/icons/22-apps-webengine.png create mode 100644 webenginepart/icons/32-apps-webengine.png create mode 100644 webenginepart/icons/48-apps-webengine.png create mode 100644 webenginepart/icons/64-apps-webengine.png create mode 100644 webenginepart/icons/CMakeLists.txt create mode 100644 webenginepart/icons/webengine.svg create mode 100755 webenginepart/scripts/codingstyle.sh create mode 100755 webenginepart/scripts/create_release_package.sh create mode 100644 webenginepart/src/CMakeLists.txt create mode 100644 webenginepart/src/about/CMakeLists.txt create mode 100644 webenginepart/src/about/intro.html create mode 100644 webenginepart/src/about/konq.css create mode 100644 webenginepart/src/about/konq_aboutpage.cpp create mode 100644 webenginepart/src/about/konq_aboutpage.desktop create mode 100644 webenginepart/src/about/konq_aboutpage.h create mode 100644 webenginepart/src/about/konqaboutpage.desktop create mode 100644 webenginepart/src/about/launch.html create mode 100644 webenginepart/src/about/plugins.html create mode 100644 webenginepart/src/about/plugins_rtl.html create mode 100644 webenginepart/src/about/specs.html create mode 100644 webenginepart/src/about/tips.html create mode 100644 webenginepart/src/about/top-left-konqueror.png create mode 100644 webenginepart/src/error.html create mode 100644 webenginepart/src/settings/webengine_filter.cpp create mode 100644 webenginepart/src/settings/webengine_filter.h create mode 100644 webenginepart/src/settings/webenginesettings.cpp create mode 100644 webenginepart/src/settings/webenginesettings.h create mode 100644 webenginepart/src/ui/featurepermissionbar.cpp create mode 100644 webenginepart/src/ui/featurepermissionbar.h create mode 100644 webenginepart/src/ui/passwordbar.cpp create mode 100644 webenginepart/src/ui/passwordbar.h create mode 100644 webenginepart/src/ui/searchbar.cpp create mode 100644 webenginepart/src/ui/searchbar.h create mode 100644 webenginepart/src/ui/searchbar.ui create mode 100644 webenginepart/src/utils.h create mode 100644 webenginepart/src/webenginepage.cpp create mode 100644 webenginepart/src/webenginepage.h create mode 100644 webenginepart/src/webenginepart.cpp create mode 100644 webenginepart/src/webenginepart.desktop create mode 100644 webenginepart/src/webenginepart.h create mode 100644 webenginepart/src/webenginepart.rc create mode 100644 webenginepart/src/webenginepart_ext.cpp create mode 100644 webenginepart/src/webenginepart_ext.h create mode 100644 webenginepart/src/webenginepartcookiejar.cpp create mode 100644 webenginepart/src/webenginepartcookiejar.h create mode 100644 webenginepart/src/webenginepartdownloadmanager.cpp create mode 100644 webenginepart/src/webenginepartdownloadmanager.h create mode 100644 webenginepart/src/webengineparterrorschemehandler.cpp create mode 100644 webenginepart/src/webengineparterrorschemehandler.h create mode 100644 webenginepart/src/webenginepartfactory.cpp create mode 100644 webenginepart/src/webenginepartfactory.h create mode 100644 webenginepart/src/webengineparthtmlembedder.cpp create mode 100644 webenginepart/src/webengineparthtmlembedder.h create mode 100644 webenginepart/src/webenginepartkiohandler.cpp create mode 100644 webenginepart/src/webenginepartkiohandler.h create mode 100644 webenginepart/src/webengineview.cpp create mode 100644 webenginepart/src/webengineview.h create mode 100644 webenginepart/src/webenginewallet.cpp create mode 100644 webenginepart/src/webenginewallet.h create mode 100644 webenginepart/src/webhistoryinterface.cpp create mode 100644 webenginepart/src/webhistoryinterface.h create mode 100644 webenginepart/src/websslinfo.cpp create mode 100644 webenginepart/src/websslinfo.h create mode 100644 webenginepart/testfiles/embed_tag_test.html create mode 100644 webenginepart/testfiles/form_save_restore_test.html create mode 100644 webenginepart/testfiles/frameset_test.html create mode 100644 webenginepart/testfiles/frametest/frame_a.html create mode 100644 webenginepart/testfiles/frametest/frame_b.html create mode 100644 webenginepart/testfiles/frametest/frame_c.html create mode 100644 webenginepart/testfiles/frametest/frame_navigation.html create mode 100644 webenginepart/testfiles/js.html create mode 100644 webenginepart/testfiles/link_tests.html create mode 100644 webenginepart/testfiles/meta_tag_refresh_test.html create mode 100644 webenginepart/tests/CMakeLists.txt create mode 100644 webenginepart/tests/webenginepart_tester.cpp diff --git a/.arcconfig b/.arcconfig new file mode 100644 index 0000000..377c7ec --- /dev/null +++ b/.arcconfig @@ -0,0 +1,3 @@ +{ + "phabricator.uri" : "https://phabricator.kde.org/" +} diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..1f3975c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,16 @@ +Started by Torben Weis +Maintained by David Faure +Current team : + Simon Hausmann + Matthias Welk + Michael Reiher + Alexander Neundorf (List views) + Michael Brade (List Views, I/O lib) + Lars Knoll (HTML rendering engine) + Antti Koivisto (HTML rendering engine) + Waldo Bastian (HTML rendering engine) + Matt Koss (I/O lib) + Stephan Kulow (I/O lib) + Richard Moore (Java applet support) + Dina Rogozin (Java applet support) + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7b0a124 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.0) + +project(Konqueror) + +set(QT_MIN_VERSION "5.9.0") +set(KF5_MIN_VERSION "5.38.0") # get new ECM layout + +find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) + +include(FeatureSummary) + +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) + +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings NO_POLICY_SCOPE) +include(ECMInstallIcons) +include(ECMSetupVersion) +include(ECMAddAppIcon) +include(ECMQtDeclareLoggingCategory) +include(CMakePackageConfigHelpers) + +set(KONQUEROR_LIB_VERSION "5.0.97") +set(KONQUEROR_VERSION "${KONQUEROR_LIB_VERSION}") + +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Widgets WebEngineWidgets) +find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Parts KCMUtils Archive Crash WindowSystem Init IconThemes DBusAddons) +find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS KDELibs4Support) + +find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS Activities DocTools) # Optional + +if(NOT Qt5WebEngineWidgets_VERSION VERSION_LESS "5.13.0") + add_definitions(-DWEBENGINE_PDF_VIEWER) +endif() + +find_package(X11) +set(KONQ_HAVE_X11 ${X11_FOUND}) + +if (X11_FOUND) + find_package(Qt5 REQUIRED X11Extras) +endif(X11_FOUND) + +add_definitions(-DQT_USE_FAST_OPERATOR_PLUS) +add_definitions(-DQT_NO_URL_CAST_FROM_STRING) + +include (CheckSymbolExists) +check_symbol_exists(mallinfo "malloc.h" KDE_MALLINFO_MALLOC) +check_symbol_exists(mallinfo "stdlib.h" KDE_MALLINFO_STDLIB) +# TODO KDE_MALLINFO_FIELD_hblkhd +# TODO KDE_MALLINFO_FIELD_uordblks +# TODO KDE_MALLINFO_FIELD_usmblks + +configure_file (config-konqueror.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-konqueror.h ) +configure_file (konqueror-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/konqueror-version.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_subdirectory( libkonq ) +add_subdirectory( src ) +add_subdirectory( client ) +if(BUILD_TESTING) + add_subdirectory( autotests ) +endif() +add_subdirectory( webenginepart ) + +add_subdirectory( pics ) +#add_subdirectory( sidebar ) +add_subdirectory( settings ) +add_subdirectory( plugins ) + +if (KF5DocTools_FOUND) + add_subdirectory( doc ) +endif() + +########### install files ############### +install( PROGRAMS + kfmclient.desktop kfmclient_html.desktop kfmclient_war.desktop kfmclient_dir.desktop + konqbrowser.desktop + DESTINATION ${KDE_INSTALL_APPDIR} ) +install(FILES org.kde.konqueror.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) + +# Make sure kfmclient can find konqueror.desktop even if people remove it from the K menu (#62242) +# This is why konqueror.desktop is installed into services. +install( FILES org.kde.konqueror.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) + +install(FILES konqy_preload.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR}) + +if (${ECM_VERSION} STRGREATER "5.58.0") + install(FILES konqueror.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) +else() + install(FILES konqueror.categories DESTINATION ${KDE_INSTALL_CONFDIR}) +endif() + +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) +ki18n_install(po) +if (KF5DocTools_FOUND) + kdoctools_install(po) +endif() diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/COPYING.DOC b/COPYING.DOC new file mode 100644 index 0000000..2f7e03c --- /dev/null +++ b/COPYING.DOC @@ -0,0 +1,451 @@ + + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..707f6b4 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,436 @@ +This ChangeLog is really outdated and only kept for nostalgic historical reasons. +Use svn log instead. + +2001-05-10 Mark Deneen + + * Implemented header of vertical toggle views, with support for + a caption text and a close-button + +2001-05-05 David Faure + + * konq_mainwindow.cc: Set WDestructiveClose again when going + to fullscreen mode (Qt bug), to prevent Alt+F4 from crashing. + * konq_misc.cc: Only abort full-screen mode for windows on the + current desktop. + +2001-05-01 Simon Hausmann + + * konq_mainwindow.cc : moved the connect and disconnect calls + to/from the highlighting signals of the actioncollections into + two separate methods, for cleanup, and use the qt child deletion + mechanism to delete the bookmark actioncollection + +2001-04-28 Simon Hausmann + + * konq_actions.h (class KonqGoURLAction): new class, derived + from KAction, used for the 'go url' action. when plugging the + action into a toolbar make sure to align the button right. + Otherwise the toolbar layout completely fucks up and QToolBar + starts flickering like mad, when the window width is getting + small than the lenght of the url in the combobox. + + * konq_mainwindow.cc (initActions): use KonqGoURLAction + +2001-04-27 Simon Hausmann + + * konq_mainwindow.cc (goURL): new slot, sending a fake key + event to the lineedit, acting like the user pressing return + (initActions): allocate a "Go" action and connect it to the + new goURL slot + + * konqueror.rc: inserted go action into the locationbar + +2001-04-07 Simon Hausmann + + * konq_mainwindow.cc (slotReload): call m_currentView->lockHistory(), + to fix #23818 + * konq_view.cc/h (reload): removed obsolete method + +2001-03-31 David Faure + + * konq_mainwindow.cc(slotRunFinished): Stop wheel animation when a + konqrun fails and we have no view. + +2001-03-25 Simon Hausmann + + * iconview/konq_iconview.cc (KonqKfmIconView): specify a status text for + some actions. Likewise for some actions in KonqDirPart. Also call + setHighlightingEnabled in the KonqDirPart constructor + + * konq_mainwindow.cc (slotShowMenuBar): call saveMainWindowSettings and + KGlobal::config()->sync() after toggling the visiblity of the menubar, + just like it is done for toolbars. + (slotPartActivated): connect and disconnect to/from the actionStatusText + and clearStatusText signals of the part's actioncollection + +2001-03-02 Simon Hausmann + + * konq_view.cc, konq_browseriface.cc/h: Utilize and implement the newly + added KParts::BrowserInterface + +2001-02-06 Simon Hausmann + + * konq_mainwindow.cc (openBookmarkURL): Patch by + Marco Krohn to call openFilteredURL + instead of openURL. Allows environment variables in bookmarks and + other sugar. + +2001-01-28 Stephan Kulow + + * konq_mainwindow.cc (initActions): Plug the actions into a KAccel to + fix short cuts in full screen mode + +2001-01-16 Simon Hausmann + + * konq_actions.cc (fillHistoryPopup), + libkonq/kbookmarkmenu.cc (fillBookmarkMenu): When a Website has + "&" in the Title, make sure to transform it into "&&" before + inserting it into a QPopupMenu (for history or for bookmarks) , to + avoid QPopupMenu interpreting it as accelerator. + + +2001-01-15 David Faure + + * konq_aboutpage.cc, konq_mainwindow.cc: Support for "about:konqueror". + Credits to Simon for the part, and Torsten for the icons. + +2001-01-14 David Faure + + * konq_viewmgr.cc (loadItem): Use openView instead of view->openURL, + so that "view-follows-view" is also applied on startup. Fixes #17679. + + * konq_mainwindow.cc etc.: Lock to current location doesn't make the + view passive anymore. This allows to e.g. change the view mode. + + * konq_frame.cc: Added Lock / Unlock to view statusbar's popupmenu. + +2001-01-13 David Faure + + * konq_dirpart.cc etc.: Always paste to current directory, even + when an item is selected. + +2001-01-12 David Faure + + * konq_viewmgr.cc (loadViewProfile): Set active part before loading + URL, so that the URL appears in the location bar. + + * konq_mainwindow.cc, konq_dirpart.cc: Store find part into history, + in order to restore it when pressing back. + +2001-01-11 David Faure + + * konq_mainwindow.*, konq_view.*: Store caption in the view, + fixes caption when switching parts or removing one. + +2001-01-11 Carsten Pfeiffer + + * konq_historymgr.*: KonqHistoryManager now implements the new + HistoryProvider (from KParts) + +2001-01-09 Alexander Neundorf + + * konq_mainwindow.*, konq_dirpart.*: Copy (F7) and move (F8) are now + available as soon as some files are selected in a directory view. + A dialog asks for the destination. + +2001-01-08 Simon Hausmann + + * KonquerorIface.cc (openBrowserWindow), + (createNewWindow), + (createNewWindow), + (createBrowserWindowFromProfile), + (createBrowserWindowFromProfile), + (createBrowserWindowFromProfileAndURL), + (createBrowserWindowFromProfileAndURL): changed return type from void + to DCOPRef + +2001-01-07 David Faure + + * konq_mainwindow.*: One KonqRun per view (del the old one in setRun), + only one with no view associated (KonqMainWindow::m_initialKonqRun). + This fixes "clicking on two bookmarks very fast opens both URLs, + splitting the view". + +2000-12-28 Simon Hausmann + + * konq_viewmgr.cc (loadViewProfile): When loading an empty profile + (in particular the webbrowsing one) , activate the clear_location + action. This gives the focus to the location bar -> the user can + type in an url right away when loading the webbrowsing profile + +2000-12-27 Simon Hausmann + + * konq_mainwindow.cc (enableAllActions): for iterating over all actions + don't use the action( int index ) method of KActionCollection but instead + retrieve a QValueList and iterate over that, as the =+(int) + operator of QDictIterator isn't really fast + + ----- KDE 2.1 BETA 1 RELEASE ---- + +2000-12-12 David Faure + + * konq_viewmgr.cc: Fixed saving of profiles containing views + "locked to their current location". The attribute was missing from + the profile. + + * konq_mainwindow.cc: Save and restore the preferred service in for + each toolbar 'viewmode' button. + +2000-12-10 David Faure + + * konq_mainwindow.cc, konq_view.*, browserextension.*: Fixed + the initial state of the common actions (cut,copy,paste etc.). + Had to move all the handling of the action states to browserextension. + +2000-12-10 Simon Hausmann + + * konqview_example.tar.gz: removed outdated example. + + * konq_frame.h, konq_view.{cc,h}, + konq_factory.{cc,h}, konq_mainwindow.{cc,h} : Code cleanups, + added missing const's here and there, removed some old unused + code. + +2000-12-09 Simon Hausmann + + * konq_actions.{cc,h}: Added KonqViewModeAction, a KRadioAction + with an additional delayed popupmenu + + * konq_mainwindow.{cc,h}: Changed the toolbar viewmode buttons to + show the available viewmodes grouped. For directories they are + grouped by iconview and listview. This way one can quickly + switch between the favourite list and iconview while still having + the complete choice of viewmodes via delayed popupmenus + (idea by Torsten and David) + + +2000-12-08 David Faure + + * konq_mainwindow.cc (openURL): Support for about:blank + Fix for severe problems with the activation of the standard actions. + The state of the action is now stored in each KonqView. + +2000-12-08 Malte Starostik + + * libkonq/, iconview/: Preview for HTML files implemented. + +2000-12-08 David Faure and Carsten Pfeiffer + + * dirtree/*: Major rewrite of the directory tree, to make it generic. + It can now handle toplevel items over to specific modules. Current + modules available are the dirtree module (directory listing) and the + history module (for a way to visualize the persistent history). + +2000-12-06 Matthias Elter + + * konq_mainwindow.cc: Turned the Configure submenu into a single dialog. + +2000-12-02 David Faure + + * konq_mainwindow.cc (slotToolFind): "Find Files" now embeds the kfind + part, and the result of the search is connected to the current directory + part. "Close" or opening any other URL closes the 'find' part. + Thanks to Eric Coquelle for the kfind classes, and to jpmartin for + pushing us to do this :) + + * konq_viewmgr.cc: Support for suicidal passive views, more arguments + to splitView and splitWindow. + + * konq_guiclients.cc: Duplicated code removed, uses splitWindow now. + +2000-11-30 David Faure + + * konq_mainwindow.cc: Use current profile in "New Window" to fix #16283. + +2000-11-28 David Faure + + * konq_actions.cc: Accel (Alt+O in English) to give focus to location bar, + shown by the label. + + * konq_profiledlg.cc: Ported to KListView to fix problems with selection. + +2000-11-26 David Faure + + * konq_misc.cc, kfmclient.cc, KonquerorIface.cc: Speed up for URLs opened + from another process using KRun (e.g. kdesktop's Minicli), by passing the + mimetype through to konqueror. + +2000-11-25 David Faure + + * konq_misc.cc: Fixed location bar not showing the URL asap. + + * konq_mainwindow.cc : Icons for the configure submenu. + + * konq_actions.cc : KonqHistoryAction turned into KToolBarPopupAction. + Drag the "Location" label to start a drag with the current URL. + +2000-11-25 Simon Hausmann + + * konq_view.cc (connectPart): Install new url event filter for plain + krops and for browserviews with the enableURLDropHandling property enabled + (eventFilter): New eventfilter which listens for url drop events + +Sat Nov 25 17:38:27 2000 Carsten Pfeiffer + + * konq_mainwindow.cc: Completion handling overhauled. We have + one KonqHistoryManager, which holds a KCompletion object and syncs + the history with the completion. + + * konq_view.cc: + set m_bAborted before calling slotCompleted in slotCanceled() + feed the history manager + + * konq_actions.cc: use KonqHistoryCombo that doesn't mess with the + competion-object, we do our own synchronization now. + + * libkonq/ added konq_history* + +2000-11-22 David Faure + + * konq_listview.cc: Added "Default" Icon Size, which corresponds to + KIcon::Small (but when switching to icon view, it becomes whatever's + configured for the "Desktop" group). + +2000-11-21 David Faure + + * konq_listview.cc: Case Insensitive Sort option, on by default. + + * Views: Major rework of the "delayed mimetypes determination" feature, + to make it available to the list view. This makes the list view + MUCH faster in big directories. + This also showed a bug in the listview background painting -> fixed. + +2000-11-19 David Faure + + * Views: Implemented in-place renaming of items ("Rename" in menus, F2) + +2000-11-17 David Faure + + * konq_profiledlg.cc: Made checkbox states persistent (saved to config) + + * konq_run.cc: Check that when we call KRun from KonqRun, it's not going + to launch another konqueror. + * konq_guiclients.cc: Build toggle-view actions in the actioncollection + of the mainwindow, so that it's possible to assign them a shortcut. + +2000-11-16 David Faure + + * konq_viewmgr.cc: Patch by Keunwoo Lee to + implement dynamic accels for the profile submenu. + +2000-11-15 David Faure + + * konq_drag.cc: Export URLs as text/plain as well. + + * konq_mainwindow.cc: Implemented auto-saving of toolbars (KMainWindow), + removed "Save Settings". + Fixed "clicking on directory in dirtree uses wrong view mode for dirs". + * konq_iconview.cc: Added +/- buttons for changing the icon size. + +2000-11-06 David Faure + + * konq_operations.cc: statURL, calls a slot when it stat'ed + the url and created a kfileitem for it. + Used in doDrop when the destination's kfileitem is unknown. Fixes #14739. + Also, KPropsDlg now does a similar thing when called with a KURL. + +2000-11-05 David Faure + + * konqueror.rc: Moved the "open with" actions to the Location menu, + and added a separator to the action list. + + * konq_view.cc (connectPart): moved call to setSaveViewPropertiesLocally + (used to be in various places in KonqMW) so that the flag is + also correct when switching views. + + * konq_dirpart.cc and directory views: apply background color and pixmap + to the viewport(), and updated konq_iconview to do the same. This fixes + many inconsistencies, and makes resizing a window much faster & smoother. + Note that it has to be the viewport and not the widget, otherwise in the + listview, the box between the scrollbars appears colored/pixmap-ed. + + * konq_mainwindow.cc: action renamed View Properties Saved In Directory + +2000-11-04 David Faure + + * konq_viewmgr.cc: now takes care of enableAllActions. + Show led and active statusbar even in the tree+icon configuration + (the rule is now "more than one view", not "more than one activeable + view"). This should remove some confusion. + + * konq_frame.cc: "Remove View" in RMB on statusbar. + Don't try to activate passive views when clicking statusbar. + Different background color on statusbar for active view. + + * konq_mainwindow.cc: Fixes for "Remove Active View" enabling, + to avoid ending up with a lonely embedded konsole, and some + cleanup of code for enabling other view-related actions. + Introducing updateViewActions for common code between enableAllActions + and slotPartActivated. Fixes a few glitches in action activation. + +2000-10-31 Carsten Pfeiffer + + * libkonq: Implemented "Text preview" functionality + +2000-10-26 David Faure + + * keditbookmarks/*: Finally, a bookmark editor for konqueror. + + * kbookmarkmanager.*: Separated from kbookmark.* after dcopidl dying on + "mutable" :). Implemented DCOP notifications between processes. + Implemented "internal bookmark address". KonqBookmarkManager is no more. + + * kbookmarkbar.*: Update for XML bookmarks, fill in aboutToShow, update + sub-menus upon changed() signal, enabled "Add Bookmark" and "New Folder" + +2000-10-24 David Faure + + * kbookmark*: Reimplemented the bookmarks, they are now saved in XML. + Desktop files are imported if the XML file doesn't exist (it's + immediately saved, so this should happen only once). + +2000-10-22 Simon Hausmann + + * konq_view.{cc,h} : changed part->child( 0, "KParts::BE" ) calls to + use the new childObject method in BrowserExtension + +2000-10-22 David Faure + + * dirtree/konq_dirtree.cc: Fixed support for devices in the directory + tree. It currently requires MountPoint in the device desktop file. + + * listview/konq_textviewwidget.cc: Only the Name column is now + selected, and used as a drop area - like in other listviews. + This requires the fix in KListView to work properly. + +2000-10-21 David Faure + + * Fix for linked views saved in profile, introducing isLoadingProfile(). + +2000-10-20 David Faure + + * konq_misc.cc: Use webbrowsing profile for *.html *.htm as well. + +2000-10-20 Simon Hausmann + + * Duplicate window duplicates the history as well. + +[...... long period of development up to KDE 2.0 ommitted .....] + +1999-03-15 Michael Reiher + + * Implemented an ActiveViewIndicator : KonqFrame + +1999-02-28 Simon Hausmann + + * Rewrite from scratch, with completely new IDL + +1999-02-09 David Faure + + * Source imported in kdebase/konqueror + +1999-01-25 Torben Weis + + * Initial import of kfmIII in corba/kfm + + diff --git a/DESIGN b/DESIGN new file mode 100644 index 0000000..a99c76f --- /dev/null +++ b/DESIGN @@ -0,0 +1,106 @@ +Konqueror Design Document + +Author: + David Faure, faure@kde.org + +Last modified: 25 September 2007 + +Overall design of konqueror : +============================= + +The design of konqueror is based on the KParts part/mainwindow mechanism +(basically, konqueror can embed several parts, putting each one inside a view : +icon views, tree views, html views...) + +The main(), including all the startup mechanism is in konq_main.* + +The main window contains several "views", in order to show several URLs +at once, possibly using several modes. Each view is a KonqView. +The KonqView contains the child part, which can be any KParts::ReadOnlyPart. +For instance: +- a directory view provided by DolphinPart +- an HTML view provided by KHTMLPart +- any other KParts::ReadOnlyPart with or without BrowserExtension + +Where to find those classes +=========================== + +src/* : This is where konqueror is. + konqrun.* : Re-implementation of KRun (see libkio) for konqueror. + Responsible for finding appropriate view<->mimetype bindings. + konqview.* : KonqView, class used by KonqMainView to handle child views + konqframe.* : KonqFrame and KonqFrameHeader (handles view-statusbar). + konqmain.* : The main() + konqmainwindow.* : KonqMainWindow, the main window :) + konqviewmanager.*: View manager. Handles view creation, activation, splitters etc. +about/* : The about part, shows the about page on startup +client/* : kfmclient, for talking to running konqueror processes +sidebar/* : The konqueror sidebar (framework+plugins) + +Libs used by konqueror +====================== + +From kdelibs: +kdecore - mimetypes, services +kdeui - widgets +kparts - component model +khtml - HTML rendering +kio - I/O stuff, bookmarks, properties dialog + +From kdebase: +libkonq - templates ("new") menu, RMB popup menu, file operations + +How konqueror opens URLs +======================== + +KonqMainWindow: + + openFilteredURL or slotOpenURLRequest + | + | + -----openUrl---- + | | | + | | | + | KonqRun KRun + | | + | | + openView + | \----- splitView to create a new one +KonqView: | + changeViewMode + | + [switchView if different mode required] + | + openUrl [emits openURLEvent (after calling openURL)] +Part: | + | + openUrl [emits started, progress info, completed] + ... + + +How history is implemented +========================== + +From the konqueror side: + +* KonqView has a list of history items. Each item contains a URL, +and a QByteArray for the view to store its stuff in the format that suits it best. +It calls saveState() at various points of time (right after starting loading the URL, +when the loading is completed, and right before loading another URL). Reason: +among other things, many views store the x and y offset of their scrollview in there. +It calls restoreState() when restoring a particular item out of the history list. + +From the khtml side: + +* Site with no frames: no problem, it just obeys to saveState/restoreState. + +* Site with frames: +KHTMLPart saves the whole structure (all frames, and their URL) in the +history buffer (saveState/restoreState). +Every time a frame changes its URL, we want a new item in the history. +But when this happens, since it's internal to khtml, konqueror wouldn't know +about it. That's why there is the openUrlNotify() signal in browser extension +(see there for extensive docu about it). +When khtml emits it, KonqView creates a new history entry and fills it +(calling saveState). + diff --git a/DESIGN_config b/DESIGN_config new file mode 100644 index 0000000..d482107 --- /dev/null +++ b/DESIGN_config @@ -0,0 +1,43 @@ +Date: Thu, 1 Apr 1999 11:51:03 +0200 +From: David Faure +To: kfm-devel@kde.org +Subject: How to choose between builtin and external application : proposal + +How to configure between builtin and external viewers ? +I discussed this with a friend, and here is what we come up with : + +* global defaults, set in kcontrol, for each mimetype group: + +text : use builtin viewer (yes/no) [checkbox] +image : use builtin viewer (yes/no) [checkbox] +other : use builtin viewer (yes/no) [checkbox] (i.e. application/*, like dvi, ps...) + +* then, in the properties dialog for every mimetype: +- use default (checkbox as "no change") +- use builtin viewer (checkbox as "on") +- use external application (checkbox as "off") + +(=> saved as X-KDE-AutoEmbed=true/false or no entry) + +This way, one can set choose between builtin and external for all text / +images files, and set individual values too (e.g. an icon-team artist would +set up external for xpm, to edit them, and builtin for jpeg, gif, ... to +simply view them). I would personnally set normal-text and english-text to +builtin (to view READMEs) but c++, h, java, ... to my editor. + +And one that doesn't like embedded viewers (like Martin ;)) can set +defaults to 'no' without having to change all mimetypes (text, c, c++, ...) +but still use libkhtml for HTML pages, by setting 'use builtin' in the +mimetype text/html - this is the way to keep the exact (though +inconsistent) behaviour of 1.1-kfm. + +I suggest that factory defaults (i.e. configuration for first-time users) +would be set to 'yes' for the three groups (-> use builtin) +and would be 'use default' for mimetypes. +This for speed reasons (embedded viewers are really fast) and also to show +the new features ;) +KOffice mimetypes have it set to no, though -> click edits. + +Implemented on 09-04-2000 +David FAURE + diff --git a/Messages.sh b/Messages.sh new file mode 100644 index 0000000..cd9d5c9 --- /dev/null +++ b/Messages.sh @@ -0,0 +1,6 @@ +#! /usr/bin/env bash +$EXTRACTRC `find src -name \*.rc` >> rc.cpp || exit 11 +$EXTRACTRC `find src -name \*.ui` >> rc.cpp || exit 12 +$EXTRACTRC `find src -name \*.kcfg` >> rc.cpp +$XGETTEXT -kaliasLocal `find src -name \*.cc -o -name \*.cpp -o -name \*.h` rc.cpp -o $podir/konqueror.pot +rm -f rc.cpp diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt new file mode 100644 index 0000000..6366176 --- /dev/null +++ b/autotests/CMakeLists.txt @@ -0,0 +1,33 @@ +if (NOT WIN32) + +find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) + +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +########### konqviewmgrtest ############### + +ecm_add_test(konqviewmgrtest.cpp + LINK_LIBRARIES kdeinit_konqueror Qt5::Core Qt5::Gui kwebenginepartlib Qt5::WebEngineWidgets Qt5::Test) + +########### historymanagertest ############### + +ecm_add_test(historymanagertest.cpp + LINK_LIBRARIES KF5::Konq konquerorprivate Qt5::Core Qt5::Test) + +########### undomanagertest ############### + +ecm_add_test(undomanagertest.cpp + LINK_LIBRARIES kdeinit_konqueror Qt5::Core Qt5::Test) + +########### konqhtmltest ############### + +ecm_add_test(konqhtmltest.cpp + LINK_LIBRARIES kdeinit_konqueror kwebenginepartlib Qt5::Core Qt5::Test) + +########### konqviewtest ############### + +ecm_add_test(konqviewtest.cpp + LINK_LIBRARIES kdeinit_konqueror Qt5::Core Qt5::Test) + +endif (NOT WIN32) diff --git a/autotests/historymanagertest.cpp b/autotests/historymanagertest.cpp new file mode 100644 index 0000000..7119e13 --- /dev/null +++ b/autotests/historymanagertest.cpp @@ -0,0 +1,144 @@ +/* This file is part of KDE + Copyright (c) 2006 David Faure + + 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. +*/ + +#include +#include +#include + +#include +#include + +class HistoryManagerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void testGetSetMaxCount(); + void testGetSetMaxAge(); + void testAddHistoryEntry(); +}; + +QTEST_MAIN(HistoryManagerTest) + +void HistoryManagerTest::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); +} + +void HistoryManagerTest::testGetSetMaxCount() +{ + KonqHistoryManager mgr(nullptr); + const int oldMaxCount = mgr.maxCount(); + qDebug("oldMaxCount=%d", oldMaxCount); + mgr.emitSetMaxCount(4242); + QTest::qWait(100); // ### fragile. We have no signal to wait for, so we must just wait a little bit... + // Yes this is just a set+get test, but given that it goes via DBUS before changing the member variable + // we do test quite a lot with it. We can't really instantiate two KonqHistoryManagers (same dbus path), + // so we'd need two processes to test the dbus signal 'for real', if the setter changed the member var... + QCOMPARE(mgr.maxCount(), 4242); + mgr.emitSetMaxCount(oldMaxCount); + QTest::qWait(100); // ### fragile. Wait again otherwise the change will be lost + QCOMPARE(mgr.maxCount(), oldMaxCount); +} + +void HistoryManagerTest::testGetSetMaxAge() +{ + KonqHistoryManager mgr(nullptr); + const int oldMaxAge = mgr.maxAge(); + qDebug("oldMaxAge=%d", oldMaxAge); + mgr.emitSetMaxAge(4242); + QTest::qWait(100); // ### fragile. We have no signal to wait for, so we must just wait a little bit... + QCOMPARE(mgr.maxAge(), 4242); + mgr.emitSetMaxAge(oldMaxAge); + QTest::qWait(100); // ### fragile. Wait again otherwise the change will be lost + QCOMPARE(mgr.maxAge(), oldMaxAge); +} + +static void waitForAddedSignal(KonqHistoryManager *mgr) +{ + QEventLoop eventLoop; + QObject::connect(mgr, SIGNAL(entryAdded(KonqHistoryEntry)), &eventLoop, SLOT(quit())); + eventLoop.exec(QEventLoop::ExcludeUserInputEvents); +} + +static void waitForRemovedSignal(KonqHistoryManager *mgr) +{ + QEventLoop eventLoop; + QObject::connect(mgr, SIGNAL(entryRemoved(KonqHistoryEntry)), &eventLoop, SLOT(quit())); + eventLoop.exec(QEventLoop::ExcludeUserInputEvents); +} + +void HistoryManagerTest::testAddHistoryEntry() +{ + KonqHistoryManager mgr(nullptr); + qRegisterMetaType("KonqHistoryEntry"); + QSignalSpy addedSpy(&mgr, SIGNAL(entryAdded(KonqHistoryEntry))); + QSignalSpy removedSpy(&mgr, SIGNAL(entryRemoved(KonqHistoryEntry))); + const QUrl url(QStringLiteral("http://user@historymgrtest.org/")); + const QString typedUrl = QStringLiteral("http://www.example.net"); + const QString title = QStringLiteral("The Title"); + mgr.addPending(url, typedUrl, title); + + waitForAddedSignal(&mgr); + + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(removedSpy.count(), 0); + QList args = addedSpy[0]; + QCOMPARE(args.count(), 1); + KonqHistoryEntry entry = qvariant_cast(args[0]); + QCOMPARE(entry.url.url(), url.url()); + QCOMPARE(entry.typedUrl, typedUrl); + QCOMPARE(entry.title, QString()); // not set yet, still pending + QCOMPARE(int(entry.numberOfTimesVisited), 1); + + // Now confirm it + mgr.confirmPending(url, typedUrl, title); + // ## alternate code path: mgr.removePending() + + waitForAddedSignal(&mgr); + + QCOMPARE(addedSpy.count(), 2); + QCOMPARE(removedSpy.count(), 0); + args = addedSpy[1]; + QCOMPARE(args.count(), 1); + entry = qvariant_cast(args[0]); + QCOMPARE(entry.url.url(), url.url()); + QCOMPARE(entry.typedUrl, typedUrl); + QCOMPARE(entry.title, title); // now it's there + QCOMPARE(int(entry.numberOfTimesVisited), 1); + + // Now clean it up + + mgr.emitRemoveFromHistory(url); + + waitForRemovedSignal(&mgr); + + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(addedSpy.count(), 2); // unchanged + args = removedSpy[0]; + QCOMPARE(args.count(), 1); + entry = qvariant_cast(args[0]); + QCOMPARE(entry.url.url(), url.url()); + QCOMPARE(entry.typedUrl, typedUrl); + QCOMPARE(entry.title, title); + QCOMPARE(int(entry.numberOfTimesVisited), 1); +} + +#include "historymanagertest.moc" diff --git a/autotests/konqhtmltest.cpp b/autotests/konqhtmltest.cpp new file mode 100644 index 0000000..037d4b2 --- /dev/null +++ b/autotests/konqhtmltest.cpp @@ -0,0 +1,254 @@ +/* This file is part of the KDE project + Copyright (C) 2008 David Faure + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include "../src/konqsettingsxt.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class KonqHtmlTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase() + { + QStandardPaths::setTestModeEnabled(true); + + KonqSessionManager::self()->disableAutosave(); + //qRegisterMetaType("KonqView*"); + + // Ensure the tests use webenginepart, not KHTML or kwebkitpart + // This code is inspired by settings/konqhtml/generalopts.cpp + bool needsUpdate = false; + KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); + KConfigGroup addedServices(profile, "Added KDE Service Associations"); + Q_FOREACH (const QString &mimeType, QStringList() << "text/html" << "application/xhtml+xml" << "application/xml") { + QStringList services = addedServices.readXdgListEntry(mimeType); + const QString wanted = QStringLiteral("webenginepart.desktop"); + if (services.isEmpty() || services.at(0) != wanted) { + services.removeAll(wanted); + services.prepend(wanted); // make it the preferred one + addedServices.writeXdgListEntry(mimeType, services); + needsUpdate = true; + } + } + if (needsUpdate) { + profile->sync(); + // kbuildsycoca is the one reading mimeapps.list, so we need to run it now + QProcess::execute(QStandardPaths::findExecutable(KBUILDSYCOCA_EXENAME)); + } + } + void cleanupTestCase() + { + // in case some test broke, don't assert in khtmlglobal... + deleteAllMainWindows(); + } + void loadSimpleHtml() + { + KonqMainWindow mainWindow; + // we specify the mimetype so that we don't have to wait for a KonqRun + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqView *view = mainWindow.currentView(); + QVERIFY(view); + QVERIFY(view->part()); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + QCOMPARE(view->serviceType(), QString("text/html")); + WebEnginePart* part = qobject_cast(view->part()); + QVERIFY(part); + } + + void loadDirectory() // #164495, konqueror gets in a loop when setting a directory as homepage + { + KonqMainWindow mainWindow; + const QUrl url = QUrl::fromLocalFile(QDir::homePath()); + mainWindow.openUrl(nullptr, url, QStringLiteral("text/html")); + KonqView *view = mainWindow.currentView(); + qDebug() << "Waiting for first completed signal"; + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); // error calls openUrlRequest + if (view->aborted()) { + qDebug() << "Waiting for second completed signal"; + QVERIFY(spyCompleted.wait(20000)); // which then opens the right part + QCOMPARE(view->serviceType(), QString("inode/directory")); + } else { + // WebEngine can actually list directories, no error. + // To test this: konqueror --mimetype text/html $HOME + QCOMPARE(view->url().adjusted(QUrl::StripTrailingSlash), url); + } + } + + void rightClickClose() // #149736 + { + QPointer mainWindow = new KonqMainWindow; + // we specify the mimetype so that we don't have to wait for a KonqRun + mainWindow->openUrl(nullptr, QUrl( + "data:text/html, "), QStringLiteral("text/html")); + QPointer view = mainWindow->currentView(); + QVERIFY(view); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + QWidget *widget = partWidget(view); + qDebug() << "Clicking on" << widget; + QTest::mousePress(widget, Qt::RightButton); + QTRY_VERIFY(!view); // deleted + QTRY_VERIFY(!mainWindow); // the whole window gets deleted, in fact + } + + void windowOpen() + { + // Simple test for window.open in a onmousedown handler. + + // Want a window, not a tab (historical test) + KonqSettings::setMmbOpensTab(false); + + // We have to use the same protocol for both the orig and dest urls. + // KAuthorized would forbid a data: URL to redirect to a file: URL for instance. + QTemporaryFile tempFile; + QVERIFY(tempFile.open()); + tempFile.write("Popup"); + + QTemporaryFile origTempFile; + QVERIFY(origTempFile.open()); + origTempFile.write( + "" + ); + tempFile.close(); + const QString origFile = origTempFile.fileName(); + origTempFile.close(); + + KonqMainWindow *mainWindow = KonqMainWindowFactory::createNewWindow(QUrl::fromLocalFile(origFile)); + QCOMPARE(KMainWindow::memberList().count(), 1); + KonqView *view = mainWindow->currentView(); + QVERIFY(view); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + qApp->processEvents(); + QWidget *widget = partWidget(view); + QVERIFY(widget); + qDebug() << "Clicking on the khtmlview"; + QTest::mousePress(widget, Qt::LeftButton); + qApp->processEvents(); // openurlrequestdelayed + qApp->processEvents(); // browserrun + hideAllMainWindows(); // TODO: why does it appear nonetheless? hiding too early? hiding too late? + // Did it open a window? + QTRY_COMPARE(KMainWindow::memberList().count(), 2); + KonqMainWindow *newWindow = qobject_cast(KMainWindow::memberList().last()); + QVERIFY(newWindow); + QVERIFY(newWindow != mainWindow); + compareToolbarSettings(mainWindow, newWindow); + // Does the window contain exactly one view? + QCOMPARE(newWindow->viewCount(), 1); + KonqFrame *frame = newWindow->currentView()->frame(); + QVERIFY(frame); + QVERIFY(!frame->childView()->isLoading()); + WebEnginePart *part = qobject_cast(frame->part()); + QVERIFY(part); + QTRY_VERIFY(!part->view()->url().isEmpty()); // hack to wait for webengine to load the page + QTRY_COMPARE(part->view()->title(), QString("Opener=[object Window]")); + deleteAllMainWindows(); + } + + void testJSError() + { + // JS errors appear in a statusbar label, and deleting the frame first + // would lead to double deletion (#228255) + QPointer mainWindow = new KonqMainWindow; + // we specify the mimetype so that we don't have to wait for a KonqRun + mainWindow->openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqView *view = mainWindow->currentView(); + QVERIFY(view); + QVERIFY(view->part()); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + QCOMPARE(view->serviceType(), QString("text/html")); + delete view->part(); + QTRY_VERIFY(!mainWindow); // the window gets deleted + } + +private: + // Return the main widget for the given KonqView; used for clicking onto it + static QWidget *partWidget(KonqView *view) + { + QWidget *widget = view->part()->widget(); + WebEnginePart *htmlPart = qobject_cast(view->part()); + if (htmlPart) { + widget = htmlPart->view(); // khtmlview != widget() nowadays, due to find bar + } + if (QScrollArea *scrollArea = qobject_cast(widget)) { + widget = scrollArea->widget(); + } + if (widget && widget->focusProxy()) { // for WebEngine's RenderWidgetHostViewQtDelegateWidget + return widget->focusProxy(); + } + return widget; + } + + // Delete all KonqMainWindows + static void deleteAllMainWindows() + { + const QList windows = KMainWindow::memberList(); + qDeleteAll(windows); + } + + void compareToolbarSettings(KMainWindow *mainWindow, KMainWindow *newWindow) + { + QVERIFY(mainWindow != newWindow); + KToolBar *firstToolBar = mainWindow->toolBars().first(); + QVERIFY(firstToolBar); + KToolBar *newFirstToolBar = newWindow->toolBars().first(); + QVERIFY(newFirstToolBar); + QCOMPARE(firstToolBar->toolButtonStyle(), newFirstToolBar->toolButtonStyle()); + } + + static void hideAllMainWindows() + { + const QList windows = KMainWindow::memberList(); + qDebug() << "hiding" << windows.count() << "windows"; + Q_FOREACH (KMainWindow *window, windows) { + window->hide(); + } + } +}; + +QTEST_MAIN(KonqHtmlTest) + +#include "konqhtmltest.moc" diff --git a/autotests/konqviewmgrtest.cpp b/autotests/konqviewmgrtest.cpp new file mode 100644 index 0000000..0b474c0 --- /dev/null +++ b/autotests/konqviewmgrtest.cpp @@ -0,0 +1,945 @@ +/* This file is part of the KDE project + Copyright (C) 2006 David Faure + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "konqviewmgrtest.h" +#include +#include "../src/konqsettingsxt.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define TEST_KHTML 1 + +#ifdef TEST_KHTML +#include +#include +#else +#include +#include +#include "../webenginepart/autotests/webengine_testutils.h" +#endif + +#include +#include +#include + +QTEST_MAIN(ViewMgrTest) + +#if 0 +// could be used to load dummy parts; or to check that the right parts are being loaded +// (and to detect the case where a part is loaded and then replaced with another one for no good reason) +class KonqTestFactory : public KonqAbstractFactory +{ +public: + virtual KonqViewFactory createView(const QString &serviceType, + const QString &serviceName = QString(), + KService::Ptr *serviceImpl = 0, + KService::List *partServiceOffers = 0, + KService::List *appServiceOffers = 0, + bool forceAutoEmbed = false); + +}; +#endif + + +// Return the main widget for the given KonqView; used for clicking onto it +// Duplicated from konqhtmltest.cpp -> move to KonqView? +static QWidget *partWidget(KonqView *view) +{ + QWidget *widget = view->part()->widget(); +#ifdef TEST_KHTML + KHTMLPart *htmlPart = qobject_cast(view->part()); +#else + WebEnginePart *htmlPart = qobject_cast(view->part()); +#endif + if (htmlPart) { + widget = htmlPart->view(); // khtmlview != widget() nowadays, due to find bar + } + if (QScrollArea *scrollArea = qobject_cast(widget)) { + widget = scrollArea->widget(); + } + if (widget && widget->focusProxy()) { // for WebEngine's RenderWidgetHostViewQtDelegateWidget + return widget->focusProxy(); + } + return widget; +} + +void ViewMgrTest::sendAllPendingResizeEvents(QWidget *mainWindow) +{ + bool foundOne = true; + while (foundOne) { + foundOne = false; + QList allChildWidgets = mainWindow->findChildren(); + allChildWidgets.prepend(mainWindow); + foreach (QWidget *w, allChildWidgets) { + if (w->testAttribute(Qt::WA_PendingResizeEvent)) { + w->setAttribute(Qt::WA_WState_Created, true); // hack: avoid assert in Qt-4.6 + //qDebug() << "Resizing" << w << " to " << w->size() << endl; + QResizeEvent e(w->size(), QSize()); + QApplication::sendEvent(w, &e); + w->setAttribute(Qt::WA_PendingResizeEvent, false); + // hack: make QTabWidget think it's visible; no layout otherwise + w->setAttribute(Qt::WA_WState_Visible, true); + foundOne = true; + } + } + // Process LayoutRequest events, in particular + qApp->sendPostedEvents(); + //qDebug() << "Loop done, checking again"; + + if (!foundOne) { // about to exit, reset visible flag, to avoid crashes in qt + foreach (QWidget *w, allChildWidgets) { + w->setAttribute(Qt::WA_WState_Visible, false); + } + } + } +} + +class DebugFrameVisitor : public KonqFrameVisitor +{ +public: + DebugFrameVisitor() {} + QString output() const + { + return m_output; + } + bool visit(KonqFrame *) override + { + m_output += 'F'; + return true; + } + bool visit(KonqFrameContainer *) override + { + m_output += QLatin1String("C("); + return true; + } + bool visit(KonqFrameTabs *) override + { + m_output += QLatin1String("T["); + return true; + } + bool visit(KonqMainWindow *) override + { + m_output += 'M'; + return true; + } + bool endVisit(KonqFrameContainer *) override + { + m_output += ')'; + return true; + } + bool endVisit(KonqFrameTabs *) override + { + m_output += ']'; + return true; + } + bool endVisit(KonqMainWindow *) override + { + m_output += '.'; + return true; + } + + static QString inspect(KonqMainWindow *mainWindow) + { + DebugFrameVisitor dfv; + bool ok = mainWindow->accept(&dfv); + if (!ok) { + return QStringLiteral("ERROR: visitor returned false"); + } + return dfv.output(); + } + +private: + QString m_output; +}; + +void ViewMgrTest::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); + QDir(KonqSessionManager::self()->autosaveDirectory()).removeRecursively(); + KonqSessionManager::self()->disableAutosave(); + QCOMPARE(KonqSettings::mmbOpensTab(), true); + QCOMPARE(KonqSettings::popupsWithinTabs(), false); + KonqSettings::setAlwaysHavePreloaded(false); // it would confuse the mainwindow counting + + // Ensure the tests use webenginepart (not khtml or webkit) + // This code is inspired by settings/konqhtml/generalopts.cpp + KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); + KConfigGroup addedServices(profile, "Added KDE Service Associations"); + bool needsUpdate = false; + Q_FOREACH (const QString &mimeType, QStringList() << "text/html" << "application/xhtml+xml" << "application/xml") { + QStringList services = addedServices.readXdgListEntry(mimeType); +#ifdef TEST_KHTML + const QString wanted = "khtml.desktop"; +#else + const QString wanted = QStringLiteral("webenginepart.desktop"); +#endif + if (services.isEmpty() || services.at(0) != wanted) { + services.removeAll(wanted); + services.prepend(wanted); // make it the preferred one + addedServices.writeXdgListEntry(mimeType, services); + needsUpdate = true; + } + } + if (needsUpdate) { + profile->sync(); + // kbuildsycoca is the one reading mimeapps.list, so we need to run it now + QProcess::execute(QStandardPaths::findExecutable(KBUILDSYCOCA_EXENAME)); + } +} + +class MyKonqMainWindow : public KonqMainWindow +{ +public: + MyKonqMainWindow() : KonqMainWindow() { + setPluginLoadingMode(KParts::PartBase::DoNotLoadPlugins); // make the test faster + } +}; + +void ViewMgrTest::testCreateFirstView() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + QVERIFY(view); + QVERIFY(viewManager->tabContainer()); + + // Use DebugFrameVisitor to find out the structure of the frame hierarchy + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, one tab, one frame + QCOMPARE(mainWindow.linkableViewsCount(), 1); + + // Check widget parents: part's widget -> frame -> [tabwidget's stack] -> tabwidget -> mainWindow + QWidget *partWidget = view->part()->widget(); + QCOMPARE(partWidget->window(), &mainWindow); + QWidget *frame = view->frame()->asQWidget(); + QCOMPARE(partWidget->parentWidget(), frame); + QWidget *tabWidget = viewManager->tabContainer()->asQWidget(); + QCOMPARE(frame->parentWidget()->parentWidget(), tabWidget); + + // Check frame geometry, to check that all layouts are there + // (the mainWindow is resized to 700x480 in its constructor) + // But pending resize events are only sent by show(), and we don't want to see + // widgets from unit tests. + // So we iterate over all widgets and ensure the pending resize events are sent. + sendAllPendingResizeEvents(&mainWindow); + for (QWidget *w = partWidget; w; w = w->parentWidget()) { + qDebug() << w << w->geometry(); + } + //const QList toolbars = mainWindow.findChildren(); + //foreach( QToolBar* toolbar, toolbars ) { + // if (!toolbar->isHidden()) + // qDebug() << toolbar << toolbar->geometry(); + //} + //qDebug() << "frame geom: " << frame->geometry(); + QVERIFY(frame->width() > 680); + QVERIFY(frame->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown + //qDebug() << "partWidget geom:" << partWidget->geometry(); + QVERIFY(partWidget->width() > 680); + QVERIFY(partWidget->height() > frame->height() - 50 /*statusbar*/); + //qDebug() << "tabWidget geom: " << tabWidget->geometry(); + QVERIFY(tabWidget->width() > 680); + QVERIFY(tabWidget->height() >= frame->height()); // equal, unless there's a border in the frame + + // Part widget should have focus, not location bar + QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), partWidget->focusWidget()->metaObject()->className()); +} + +void ViewMgrTest::testEmptyWindow() +{ + QScopedPointer emptyWindow(KonqMainWindowFactory::createNewWindow()); + QCOMPARE(emptyWindow->currentView()->url().url(), QString("konq:konqueror")); + QCOMPARE(emptyWindow->focusWidget()->metaObject()->className(), "KonqCombo"); +} + +void ViewMgrTest::testRemoveFirstView() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame + viewManager->removeView(view); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // removing not allowed + // real test for removeView is part of testSplitView +} + +void ViewMgrTest::testSplitView() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame + KonqView *view2 = viewManager->splitView(view, Qt::Horizontal); + QVERIFY(view2); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + + QCOMPARE(mainWindow.linkableViewsCount(), 2); + + // Check widget parents + //mainWindow.dumpObjectTree(); + QWidget *partWidget = view->part()->widget(); + QCOMPARE(partWidget->window(), &mainWindow); + QWidget *frame = view->frame()->asQWidget(); + QCOMPARE(partWidget->parentWidget(), frame); + QVERIFY(!frame->isHidden()); + + QWidget *part2Widget = view2->part()->widget(); + QCOMPARE(part2Widget->window(), &mainWindow); + QWidget *frame2 = view2->frame()->asQWidget(); + QCOMPARE(part2Widget->parentWidget(), frame2); + QVERIFY(!frame2->isHidden()); + + // Check container + QVERIFY(view->frame()->parentContainer()->frameType() == KonqFrameBase::Container); + KonqFrameContainer *container = static_cast(view->frame()->parentContainer()); + QVERIFY(container); + QCOMPARE(container->count(), 2); + QCOMPARE(container, view2->frame()->parentContainer()); + QCOMPARE(container->firstChild(), view->frame()); + QCOMPARE(container->secondChild(), view2->frame()); + QCOMPARE(container->widget(0), view->frame()->asQWidget()); + QCOMPARE(container->widget(1), view2->frame()->asQWidget()); + + // Check frame geometries + sendAllPendingResizeEvents(&mainWindow); + //for ( QWidget* w = partWidget; w; w = w->parentWidget() ) + // qDebug() << w << w->geometry() << "visible:" << w->isVisible(); + + //qDebug() << "view geom:" << frame->geometry(); + QVERIFY(frame->width() > 300 && frame->width() < 400); // horiz split, so half the mainWindow width + QVERIFY(frame->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown + //qDebug() << "view2 geom:" << frame2->geometry(); + QVERIFY(frame2->width() > 300 && frame2->width() < 400); // horiz split, so half the mainWindow width + QVERIFY(frame2->height() > 240); // usually 325, but can be 256 with oxygen when three toolbars are shown + // Both frames should have the same size; well, if the width was odd then there can be an off-by-one... + QCOMPARE(frame->height(), frame2->height()); + QVERIFY(qAbs(frame->width() - frame2->width()) <= 1); // e.g. 173 and 172 are "close enough" + //qDebug() << "partWidget geom:" << partWidget->geometry(); + QVERIFY(partWidget->width() > 300 && partWidget->width() < 400); // horiz split, so half the mainWindow width + QVERIFY(partWidget->height() > 220); // frame minus statusbar height + QVERIFY(part2Widget->width() > 300 && part2Widget->width() < 400); // horiz split, so half the mainWindow width + QVERIFY(part2Widget->height() > 220); + + //KonqFrameContainerBase* container = view->frame()->parentContainer(); + //QVERIFY( container ); + //qDebug() << "container geom: " << container->asQWidget()->geometry(); + + // Split again + int widthFrame2 = frame2->width(); + KonqView *view3 = viewManager->splitView(view, Qt::Horizontal); + QVERIFY(view3); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(C(FF)F)].")); + // Check that the width of the second frame has not changed (bug 160407) + QCOMPARE(frame2->width(), widthFrame2); + QCOMPARE(mainWindow.linkableViewsCount(), 3); + + // Now test removing the first view + viewManager->removeView(view); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + // Check again that the width of the second frame has not changed (bug 160407 comments 18-20) + QCOMPARE(frame2->width(), widthFrame2); + QCOMPARE(mainWindow.linkableViewsCount(), 2); + + // Now test removing the last view + viewManager->removeView(view3); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame + QCOMPARE(mainWindow.linkableViewsCount(), 1); +} + +void ViewMgrTest::testSplitMainContainer() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame + KonqFrameContainerBase *tabContainer = view->frame()->parentContainer(); + KonqView *view2 = viewManager->splitMainContainer(view, Qt::Horizontal, QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage"), true); + QVERIFY(view2); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MC(FT[F]).")); // mainWindow, splitter, frame, tab widget, one frame + + // Check widget parents + QWidget *partWidget = view->part()->widget(); + QCOMPARE(partWidget->window(), &mainWindow); + QWidget *frame = view->frame()->asQWidget(); + QCOMPARE(partWidget->parentWidget(), frame); + QVERIFY(!frame->isHidden()); + + QWidget *part2Widget = view2->part()->widget(); + QCOMPARE(part2Widget->window(), &mainWindow); + QWidget *frame2 = view2->frame()->asQWidget(); + QCOMPARE(part2Widget->parentWidget(), frame2); + QVERIFY(!frame2->isHidden()); + + // Check container + QVERIFY(view->frame()->parentContainer()->frameType() == KonqFrameBase::Tabs); + QVERIFY(view2->frame()->parentContainer()->frameType() == KonqFrameBase::Container); + KonqFrameContainer *container = static_cast(view2->frame()->parentContainer()); + QVERIFY(container); + QCOMPARE(container->count(), 2); + QCOMPARE(container, view2->frame()->parentContainer()); + QCOMPARE(container->firstChild(), view2->frame()); + QCOMPARE(container->secondChild(), tabContainer); + QCOMPARE(container->widget(0), view2->frame()->asQWidget()); + QCOMPARE(container->widget(1), tabContainer->asQWidget()); + + // Now test removing the view we added last + viewManager->removeView(view2); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one frame +} + +static void openHtmlWithLink(KonqMainWindow &mainWindow) +{ + // Much like KonqHtmlTest::loadSimpleHtml. + // We use text/plain as the linked file, in order to test #67956 (switching parts in new tab) + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html, Click me")), QStringLiteral("text/html")); + KonqView *view = mainWindow.currentView(); + QVERIFY(view); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + QCOMPARE(view->serviceType(), QString("text/html")); +} + +void ViewMgrTest::testLinkedViews() +{ + MyKonqMainWindow mainWindow; + openHtmlWithLink(mainWindow); + KonqView *view = mainWindow.currentView(); + WebEnginePart *part = qobject_cast(view->part()); + QVERIFY(part); + // Split it + qDebug() << "SPLITTING"; + mainWindow.slotSplitViewHorizontal(); + KonqView *view2 = mainWindow.currentView(); + QVERIFY(view2); + QCOMPARE(view2->serviceType(), QString("text/html")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + QSignalSpy spyCompleted(view2, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + const QUrl origUrl = view->url(); + QCOMPARE(view2->url().url(), origUrl.url()); + QCOMPARE(mainWindow.linkableViewsCount(), 2); + view->setLinkedView(true); + view2->setLinkedView(true); + view->setLockedLocation(true); + + mainWindow.show(); + + // "Click" on the link + qDebug() << "ACTIVATING LINK"; + +#ifdef TEST_KHTML + KHTMLPart *part = qobject_cast(view->part()); + QVERIFY(part); + DOM::HTMLAnchorElement anchor = part->htmlDocument().getElementsByTagName(DOM::DOMString("a")).item(0); + QVERIFY(!anchor.isNull()); + anchor.focus(); + QKeyEvent ev(QKeyEvent::KeyPress, Qt::Key_Return, 0, "\n"); + QApplication::sendEvent(part->view(), &ev); + qApp->processEvents(); // openUrlRequestDelayed + QTest::qWait(0); +#else + QTest::mouseClick(part->view()->focusProxy(), Qt::LeftButton, Qt::KeyboardModifiers(), + elementCenter(part->view()->page(), QStringLiteral("linkid"))); + + // Check that the link opened in the 2nd view, not the first one +#endif + QCOMPARE(view->url().url(), origUrl.url()); +#ifndef TEST_KHTML + QEXPECT_FAIL("", "Broken feature right now, requires URLs to be opened by konq rather than the part", Abort); +#endif + QTRY_COMPARE_WITH_TIMEOUT(view2->url().url(), QUrl("data:text/plain, Link target").url(), 400); +} + +void ViewMgrTest::testPopupNewTab() // RMB, "Open in new tab" +{ + MyKonqMainWindow mainWindow; + openHtmlWithLink(mainWindow); + KonqFrameTabs *tabs = mainWindow.viewManager()->tabContainer(); + QCOMPARE(tabs->currentIndex(), 0); + KFileItem item(QUrl(QStringLiteral("data:text/html, hello")), QStringLiteral("text/html"), S_IFREG); + mainWindow.prepareForPopupMenu(KFileItemList() << item, KParts::OpenUrlArguments(), KParts::BrowserArguments()); + QMetaObject::invokeMethod(&mainWindow, "slotPopupNewTab"); + QTest::qWait(1000); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + QCOMPARE(KMainWindow::memberList().count(), 1); + QCOMPARE(mainWindow.linkableViewsCount(), 1); + + if (KonqSettings::newTabsInFront()) { + QCOMPARE(tabs->currentIndex(), 1); + } +} + +static void checkSecondWindowHasOneTab(bool fromPopup) // and delete it. +{ + QTRY_COMPARE(KMainWindow::memberList().count(), 2); + QScopedPointer newWindow(qobject_cast(KMainWindow::memberList().last())); + QVERIFY(newWindow.data()); + QTRY_COMPARE(DebugFrameVisitor::inspect(newWindow.data()), QString("MT[F].")); // mainWindow, tab widget, one tab + QTabWidget *tabWidget = newWindow->findChild(); + QVERIFY(tabWidget); + // The location bar shouldn't get focus (#208821) + QTRY_VERIFY(newWindow->focusWidget()); + qDebug() << newWindow->focusWidget(); +#ifndef TEST_KHTML + if (!fromPopup) { + QEXPECT_FAIL("", "This fails because it doesn't go through KRun and KonqView::setLoading yet", Abort); + } +#endif + QTRY_VERIFY_WITH_TIMEOUT(tabWidget->focusWidget(), 200); + QCOMPARE(newWindow->focusWidget()->metaObject()->className(), tabWidget->focusWidget()->metaObject()->className()); +} + +void ViewMgrTest::testPopupNewWindow() // RMB, "Open new window" +{ + MyKonqMainWindow mainWindow; + openHtmlWithLink(mainWindow); + KFileItem item(QUrl(QStringLiteral("data:text/html, hello")), QStringLiteral("text/html"), S_IFREG); + mainWindow.prepareForPopupMenu(KFileItemList() << item, KParts::OpenUrlArguments(), KParts::BrowserArguments()); + QMetaObject::invokeMethod(&mainWindow, "slotPopupNewWindow"); + QTRY_COMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab + QVERIFY(KMainWindow::memberList().last() != &mainWindow); + checkSecondWindowHasOneTab(true); +} + +void ViewMgrTest::testCtrlClickOnLink() +{ + KonqMainWindow mainWindow; + openHtmlWithLink(mainWindow); + KonqFrameTabs *tabs = mainWindow.viewManager()->tabContainer(); + KonqView *view = mainWindow.currentView(); + mainWindow.show(); + qDebug() << "CLICKING NOW"; + QTest::mouseClick(partWidget(view), Qt::LeftButton, Qt::ControlModifier, QPoint(10, 10)); + QTest::qWait(100); + KonqView *newView = nullptr; + // Expected behavior for Ctrl+click: + // new tab, if mmbOpensTab + // new window, if !mmbOpensTab + // (this code is called for both cases) + if (KonqSettings::mmbOpensTab()) { + QCOMPARE(KMainWindow::memberList().count(), 1); + QTRY_COMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + if (KonqSettings::newTabsInFront()) { // when called by sameTestsWithNewTabsInFront + QCOMPARE(tabs->currentIndex(), 1); + QVERIFY(mainWindow.currentView() != view); + QVERIFY(mainWindow.viewManager()->activePart() != view->part()); + } else { // the default case + QCOMPARE(tabs->currentIndex(), 0); + QCOMPARE(mainWindow.currentView(), view); + QCOMPARE(mainWindow.viewManager()->activePart(), view->part()); + } + KonqFrame *newFrame = dynamic_cast(mainWindow.viewManager()->tabContainer()->tabAt(1)); + QVERIFY(newFrame); + newView = newFrame->activeChildView(); + QVERIFY(newView); + //QVERIFY(newView->supportsMimeType("text/plain")); + } else { + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab + checkSecondWindowHasOneTab(false); + } +} + +void ViewMgrTest::sameTestsWithNewTabsInFront() +{ + // Redo testCtrlClickOnLink, + // but with the option "NewTabsInFront" set to true. + QVERIFY(!KonqSettings::newTabsInFront()); // default setting = false + KonqSettings::setNewTabsInFront(true); + testPopupNewTab(); + testCtrlClickOnLink(); + KonqSettings::setNewTabsInFront(false); +} + +void ViewMgrTest::sameTestsWithMmbOpenTabsFalse() +{ + // Redo testPopupNewTab, testPopupNewWindow and testCtrlClickOnLink, + // but as if the user (e.g. Pino) had disabled the setting "Open links in new tabs". + KonqSettings::setMmbOpensTab(false); + testPopupNewTab(); + testPopupNewWindow(); + testCtrlClickOnLink(); + KonqSettings::setMmbOpensTab(true); +} + +static void openTabWithTitle(KonqMainWindow &mainWindow, const QString &title, KonqView *&view) +{ + KonqViewManager *viewManager = mainWindow.viewManager(); + view = viewManager->addTab(QStringLiteral("text/html")); + QVERIFY(view); + QVERIFY(view->supportsMimeType("text/html")); + QVERIFY(!view->supportsMimeType("text/plain")); + // correct since it's a subclass of text/html, khtml can display it + QVERIFY(view->supportsMimeType("application/x-netscape-bookmarks")); + // Tab caption test + view->openUrl(QUrl("data:text/html, " + title.toUtf8() + ""), QStringLiteral("http://loc.bar.url")); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(10000)); + QCOMPARE(view->caption(), title); + QCOMPARE(view->locationBarURL(), QString("http://loc.bar.url")); +} + +void ViewMgrTest::testAddTabs() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + QVERIFY(view); + // The testcase was "konqueror www.kde.org www.google.fr bugs.kde.org www.cuil.com www.davidfaure.fr" + const QStringList titles { + "K Desktop Environment - Be free", + "Google", + "KDE Bug Tracking System", + "Cuil", + "http://www.davidfaure.fr/" }; + view->setCaption(titles.at(0)); + + KTabWidget *tabWidget = mainWindow.findChild(); + QVERIFY(tabWidget); + KonqView *viewTab1, *viewTab2, *viewTab3, *viewTab4; + openTabWithTitle(mainWindow, titles.at(1), viewTab1); + openTabWithTitle(mainWindow, titles.at(2), viewTab2); + openTabWithTitle(mainWindow, titles.at(3), viewTab3); + openTabWithTitle(mainWindow, titles.at(4), viewTab4); + for (int i = 0; i < titles.count(); ++i) { + QCOMPARE(tabWidget->tabText(i), QString(titles.at(i))); + } + QPointer viewTab2Pointer(viewTab2); + QPointer tab2PartPointer(viewTab2->part()); + + // Ensure tabwidget has a nice size + mainWindow.resize(1000, 699); + sendAllPendingResizeEvents(&mainWindow); + + // Remove active tab (#170470) + tabWidget->setCurrentIndex(2); + KonqFrameBase *frame = dynamic_cast(viewManager->tabContainer()->currentWidget()); + QVERIFY(frame); + viewManager->removeTab(frame); + QVERIFY(viewTab2Pointer.isNull()); // check the view got deleted + QVERIFY(tab2PartPointer.isNull()); // check the part got deleted too, since pino is a non-believer :) + QList expectedTitles{0, 1, 3, 4}; + for (int i = 0; i < expectedTitles.count(); ++i) { + QCOMPARE(tabWidget->tabText(i), titles.at(expectedTitles[i])); + } + for (int i = 0; i < expectedTitles.count(); ++i) { + QCOMPARE(tabWidget->QTabWidget::tabText(i).left(10), titles.at(expectedTitles[i]).left(10)); + } + + tabWidget->removeTab(0); + expectedTitles.removeAt(0); + for (int i = 0; i < expectedTitles.count(); ++i) { + QCOMPARE(tabWidget->tabText(i), QString(titles.at(expectedTitles[i]))); + } +} + +void ViewMgrTest::testDuplicateTab() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + /*KonqView* view =*/ viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + viewManager->duplicateTab(0); // should return a KonqFrameBase? + + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + // TODO check serviceType and serviceName of the new view +} + +void ViewMgrTest::testDuplicateSplittedTab() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + KonqView *view2 = viewManager->splitView(view, Qt::Vertical); + QVERIFY(view2); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + + KonqFrameContainer *container = static_cast(view->frame()->parentContainer()); + QVERIFY(container); + QVERIFY(container->parentContainer()->frameType() == KonqFrameBase::Tabs); + + viewManager->duplicateTab(0); // TODO shouldn't it return a KonqFrameBase? + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)C(FF)].")); // mainWindow, tab widget, two tabs + QCOMPARE(mainWindow.linkableViewsCount(), 2); + + // While we're here, let's test Ctrl+Tab navigation + view->setProperty("num", 0); + view2->setProperty("num", 1); + KonqFrameTabs *tabs = viewManager->tabContainer(); + KonqFrameBase *tab2base = tabs->tabAt(1); + QVERIFY(tab2base->isContainer()); + KonqFrameContainer *tab2 = dynamic_cast(tab2base); + QVERIFY(tab2); + KonqView *view3 = tab2->firstChild()->activeChildView(); + QVERIFY(view3); + KonqView *view4 = tab2->secondChild()->activeChildView(); + QVERIFY(view4); + QVERIFY(view3 != view); + QVERIFY(view4 != view2); + view3->setProperty("num", 2); + view4->setProperty("num", 3); + QCOMPARE(mainWindow.currentView()->property("num").toInt(), 3); + QCOMPARE(tabs->currentIndex(), 1); + QVERIFY(mainWindow.focusWidget()); + QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); + QCOMPARE(mainWindow.currentView()->property("num").toInt(), 0); + QCOMPARE(tabs->currentIndex(), 0); + QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); + QCOMPARE(mainWindow.currentView()->property("num").toInt(), 1); + QCOMPARE(tabs->currentIndex(), 0); + QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); + QCOMPARE(mainWindow.currentView()->property("num").toInt(), 2); + QCOMPARE(tabs->currentIndex(), 1); + QTest::keyClick(mainWindow.focusWidget(), Qt::Key_Tab, Qt::ControlModifier); + QCOMPARE(mainWindow.currentView()->property("num").toInt(), 3); + QCOMPARE(tabs->currentIndex(), 1); + + viewManager->removeTab(container); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one tab + QCOMPARE(mainWindow.linkableViewsCount(), 2); +} + +// Like in http://bugs.kde.org/show_bug.cgi?id=153533, +// where the part deletes itself. +void ViewMgrTest::testDeletePartInTab() +{ + QPointer mainWindow = new MyKonqMainWindow; + QVERIFY(mainWindow->testAttribute(Qt::WA_DeleteOnClose)); + KonqViewManager *viewManager = mainWindow->viewManager(); + QPointer view = viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + QVERIFY(!view.isNull()); + QPointer partWidget = view->part()->widget(); + + QPointer viewTab2 = viewManager->addTab(QStringLiteral("text/html")); + QPointer partWidget2 = viewTab2->part()->widget(); + QVERIFY(!viewTab2.isNull()); + QCOMPARE(DebugFrameVisitor::inspect(mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + + delete viewTab2->part(); + QVERIFY(viewTab2.isNull()); + QVERIFY(partWidget2.isNull()); + QCOMPARE(DebugFrameVisitor::inspect(mainWindow), QString("MT[F].")); // mainWindow, tab widget, one tab + + delete view->part(); + QVERIFY(view.isNull()); + QVERIFY(partWidget.isNull()); + qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete); + QVERIFY(mainWindow.isNull()); +} + +void ViewMgrTest::testSaveProfile() +{ + MyKonqMainWindow mainWindow; + const QUrl url(QStringLiteral("data:text/html,

Hello World

")); + mainWindow.openUrl(nullptr, url, QStringLiteral("text/html")); + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view2 = viewManager->addTab(QStringLiteral("text/html")); + const QUrl url2(QStringLiteral("data:text/html,

view2

")); + view2->openUrl(url2, QStringLiteral("2")); + QTabWidget *tabWidget = mainWindow.findChild(); + QVERIFY(tabWidget); + + // Save a profile with two tabs (via KonqSessionManager) + KonqSessionManager *sessionMgr = KonqSessionManager::self(); + const QString filePath = QDir::currentPath() + "unittest_profile"; + sessionMgr->saveCurrentSessionToFile(filePath); + QVERIFY(QFile::exists(filePath)); + + { + KConfig cfg(filePath, KConfig::SimpleConfig); + KConfigGroup profileGroup(&cfg, "Window0"); + QCOMPARE(profileGroup.readEntry("RootItem"), QString("Tabs0")); + QCOMPARE(profileGroup.readEntry("Tabs0_Children"), QString("ViewT0,ViewT1")); + QCOMPARE(profileGroup.readEntry("HistoryItemViewT0_0Url"), url.url()); + QCOMPARE(profileGroup.readEntry("HistoryItemViewT1_0Url"), url2.url()); + } + + // Now close a tab and save again - to check that the stuff from the old + // tab isn't lying around. + viewManager->removeTab(view2->frame()); + sessionMgr->saveCurrentSessionToFile(filePath); + { + KConfig cfg(filePath, KConfig::SimpleConfig); + KConfigGroup profileGroup(&cfg, "Window0"); + QCOMPARE(profileGroup.readEntry("RootItem"), QString("Tabs0")); + QCOMPARE(profileGroup.readEntry("Tabs0_Children"), QString("ViewT0")); + QCOMPARE(profileGroup.readEntry("HistoryItemViewT0_0Url"), url.url()); + QVERIFY(!profileGroup.hasKey("HistoryItemViewT1_0Url")); + } + QFile::remove(filePath); +} + +void ViewMgrTest::testDuplicateWindow() +{ + MyKonqMainWindow mainWindow; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *viewTab2 = viewManager->addTab(QStringLiteral("text/html")); + KonqView *splitted = viewManager->splitView(viewTab2, Qt::Horizontal); + Q_UNUSED(splitted); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FC(FF)].")); // mainWindow, tab widget, first tab = one frame, second tab = splitter with two frames + QScopedPointer secondWindow(viewManager->duplicateWindow()); + QCOMPARE(DebugFrameVisitor::inspect(secondWindow.data()), QString("MT[FC(FF)].")); // mainWindow, tab widget, first tab = one frame, second tab = splitter with two frames +} + +void ViewMgrTest::testCloseOtherTabs() +{ + MyKonqMainWindow mainWindow; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqViewManager *viewManager = mainWindow.viewManager(); + QTabWidget *tabWidget = mainWindow.findChild(); + QVERIFY(tabWidget); + QVERIFY(tabWidget->focusWidget()); + QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), tabWidget->focusWidget()->metaObject()->className()); + viewManager->addTab(QStringLiteral("text/html")); + KonqView *viewTab2 = viewManager->addTab(QStringLiteral("text/html")); + viewManager->splitView(viewTab2, Qt::Horizontal); + viewManager->addTab(QStringLiteral("text/html")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFC(FF)F].")); // mainWindow, tab widget, first tab = one frame, second tab = one frame, third tab = splitter with two frames, fourth tab = one frame + QCOMPARE(tabWidget->count(), 4); + tabWidget->setCurrentIndex(2); + QCOMPARE(mainWindow.linkableViewsCount(), 2); + tabWidget->setCurrentIndex(3); + QCOMPARE(mainWindow.linkableViewsCount(), 1); + // Switching to an empty tab -> focus goes to location bar (#84867) + QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), "KonqCombo"); + + // Check that removeOtherTabs deals with split views correctly + mainWindow.viewManager()->removeOtherTabs(2); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, first tab = splitter with two frames +} + +void ViewMgrTest::testCloseTabsFast() // #210551/#150162 +{ + MyKonqMainWindow mainWindow; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqViewManager *viewManager = mainWindow.viewManager(); + viewManager->addTab(QStringLiteral("text/html")); + viewManager->addTab(QStringLiteral("text/html")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFF].")); // mainWindow, tab widget, 3 simple tabs + QTabWidget *tabWidget = mainWindow.findChild(); + tabWidget->setCurrentIndex(2); + + mainWindow.setWorkingTab(1); + mainWindow.slotRemoveTabPopup(); + mainWindow.slotRemoveTabPopup(); + QTest::qWait(100); // process the delayed invocations + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, tab widget, 1 tab left +} + +void ViewMgrTest::testBrowserArgumentsNewTab() +{ + MyKonqMainWindow mainWindow; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KParts::OpenUrlArguments urlArgs; + KParts::BrowserArguments browserArgs; + browserArgs.setNewTab(true); + KonqView *view = mainWindow.currentView(); + KParts::BrowserExtension *ext = view->browserExtension(); + QVERIFY(ext); + emit ext->openUrlRequest(QUrl(QStringLiteral("data:text/html,

Second tab test

")), urlArgs, browserArgs); + QTest::qWait(5000); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + QCOMPARE(view->url(), QUrl("data:text/html,

Hello World

")); + + // compare the url of the new view... how to? +// QCOMPARE(view->url(), QUrl("data:text/html,

Second tab test

")); +} + +void ViewMgrTest::testBreakOffTab() +{ + MyKonqMainWindow mainWindow; + KonqViewManager *viewManager = mainWindow.viewManager(); + /*KonqView* firstView =*/ viewManager->createFirstView(QStringLiteral("KonqAboutPage"), QStringLiteral("konq_aboutpage")); + + //KonqFrameBase* tab = firstView->frame(); + viewManager->duplicateTab(0); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FF].")); // mainWindow, tab widget, two tabs + + // Break off a tab + + KonqMainWindow *mainWindow2 = viewManager->breakOffTab(0, mainWindow.size()); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[F].")); // mainWindow, one tab, one frame + QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[F].")); // mainWindow, one tab, one frame + + // Verify that the new tab container has an active child and that duplicating the tab in the new window does not crash (bug 203069) + + QVERIFY(mainWindow2->viewManager()->tabContainer()->activeChild()); + mainWindow2->viewManager()->duplicateTab(0); + QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[FF].")); // mainWindow, tab widget, two tabs + + delete mainWindow2; + + // Now split the remaining view, duplicate the tab and verify that breaking off a split tab does not crash (bug 174292). + // Also check that the tab container of the new main window has an active child. + + KonqView *view = mainWindow.activeChildView(); + viewManager->splitView(view, Qt::Vertical); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + // KonqFrameContainerBase* container = view->frame()->parentContainer(); + viewManager->duplicateTab(0); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)C(FF)].")); // mainWindow, tab widget, two tabs with split views + mainWindow2 = viewManager->breakOffTab(0, mainWindow.size()); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + QCOMPARE(DebugFrameVisitor::inspect(mainWindow2), QString("MT[C(FF)].")); // mainWindow, tab widget, one splitter, two frames + QVERIFY(mainWindow2->viewManager()->tabContainer()->activeChild()); + + delete mainWindow2; +} + +void ViewMgrTest::moveTabLeft() +{ + MyKonqMainWindow mainWindow; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html")); + KonqViewManager *viewManager = mainWindow.viewManager(); + KonqView *view1 = viewManager->addTab(QStringLiteral("text/html")); + view1->openUrl(QUrl(QStringLiteral("data:text/html,

view1

")), QStringLiteral("1")); + KonqView *view2 = viewManager->addTab(QStringLiteral("text/html")); + view2->openUrl(QUrl(QStringLiteral("data:text/html,

view2

")), QStringLiteral("2")); + QCOMPARE(DebugFrameVisitor::inspect(&mainWindow), QString("MT[FFF].")); // mainWindow, tab widget, 3 simple tabs + QTabWidget *tabWidget = mainWindow.findChild(); + tabWidget->setCurrentIndex(2); + view2->part()->widget()->setFocus(); + //qDebug() << mainWindow.focusWidget() << view2->part()->widget()->focusWidget(); + QCOMPARE(mainWindow.focusWidget(), view2->part()->widget()->focusWidget()); + viewManager->moveTabBackward(); + // Now we should have the views (tabs) in the order 0, 2, 1 + QList views = KonqViewCollector::collect(&mainWindow); + QCOMPARE(views[1], view2); + QCOMPARE(views[2], view1); + QCOMPARE(tabWidget->currentIndex(), 1); + QCOMPARE(mainWindow.currentView(), view2); + qDebug() << mainWindow.focusWidget() << view2->part()->widget()->focusWidget(); + // the focus should stay with that view (#208821) + QCOMPARE(mainWindow.focusWidget()->metaObject()->className(), view2->part()->widget()->focusWidget()->metaObject()->className()); + QCOMPARE(mainWindow.focusWidget(), view2->part()->widget()->focusWidget()); +} + diff --git a/autotests/konqviewmgrtest.h b/autotests/konqviewmgrtest.h new file mode 100644 index 0000000..cdb5f31 --- /dev/null +++ b/autotests/konqviewmgrtest.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE project + Copyright (C) 2006 David Faure + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + Boston, MA 02110-1301, USA. +*/ + +#ifndef KONQVIEWMGRTEST_H +#define KONQVIEWMGRTEST_H + +#include + +class ViewMgrTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + + void testCloseOtherTabs(); + void testCloseTabsFast(); + void testCreateFirstView(); + void testEmptyWindow(); + void testRemoveFirstView(); + void testSplitView(); + void testSplitMainContainer(); + void testLinkedViews(); + + void testPopupNewTab(); + void testPopupNewWindow(); + void testCtrlClickOnLink(); + void sameTestsWithNewTabsInFront(); + void sameTestsWithMmbOpenTabsFalse(); + + void testAddTabs(); + void testDuplicateTab(); + void testDuplicateSplittedTab(); + void testDeletePartInTab(); + void testSaveProfile(); + + void testDuplicateWindow(); + + void testBrowserArgumentsNewTab(); + + void testBreakOffTab(); + void moveTabLeft(); + + static void sendAllPendingResizeEvents(QWidget *); +}; + +#endif diff --git a/autotests/konqviewtest.cpp b/autotests/konqviewtest.cpp new file mode 100644 index 0000000..bbf7180 --- /dev/null +++ b/autotests/konqviewtest.cpp @@ -0,0 +1,63 @@ +/* This file is part of the KDE project + Copyright (C) 2008 David Faure + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include + +class KonqViewTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + QStandardPaths::setTestModeEnabled(true); + } + + void textThenHtml() + { + // This is test for the bug "embed katepart and then type a website URL -> loaded into katepart" + // i.e. KonqView::changePart(), KonqView::ensureViewSupports() + + KonqMainWindow mainWindow; + // we specify the mimetype so that we don't have to wait for a KonqRun + KonqOpenURLRequest req; req.forceAutoEmbed = true; + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/plain, Hello World")), QStringLiteral("text/plain"), req); + KonqView *view = mainWindow.currentView(); + QVERIFY(view); + QVERIFY(view->part()); + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(10000)); + QCOMPARE(view->serviceType(), QString("text/plain")); + const QString firstService = view->service()->entryPath(); + qDebug() << firstService; + QVERIFY(view->supportsMimeType("text/html")); // it does, since that's a mimetype subclass + + // Now open HTML, as if we typed a URL in the location bar. + KonqOpenURLRequest req2; req2.typedUrl = QStringLiteral("http://www.kde.org"); + mainWindow.openUrl(nullptr, QUrl(QStringLiteral("data:text/html,

Hello World

")), QStringLiteral("text/html"), req2); + qDebug() << view->service()->entryPath(); + QVERIFY(view->service()->entryPath() != firstService); + } + +}; + +QTEST_MAIN(KonqViewTest) + +#include "konqviewtest.moc" diff --git a/autotests/undomanagertest.cpp b/autotests/undomanagertest.cpp new file mode 100644 index 0000000..2667ed6 --- /dev/null +++ b/autotests/undomanagertest.cpp @@ -0,0 +1,92 @@ +/* This file is part of KDE + Copyright 2007 David Faure + + 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. +*/ + +#include +#include +#include +#include +#include + +class UndoManagerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void testAddClosedTabItem(); + void testUndoLastClosedTab(); +}; + +QTEST_MAIN(UndoManagerTest) + +void UndoManagerTest::initTestCase() +{ + // Make sure we start clean + QStandardPaths::setTestModeEnabled(true); + KonqSessionManager::self()->disableAutosave(); + KonqUndoManager manager(nullptr); + QSignalSpy spyUndoAvailable(&manager, SIGNAL(undoAvailable(bool))); + QVERIFY(spyUndoAvailable.isValid()); + manager.clearClosedItemsList(); + QCOMPARE(spyUndoAvailable.count(), 1); + QCOMPARE(spyUndoAvailable[0][0], QVariant(false)); + QVERIFY(!manager.undoAvailable()); +} + +void UndoManagerTest::testAddClosedTabItem() +{ + KonqUndoManager manager(nullptr); + QVERIFY(!manager.undoAvailable()); + KonqClosedTabItem *item = new KonqClosedTabItem(QStringLiteral("url"), QStringLiteral("title"), 0, manager.newCommandSerialNumber()); + QCOMPARE(item->url(), QString("url")); + QCOMPARE(item->serialNumber(), quint64(1001)); + QCOMPARE(item->pos(), 0); + KConfigGroup configGroup = item->configGroup(); + QVERIFY(!configGroup.exists()); + + QSignalSpy spyUndoAvailable(&manager, SIGNAL(undoAvailable(bool))); + QVERIFY(spyUndoAvailable.isValid()); + QSignalSpy spyTextChanged(&manager, SIGNAL(undoTextChanged(QString))); + QVERIFY(spyTextChanged.isValid()); + manager.addClosedTabItem(item); + + QVERIFY(manager.undoAvailable()); + QCOMPARE(spyUndoAvailable.count(), 1); + QCOMPARE(spyTextChanged.count(), 1); + QCOMPARE(manager.closedItemsList().count(), 1); + configGroup.writeEntry("RootItem", "test"); + QVERIFY(!configGroup.keyList().isEmpty()); + + // This requires a default constructor... + //qRegisterMetaType("KonqClosedTabItem"); + QSignalSpy spyOpenClosedTab(&manager, SIGNAL(openClosedTab(KonqClosedTabItem))); + manager.undo(); + QCOMPARE(spyUndoAvailable.count(), 2); + QVERIFY(!manager.undoAvailable()); + QCOMPARE(spyOpenClosedTab.count(), 1); + QCOMPARE(manager.closedItemsList().count(), 0); + QVERIFY(configGroup.keyList().isEmpty()); // was deleted by the KonqClosedTabItem destructor +} + +void UndoManagerTest::testUndoLastClosedTab() +{ + +} + +#include "undomanagertest.moc" diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000..8d14e33 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,38 @@ +########### kfmclient ############### +include(ECMMarkNonGuiExecutable) +find_package(KF5 REQUIRED Init) + +set(kfmclient_SRCS + kfmclient.cpp + konqclientrequest.cpp +) + +qt5_add_dbus_interface( kfmclient_SRCS ../src/org.kde.Konqueror.Main.xml konq_main_interface ) +qt5_add_dbus_interface( kfmclient_SRCS ../src/org.kde.Konqueror.MainWindow.xml konq_mainwindow_interface ) + +add_definitions(-DQT_NO_CAST_ASCII) + +set(kfmclient_LIBS + KF5::CoreAddons + KF5::KIOCore + KF5::KIOWidgets + KF5::I18n + KF5::WindowSystem + Qt5::DBus +) + +if (WIN32) + add_definitions(-Dkdemain=main) + add_executable(kfmclient ${kfmclient_SRCS}) + target_link_libraries(kfmclient ${kfmclient_LIBS}) +else (WIN32) + kf5_add_kdeinit_executable( kfmclient NOGUI ${kfmclient_SRCS}) + target_link_libraries(kdeinit_kfmclient ${kfmclient_LIBS}) + if(X11_FOUND) + target_link_libraries(kdeinit_kfmclient Qt5::X11Extras) + endif(X11_FOUND) + install(TARGETS kdeinit_kfmclient ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) +endif (WIN32) + +install(TARGETS kfmclient ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) + diff --git a/client/ChangeLog b/client/ChangeLog new file mode 100644 index 0000000..a32836e --- /dev/null +++ b/client/ChangeLog @@ -0,0 +1,14 @@ +1999-11-08 Kurt Granroth + * if 'exec' has no parameters, popup the Execute Command + dialog from kdesktop + +1999-05-28 Simon Hausmann + + * use kded instead of the ior file + * use KOMApplication instead of OPApplication (no need for + OpenParts at all) + +1999-04-28 Christophe Prud'homme + + * Makefile.am: $(top_srcdir) to $(top_builddir) + diff --git a/client/Messages.sh b/client/Messages.sh new file mode 100644 index 0000000..ca39dde --- /dev/null +++ b/client/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT -kaliasLocal *.h *.cpp -o $podir/kfmclient.pot diff --git a/client/kfmclient.cpp b/client/kfmclient.cpp new file mode 100644 index 0000000..b5eaa7e --- /dev/null +++ b/client/kfmclient.cpp @@ -0,0 +1,291 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2006 David Faure + + 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. +*/ + +#include "kfmclient.h" + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if KONQ_HAVE_X11 +#include +#endif +#ifdef WIN32 +#include +#endif + +static const char appName[] = "kfmclient"; +static const char programName[] = I18N_NOOP("kfmclient"); +static const char description[] = I18N_NOOP("KDE tool for opening URLs from the command line"); +static const char version[] = "2.0"; + +extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv) +{ + QApplication app(argc, argv); + + KAboutData aboutData(appName, i18n(programName), QLatin1String(version)); + aboutData.setShortDescription(i18n(description)); + KAboutData::setApplicationData(aboutData); + + QCommandLineParser parser; + aboutData.setupCommandLine(&parser); + + //qDebug() << "kfmclient starting" << QTime::currentTime(); + + parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("noninteractive"), i18n("Non interactive use: no message boxes"))); + + parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("commands"), i18n("Show available commands"))); + + parser.addPositionalArgument(QStringLiteral("command"), i18n("Command (see --commands)")); + + parser.addPositionalArgument(QStringLiteral("[URL(s)]"), i18n("Arguments for command")); + + parser.addOption(QCommandLineOption(QStringList{"tempfile"}, i18n("The files/URLs opened by the application will be deleted after use"))); + + parser.process(app); + aboutData.processCommandLine(&parser); + + const QStringList args = parser.positionalArguments(); + + if (args.isEmpty() || parser.isSet(QStringLiteral("commands"))) { + puts(i18n("\nSyntax:\n").toLocal8Bit()); + puts(i18n(" kfmclient openURL 'url' ['mimetype']\n" + " # Opens a window showing 'url'.\n" + " # 'url' may be a relative path\n" + " # or file name, such as . or subdir/\n" + " # If 'url' is omitted, $HOME is used instead.\n\n").toLocal8Bit()); + puts(i18n(" # If 'mimetype' is specified, it will be used to determine the\n" + " # component that Konqueror should use. For instance, set it to\n" + " # text/html for a web page, to make it appear faster\n\n").toLocal8Bit()); + + puts(i18n(" kfmclient newTab 'url' ['mimetype']\n" + " # Same as above but opens a new tab with 'url' in an existing Konqueror\n" + " # window on the current active desktop if possible.\n\n").toLocal8Bit()); + + return 0; + } + + // Use kfmclient from the session KDE version + if ((args.at(0) == QLatin1String("openURL") || args.at(0) == QLatin1String("newTab")) + && qEnvironmentVariableIsSet("KDE_FULL_SESSION")) { + const int version = atoi(getenv("KDE_SESSION_VERSION")); + if (version != 0 && version != KCOREADDONS_VERSION_MAJOR) { + qDebug() << "Forwarding to kfmclient from KDE version " << version; + char wrapper[ 10 ]; + sprintf(wrapper, "kde%d", version); + char **newargv = new char *[ argc + 2 ]; + newargv[ 0 ] = wrapper; + for (int i = 0; + i < argc; + ++i) { + newargv[ i + 1 ] = argv[ i ]; + } + newargv[ argc + 1 ] = nullptr; +#ifdef WIN32 + _execvp(wrapper, newargv); +#else + execvp(wrapper, newargv); +#endif + // just continue if failed + } + } + + ClientApp client; + return client.doIt(parser) ? 0 /*no error*/ : 1 /*error*/; +} + +static bool s_dbus_initialized = false; +static void needDBus() +{ + if (!s_dbus_initialized) { + extern void qDBusBindToApplication(); + qDBusBindToApplication(); + if (!QDBusConnection::sessionBus().isConnected()) { + qFatal("Session bus not found"); + } + s_dbus_initialized = true; + } +} + +static QUrl filteredUrl(const QString &url) +{ + KUriFilterData data; + data.setData(url); + data.setAbsolutePath(QDir::currentPath()); + data.setCheckForExecutables(false); + + if (KUriFilter::self()->filterUri(data) && data.uriType() != KUriFilterData::Error) { + return data.uri(); + } + return QUrl(); +} + +ClientApp::ClientApp() +{ +} + +bool ClientApp::createNewWindow(const QUrl &url, bool newTab, bool tempFile, const QString &mimetype) +{ + qDebug() << url << "mimetype=" << mimetype; + + if (url.scheme().startsWith(QLatin1String("http"))) { + KConfig config(QStringLiteral("kfmclientrc")); + KConfigGroup generalGroup(&config, "General"); + const QString browserApp = generalGroup.readEntry("BrowserApplication"); + if (!browserApp.isEmpty() && !browserApp.startsWith(QLatin1String("!kfmclient")) + && (browserApp.startsWith('!') || KService::serviceByStorageId(browserApp))) { + qDebug() << "Using external browser" << browserApp; + KStartupInfo::appStarted(); + + // TODO we don't handle tempFile here, but most likely the external browser doesn't support it, + // so we should sleep and delete it ourselves.... + KRun *run = new KRun(url, nullptr, false /* no progress window */); + QObject::connect(run, &KRun::finished, this, &ClientApp::delayedQuit); + QObject::connect(run, &KRun::error, this, [](){ qApp->exit(1); }); + return qApp->exec(); + } + } + + needDBus(); + + KonqClientRequest req; + req.setUrl(url); + req.setNewTab(newTab); + req.setTempFile(tempFile); + req.setMimeType(mimetype); + return req.openUrl(); +} + +bool ClientApp::openProfile(const QString &profileName, const QUrl &url, const QString &mimetype) +{ + Q_UNUSED(profileName); // the concept disappeared + return createNewWindow(url, false, false, mimetype); +} + +void ClientApp::delayedQuit() +{ + // Quit in 2 seconds. This leaves time for KRun to pop up + // "app not found" in KProcessRunner, if that was the case. + QTimer::singleShot(2000, qApp, SLOT(quit())); +} + +static void checkArgumentCount(int count, int min, int max) +{ + if (count < min) { + fprintf(stderr, "%s: %s", programName, i18n("Syntax error, not enough arguments\n").toLocal8Bit().data()); + ::exit(1); + } + if (max && (count > max)) { + fprintf(stderr, "%s: %s", programName, i18n("Syntax error, too many arguments\n").toLocal8Bit().data()); + ::exit(1); + } +} + +bool ClientApp::doIt(const QCommandLineParser &parser) +{ + const QStringList args = parser.positionalArguments(); + int argc = args.count(); + checkArgumentCount(argc, 1, 0); + + if (!parser.isSet(QStringLiteral("noninteractive"))) { + m_interactive = false; + } + QString command = args.at(0); + + if (command == QLatin1String("openURL") || command == QLatin1String("newTab")) { + checkArgumentCount(argc, 1, 3); + const bool tempFile = parser.isSet(QStringLiteral("tempfile")); + if (argc == 1) { + return createNewWindow(QUrl::fromLocalFile(QDir::homePath()), command == QLatin1String("newTab"), tempFile); + } + if (argc == 2) { + return createNewWindow(filteredUrl(args.at(1)), command == QLatin1String("newTab"), tempFile); + } + if (argc == 3) { + return createNewWindow(filteredUrl(args.at(1)), command == QLatin1String("newTab"), tempFile, args.at(2)); + } + } else if (command == QLatin1String("openProfile")) { // deprecated command, kept for compat + checkArgumentCount(argc, 2, 3); + QUrl url; + if (argc == 3) { + url = QUrl::fromUserInput(args.at(2), QDir::currentPath()); + } + return openProfile(args.at(1), url); + } else if (command == QLatin1String("exec") && argc >= 2) { + // compatibility with KDE 3 and xdg-open + QStringList kioclientArgs; + if (!m_interactive) { + kioclientArgs << QStringLiteral("--noninteractive"); + } + kioclientArgs << QStringLiteral("exec") << args.at(1); + if (argc == 3) { + kioclientArgs << args.at(2); + } + + int ret = KProcess::execute(QStringLiteral("kioclient5"), kioclientArgs); + return ret == 0; + } else { + fprintf(stderr, "%s: %s", programName, i18n("Syntax error, unknown command '%1'\n", command).toLocal8Bit().data()); + return false; + } + return true; +} + +void ClientApp::slotResult(KJob *job) +{ + if (job->error() && m_interactive) { + KJobWidgets::setWindow(job, nullptr); + job->uiDelegate()->showErrorMessage(); + } + const bool ok = !job->error(); + qApp->exit(ok ? 0 : 1); +} + diff --git a/client/kfmclient.h b/client/kfmclient.h new file mode 100644 index 0000000..a1de919 --- /dev/null +++ b/client/kfmclient.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + Copyright (C) 1999-2006 David Faure + + 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 KFMCLIENT_H +#define KFMCLIENT_H + +#include +class KJob; +class QUrl; +class QString; +class QCommandLineParser; + +class ClientApp : public QObject +{ + Q_OBJECT +public: + ClientApp(); + + /** Parse command-line arguments and "do it" */ + bool doIt(const QCommandLineParser &parser); + + /** Make konqueror open a window for @p url */ + bool createNewWindow(const QUrl &url, bool newTab, bool tempFile, const QString &mimetype = QString()); + + /** Make konqueror open a window for @p profile, @p url and @p mimetype, deprecated */ + bool openProfile(const QString &profile, const QUrl &url, const QString &mimetype = QString()); + +private Q_SLOTS: + void slotResult(KJob *); + void delayedQuit(); + +private: + bool m_interactive = true; +}; + +#endif diff --git a/client/konqclientrequest.cpp b/client/konqclientrequest.cpp new file mode 100644 index 0000000..21f8a4d --- /dev/null +++ b/client/konqclientrequest.cpp @@ -0,0 +1,157 @@ +/* This file is part of the KDE project + Copyright (C) 2017 David Faure + + 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. +*/ + +#include "konqclientrequest.h" +#include // KONQ_HAVE_X11 +#include +#include + +#include +#include +#include +#include +#include +#include + +#if KONQ_HAVE_X11 +#include +#endif + +#include +#include +#include +#include + +class KonqClientRequestPrivate +{ +public: + void sendASNChange(); + + QUrl url; + bool newTab = false; + bool tempFile = false; + QString mimeType; + QByteArray startup_id_str; +}; + +KonqClientRequest::KonqClientRequest() + : d(new KonqClientRequestPrivate) +{ + // read ASN env. variable + d->startup_id_str = KStartupInfo::currentStartupIdEnv().id(); +} + +KonqClientRequest::~KonqClientRequest() +{ +} + +void KonqClientRequest::setUrl(const QUrl& url) +{ + d->url = url; +} + +void KonqClientRequest::setNewTab(bool newTab) +{ + d->newTab = newTab; +} + +void KonqClientRequest::setTempFile(bool tempFile) +{ + d->tempFile = tempFile; +} + +void KonqClientRequest::setMimeType(const QString &mimeType) +{ + d->mimeType = mimeType; +} + +void KonqClientRequestPrivate::sendASNChange() +{ +#if KONQ_HAVE_X11 + if (KWindowSystem::platform() == KWindowSystem::Platform::X11) { + KStartupInfoId id; + id.initId(startup_id_str); + KStartupInfoData data; + data.addPid(0); // say there's another process for this ASN with unknown PID + data.setHostname(); // ( no need to bother to get this konqy's PID ) + KStartupInfo::sendChangeXcb(QX11Info::connection(), QX11Info::appScreen(), id, data); + } +#endif +} + +bool KonqClientRequest::openUrl() +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + const QString appId = QStringLiteral("org.kde.konqueror"); + org::kde::Konqueror::Main konq(appId, QStringLiteral("/KonqMain"), dbus); + + if (!d->newTab) { + KConfig cfg(QStringLiteral("konquerorrc")); + d->newTab = cfg.group("FMSettings").readEntry("KonquerorTabforExternalURL", false); + } + if (d->newTab) { + QDBusObjectPath foundObj; + QDBusReply windowReply = konq.windowForTab(); + if (windowReply.isValid()) { + QDBusObjectPath path = windowReply; + // "/" is the indicator for "no object found", since we can't use an empty path + if (path.path() != QLatin1String("/")) { + org::kde::Konqueror::MainWindow konqWindow(appId, path.path(), dbus); + QDBusReply newTabReply = konqWindow.newTabASNWithMimeType(d->url.toString(), d->mimeType, d->startup_id_str, d->tempFile); + if (newTabReply.isValid()) { + d->sendASNChange(); + return true; + } + } + } + } + + QDBusReply reply = konq.createNewWindow(d->url.toString(), d->mimeType, d->startup_id_str, d->tempFile); + if (reply.isValid()) { + d->sendASNChange(); + return true; + } else { + // pass kfmclient's startup id to konqueror using kshell + KStartupInfoId id; + id.initId(d->startup_id_str); + id.setupStartupEnv(); + QStringList args; + args << QStringLiteral("konqueror"); + if (!d->mimeType.isEmpty()) { + args << QStringLiteral("--mimetype") << d->mimeType; + } + if (d->tempFile) { + args << QStringLiteral("-tempfile"); + } + args << d->url.toEncoded(); + qint64 pid; +#ifdef Q_OS_WIN + const bool ok = QProcess::startDetached(QStringLiteral("kwrapper5"), args, QString(), &pid); +#else + const bool ok = QProcess::startDetached(QStringLiteral("kshell5"), args, QString(), &pid); +#endif + KStartupInfo::resetStartupEnv(); + if (ok) { + qDebug() << "Konqueror started, pid=" << pid; + } else { + qWarning() << "Error starting konqueror"; + } + return ok; + } +} diff --git a/client/konqclientrequest.h b/client/konqclientrequest.h new file mode 100644 index 0000000..050d2b4 --- /dev/null +++ b/client/konqclientrequest.h @@ -0,0 +1,75 @@ +/* This file is part of the KDE project + Copyright (C) 2017 David Faure + + 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 KONQ_CLIENT_REQUEST_H +#define KONQ_CLIENT_REQUEST_H + +#include + +class KonqClientRequestPrivate; +class QUrl; + +/** + * KonqClientRequest talks to a running Konqueror process, or starts a new one, + * in order to create a new window or tab for a URL. + * + * Usage: each instance of KonqClientRequest is a separate request. + */ +class KonqClientRequest +{ +public: + /** + * Creates a KonqClientRequest instance + */ + KonqClientRequest(); + /** + * Destroys this KonqClientRequest instance + */ + ~KonqClientRequest(); + + /** + * Sets the URL to open (mandatory) + */ + void setUrl(const QUrl& url); + /** + * Sets whether to open the URL in a new tab (optional, defaults to false) + */ + void setNewTab(bool newTab); + /** + * Sets whether the URL is a temp file that should be deleted after usage (optional, defaults to false) + */ + void setTempFile(bool tempFile); + /** + * Sets the MIME type of the URL (optional) + */ + void setMimeType(const QString &mimeType); + + /** + * This is the main method, call it to trigger the opening of the URL, + * once you have called all the relevant setters. + */ + bool openUrl(); + +private: + Q_DISABLE_COPY(KonqClientRequest) + + QScopedPointer d; +}; + +#endif diff --git a/config-konqueror.h.cmake b/config-konqueror.h.cmake new file mode 100644 index 0000000..8ed9208 --- /dev/null +++ b/config-konqueror.h.cmake @@ -0,0 +1,8 @@ +/* config-konqueror.h. Generated by cmake from config-konqueror.h.cmake */ + +/* Define to 1 if you have the KActivities library. */ +#cmakedefine KActivities_FOUND 1 + +/* compiling for X11 */ +#cmakedefine01 KONQ_HAVE_X11 + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..daf11ad --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,5 @@ +########### install files ############### + +add_subdirectory( kcontrol5 ) + +add_subdirectory( konqueror ) diff --git a/doc/kcontrol5/CMakeLists.txt b/doc/kcontrol5/CMakeLists.txt new file mode 100644 index 0000000..95e4464 --- /dev/null +++ b/doc/kcontrol5/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory( bookmarks ) +add_subdirectory( filemanager ) +#add_subdirectory( history ) commented from build like the code in sidebar/history_module +add_subdirectory( kcmcss ) +add_subdirectory( khtml-adblock ) +add_subdirectory( khtml-behavior ) +add_subdirectory( khtml-general ) +add_subdirectory( khtml-java-js ) +add_subdirectory( performance ) diff --git a/doc/kcontrol5/bookmarks/CMakeLists.txt b/doc/kcontrol5/bookmarks/CMakeLists.txt new file mode 100644 index 0000000..c6f28c5 --- /dev/null +++ b/doc/kcontrol5/bookmarks/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/bookmarks) diff --git a/doc/kcontrol5/bookmarks/index.docbook b/doc/kcontrol5/bookmarks/index.docbook new file mode 100644 index 0000000..72551fc --- /dev/null +++ b/doc/kcontrol5/bookmarks/index.docbook @@ -0,0 +1,101 @@ + + + +]> + +
+ + +Bookmarks + + +XavierVello +xavier.vello@gmail.com + + + + +2016-11-08 +Applications 16.12 + + +KDE +Systemsettings +bookmarks +KIO + + + +Bookmarks home page +This module lets you configure the bookmarks home page. +To view the bookmarks home page enter bookmarks:/ in +the location bar. +The settings in this module are also accessible by entering +bookmarks:/config in the location bar. + +General settings + + +Number of columns to show + +Folders are automatically distributed in several columns. The optimal number of columns depends on the width of the &konqueror; window and the number of bookmarks you have. + + + + +Show folder backgrounds + +Disable it on slow system to disable background images. + + + + + + +Bookmarks + + +Show bookmarks without folder + +If this option is unchecked, bookmarks at the root of the hierarchy (not in a folder) are not displayed. If checked, they are gathered in a "root" folder. + + + + +Flatten bookmarks tree + +Sub-folders are shown within their parent by default. If you activate this option, sub-folders are displayed on their own. It looks less nice but it may help if you have a very big folder you want to spread in two columns. + + + + +Show system places + +Show a box with common places (Home, Network, ...). Useful if you use &konqueror; as a file manager. + + + + + + +Pixmap cache + + +Disk cache size + +Specify how much disk space is used to cache the pixmaps. + + + + +Clear Cache + +Remove all cached images. This may be necessary if some favicons become corrupt and don't refresh automatically. + + + + + +
diff --git a/doc/kcontrol5/filemanager/CMakeLists.txt b/doc/kcontrol5/filemanager/CMakeLists.txt new file mode 100644 index 0000000..d667c59 --- /dev/null +++ b/doc/kcontrol5/filemanager/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/filemanager) diff --git a/doc/kcontrol5/filemanager/index.docbook b/doc/kcontrol5/filemanager/index.docbook new file mode 100644 index 0000000..76f5f7e --- /dev/null +++ b/doc/kcontrol5/filemanager/index.docbook @@ -0,0 +1,61 @@ + + + +]> + +
+ +File Management + +&Mike.McBride; &Mike.McBride.mail; + + + +2016-11-08 +Applications 16.12 + + +KDE +Systemsettings +file manager + + + +In these modules, you can configure various aspects of +&konqueror;'s file manager functionality. + +&konqueror;'s web browser functionality has its own configuration +modules. + + +<guilabel>Misc Options</guilabel> + +Open folders in separate windows + If this option is checked, a new +&konqueror; window will be created when you open a +folder, rather than simply showing that folder's contents in the + current +window. + + + +Show 'Delete' menu entries which +bypass the trashcan + +Check this if you want Delete menu commands to be +displayed on the desktop and in the file manager's context menus. +You can always delete files by holding the &Shift; key while calling +Move to Trash. + + + + +The settings for &konqueror;'s file manager mode on the View Modes, +Navigation, Services, General +and Trash pages are used by &dolphin; as well. + + +
diff --git a/doc/kcontrol5/history/CMakeLists.txt b/doc/kcontrol5/history/CMakeLists.txt new file mode 100644 index 0000000..b4ec7e7 --- /dev/null +++ b/doc/kcontrol5/history/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/history) diff --git a/doc/kcontrol5/history/index.docbook b/doc/kcontrol5/history/index.docbook new file mode 100644 index 0000000..27f805c --- /dev/null +++ b/doc/kcontrol5/history/index.docbook @@ -0,0 +1,62 @@ + + + +]> +
+History Sidebar + + +&Burkhard.Lueck; + + + +2009-11-24 +&kde; 4.4 + + +KDE +Systemsettings +history + + + + +This dialog allows you to configure the history sidebar. + + + +Limits + +The options in this section can be used to set the maximum size of your history and set a time after which +items are automatically removed. + + + + +Custom Font + +Here you can also set different fonts for new and +old &URL;s by selecting the Choose Font button. + + + + +Details + +The Detailed tooltips check box controls how much +information is displayed when you hover the mouse pointer over an item in the +history page. +If checked the number of times visited and the dates of the first and last +visits are shown, in addition to the URL. + + + + +Selecting Clear History will +clear out the entire history. + +
diff --git a/doc/kcontrol5/kcmcss/CMakeLists.txt b/doc/kcontrol5/kcmcss/CMakeLists.txt new file mode 100644 index 0000000..eeaa903 --- /dev/null +++ b/doc/kcontrol5/kcmcss/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/kcmcss) diff --git a/doc/kcontrol5/kcmcss/index.docbook b/doc/kcontrol5/kcmcss/index.docbook new file mode 100644 index 0000000..5fb737d --- /dev/null +++ b/doc/kcontrol5/kcmcss/index.docbook @@ -0,0 +1,367 @@ + + + +]> + +
+ +Appearance + +&Lauri.Watts; &Lauri.Watts.mail; + + + +2016-11-08 +Applications 16.12 + + +KDE +CSS +Appearance +Font +CSS +Stylesheets +Accessibility + + + + + +Appearance +This module consists of three tabs with configure options how to display web pages. + + +General + +The check box labeled Automatically load +images allows you to control whether images on web pages are +loaded by default. Unless you have a very slow connection, you will +probably want to leave this option selected, as there are many web pages +that are difficult to use without images. If you don't select the option +to automatically load images, you can still view the text on the page, +and then load the images if you need them. + +If Draw frame around not completely loaded images +is checked, &konqueror; will draw a frame as a placeholder +around images embedded in a web page that are not yet fully loaded. You +will probably want to check this box to enhance your browsing experience, +especially if have a slow network connection. + +Many web pages use animated gif images, and these can be very +annoying, and in some cases, quite a drain on your system resources. +The Animations option lets you choose when +animations are enabled. The default is enabled, but you can set this +to disabled, or to run the animation only once, even if the file +itself contains instructions that the animation should run more times, +or continuously. + +The next setting is Underline links:. You can +choose to underline links Enabled. If this option +is selected, any text on web pages that acts as a link will be shown in +an underlined font. While many web pages do use color to distinguish +text that acts as a link, underlining makes it very easy to spot +links. + +If you don't like underlined links, you can choose +Disabled, so that no links are underlined. Or you +can choose a middle ground, Only on Hover, so that links +are underlined when the mouse cursor is resting over them, and not +underlined the rest of the time. + +The site's CSS definitions can override this value. + +Smooth scrolling +determines whether &konqueror; should use smooth steps to scroll &HTML; +pages, or whole steps: + +Always: Always use smooth steps +when scrolling. +Never: Never use smooth scrolling, scroll +with whole steps instead. +When Efficient: Only use smooth +scrolling on pages where it can be achieved with moderate usage of system +resources. + + + + + + +Fonts +Under this tab, you can select various options related to the use +of fonts. Although the shapes and sizes of fonts are often part of the +design of a web page, you can select some default settings for +&konqueror; to use. + +The first thing you can set here is the font size. There are two +settings which work together to allow you a comfortable browsing +experience. + +Firstly, you can set a Minimum font size. +This means, even if the font size is set specifically in the page you +are viewing, &konqueror; will ignore that instruction and never show +smaller fonts than you set here. + +Next you can set a Medium font size. This is +not only the default size of text, used when the page does not specify +sizes, but it is also used as the base size that relative font sizes are +calculated against. That is, the &HTML; instruction +smaller, it means smaller than the size you set for this +option. + +For either option, you can select the exact font size in points by +using the up/down spin control (or just typing) next to the option +label. + +These options are independent of each other. Pages that do not +set a font size, or ask for the default, will display with the size +you set from Medium font size, while any pages +that ask for a size smaller than your Minimum font +size setting will instead show that size. The one does not +affect the other. + +The remaining options are for the fonts to be associated with +different types of markup used in &HTML; pages. Note +that many web pages may override these settings. For any type of font +(Standard, Fixed, Serif, &etc;) you can select a different font if you like. + +Below this, you can set a Font size adjustment for this +encoding. Sometimes the fonts you want to use for a +particular encoding or language are much larger or smaller than average, +so you can use this setting to bring them into line. + +You can set a default encoding that &konqueror; should assume +pages are when rendering them. The default setting is Use +Language Encoding, but you can change it to any encoding +available in the list. + + + + + +Stylesheets + + +Introduction + +CSS style sheets affect the way web pages +appear. CSS stands for +Cascading Style +Sheets. + +&kde; can use its own stylesheet, based on simple defaults and +the color scheme you are using for your desktop. &kde; can also use a +stylesheet that you have written yourself. Finally, you can specify a +stylesheet in this module. The options presented in this module are +tuned for accessibility purposes, especially for people with reduced +vision. + +Your choices here affect every &kde; application that renders HTML +with &kde;'s own renderer, which is called khtml. These include +&kmail;, &khelpcenter; and of course &konqueror;. Choices here do not +affect other browsers such as &firefox;. + + + + +Stylesheets + +This section contains the following options: + + + +Use default stylesheet + +&kde; will use the default stylesheet. Some of the colors will +default to those defined in your chosen color scheme. Most settings are +easily overridden by the page you are viewing. + + + + +Use user-defined stylesheet + +&kde; will use a stylesheet that you have written yourself. You +can use the browse button to locate the stylesheet on your system. +CSS files traditionally have a .css extension, but this is not +required. + + + + +Use accessibility stylesheet + +Use the settings defined in the Customize +dialog. Enabling this option will enable the Customize +button lo launch a dialog to define stylesheet settings. + + + + + + + +Customize + +In this dialog you can set up a user stylesheet. The options available are +only a subset of the instructions you can add in a stylesheet, and they +are geared towards people with reduced vision, to allow users to create +a stylesheet that makes web pages and the &kde; help files more +readable. + +The options in this dialog are disabled unless you chose +Use accessibility stylesheet. + + +<guilabel>Font Family</guilabel> + + + +Base family + +Choose a font family to use for body text. + + + + +Use same family for all text + +If you enable this, then the same font family will be used for all +text, regardless of the settings on the page you are viewing. This is +useful for pages which have used a decorative or hard to read font for +headlines. + + + + + + +Font Size + + + +Base font size + +This is the default size for text on the page. Many web sites set +their font sizes relative to this default, using larger +or +1 to make the text bigger, and smaller +or -1 to make the text smaller. +Many people design their web pages on platforms where the ordinary +default text size is too large for the average user to read, so it is +very common to come across web pages that have forced the font smaller +in this way. +This setting will allow you to set the default font to a +comfortable size, so that the relative sizes are also enlarged enough to +be comfortable. +Do not forget you can also have &konqueror; enforce a minimum size, +so that text is never too small to read. + + + + + + +Use same size for all elements + +If you enable this option, then all text will be rendered at your +specified font size, regardless of the instructions the page contains. +Relative font sizes as discussed earlier, and even specific instructions +that text should be rendered at a certain size will be overridden +here. + + + + + + +Images + + + +Suppress images + +If you do not want to view images, you can turn this off +here. + + + +Suppress background images + +One major problem for reduced vision users is that background +images do not give sufficient contrast to allow them to read the text. +You can disable background images here, independently of your choice +above to view all images. + + + + + + +Colors + + + +Black on white + +Many people with reduced vision find black text on a white screen +gives the most contrast, and is easiest to read. If this applies to +you, you can set this here. + + + + +White on black + +Many other people with reduced vision find the opposite to be +true, that white text on a black screen is easier to read. + + + + +Custom + +Still other people find that pure black and white, in either +order, is difficult to read. You can set custom colors here for both +the Background and the +Foreground. + + + + +Use same color for all text + +Many web sites use a different, often contrasting color for +headings or other flourishes. If this interferes with your ability to +read the content, you can enable this check box to have &kde; use the +colors you have set above for all text. + + + + + + + +Preview + +The Preview section allows you to see the effect of +your changes. Several types of headings are displayed with your stylesheet, +and a sentence in the default body text. + +This should allow you to fine-tune your stylesheet until you have +something that you can comfortably read. + +Happy surfing! + + + + + + + + + +
diff --git a/doc/kcontrol5/khtml-adblock/CMakeLists.txt b/doc/kcontrol5/khtml-adblock/CMakeLists.txt new file mode 100644 index 0000000..bc34e36 --- /dev/null +++ b/doc/kcontrol5/khtml-adblock/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/khtml-adblock) diff --git a/doc/kcontrol5/khtml-adblock/index.docbook b/doc/kcontrol5/khtml-adblock/index.docbook new file mode 100644 index 0000000..d588409 --- /dev/null +++ b/doc/kcontrol5/khtml-adblock/index.docbook @@ -0,0 +1,86 @@ + + + +]> + +
+ +AdBlocK Filters + +&Krishna.Tateneni; &Krishna.Tateneni.mail; + + + +2016-11-08 +Applications 16.12 + + +&konqueror; AdBlocK can be configured to replace or remove +images or frames from web pages that match a series of filters. + +The setting Enable filters enables or +disables the use of list of URL filters. +If Hide filtered images is enabled then +blocked images are completely removed from the page and the space they +occupied is reclaimed. If the option is disabled then a placeholder +image is used in place of filtered images. + + + +Manual Filter + +The main part of this tab is a list of +URLs that will be compared against image and frame names to decide +on fitlering actions. The wildcards can be given as filename style +regular expressions. + +Each filter can either be expressed as a file style wildcard +string (e.g. http://www.site.com/ads/*) or as a full regular expression +by enclosing the filter with forward slashes (e.g. //(ads|dclk)\./). + +Any filter string can be preceded by @@ to whitelist +(allow) any matching &URL;, which takes priority over any blacklist (blocking) +filter. + +Import and Export will +save or read the current filter list to a plain text file. The file begins with a +header line [AdBlock], then all of the filters follow each +on a separate line. Lines prefixed with an exclamation mark (!) +and the header line are treated as comments and can be used +to clarify or label a set of filters. + +Highlight an entry from the list to change it in the edit box or remove this item. +Enter a new filter string here and add it to the list using the +Insert button. + + + + +Automatic Filter + + +This tab shows a list of names and &URL;'s with predefined AdBlock filter entries. +To enable an entry tick the checkbox beside the filter name and adjust the +Automatic update interval (default 7 days). + + + + + + + +If AdBlock filters are enabled, an icon at the right side of status bar is shown. +Use a &RMB; click on this icon to open the context menu with actions to show all blockable +elements on a web page, open this &systemsettings; module and disable blocking for a site +or page temporarily. + +A click with the &LMB; shows the dialog with all blockable elements on the opened web page +as well. From this dialog you can add new filters directly without opening this &systemsettings; +module. + +
diff --git a/doc/kcontrol5/khtml-behavior/CMakeLists.txt b/doc/kcontrol5/khtml-behavior/CMakeLists.txt new file mode 100644 index 0000000..c61133f --- /dev/null +++ b/doc/kcontrol5/khtml-behavior/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/khtml-behavior) diff --git a/doc/kcontrol5/khtml-behavior/index.docbook b/doc/kcontrol5/khtml-behavior/index.docbook new file mode 100644 index 0000000..d212994 --- /dev/null +++ b/doc/kcontrol5/khtml-behavior/index.docbook @@ -0,0 +1,100 @@ + + + +]> + +
+ +Web Browsing + +&Krishna.Tateneni; &Krishna.Tateneni.mail; + + + +2019-11-04 +Applications 19.12 + + +KDE +Systemsettings +konqueror +browsing + + + + +Web Browsing + +The &konqueror; Browser module of &systemsettings; allows you to select +various options for the behavior of &konqueror;, the +integrated web browser of &kde;. + +If Ask for name and folder when adding bookmarks +is checked, &konqueror; will allow you to change the title of the +bookmark and choose a folder in which to store it when you add a new +bookmark. + +Enable Show only marked bookmarks in bookmark toolbar +and &konqueror; will show only those bookmarks in the +bookmark toolbar which you have marked to do so in the bookmark editor. + +The next option you can enable on this page is Form +Completion. If you check this box, &konqueror; will +try to remember what you answer to form questions, and will try to fill +in forms for you with the answers you previously used. + +You can configure the number of form items &konqueror; remembers +with the spin box labelled Maximum +completions + +Of course, anything &konqueror; fills in a form with, you +can still edit before submitting the form! + +The next option is Change cursor over +links. If this option is selected, the shape of the cursor +will change (usually to a hand) whenever it moves over a +hyperlink. This makes it easy to identify links, especially when they +are in the form of images. + +If Middle click opens URL in selection +is checked, you can open the &URL; in the selection by middle +clicking on a &konqueror; view. + +As a convenience feature, if you enable Right click +goes back in history, then clicking an empty area (&ie; not +a link) in the &konqueror; window will act as if you pressed the +Back button on the toolbar. + +Enabling Allow automatic delayed +reloading/redirecting allows websites to send you to +another page without your interaction. In many cases, this is a +convenience. For example, the website has moved to a new +&URL;. Many webmasters in this situation will put up +a page on the old site, telling you that it has moved and you may like +to change your bookmark, and then automatically move you along to the +new website. However, such features can be confusing, or annoying, +when misused, and so you may wish to disable it. + +Enable Access Key activation with &Ctrl; key: +Pressing the &Ctrl; key when viewing web pages activates Access Keys. +Unchecking this box will disable this accessibility feature. &konqueror; +needs to be restarted for this change to take effect. + +Send the DNT header to tell web sites you do not want +to be tracked. Check this box if you want to inform a web site +that you do not want to your web browsing habits tracked. + + +Offer to save website passwords. +Uncheck this box from being prompted to save website passwords + + +Display online &PDF; files using WebEngine. +Uncheck this box to display online &PDF; files as configured in the File Associations module of &systemsettings;. + + + + +
diff --git a/doc/kcontrol5/khtml-general/CMakeLists.txt b/doc/kcontrol5/khtml-general/CMakeLists.txt new file mode 100644 index 0000000..132f198 --- /dev/null +++ b/doc/kcontrol5/khtml-general/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/khtml-general) diff --git a/doc/kcontrol5/khtml-general/index.docbook b/doc/kcontrol5/khtml-general/index.docbook new file mode 100644 index 0000000..d105432 --- /dev/null +++ b/doc/kcontrol5/khtml-general/index.docbook @@ -0,0 +1,125 @@ + + + +]> + +
+General &konqueror; Behavior + + + +&Burkhard.Lueck; + + + +2016-11-08 +Applications 16.12 + + +On this page you find settings for home and start page and the behavior +of tabbed browsing both for &konqueror;'s file manager and browser mode. + + + +When Konqueror starts + +This option determines which page is displayed when &konqueror; starts, +the introduction page, your home page, a blank page or your bookmarks page. + + + + +Home page +This is the &URL; (⪚ a +folder or a web page) where &konqueror; in browser mode will jump to +when the Home Page button in the toolbar is pressed. +You can set a path that is your Home page by +typing into the text field, or using the browse +icon to select a local folder. &konqueror; needs to be restarted for +changes to take effect. +When &konqueror; is used in file manager mode, the Home Page +button in the toolbar is replaced by a Home Folder button +which makes it jump to your local home folder instead. + + + + +Open links in +new tab instead of in new window +&konqueror; defaults to a single window per page, but has the +capability to open multiple tabs inside a +single window. &konqueror; also, by default, has a &MMB; shortcut to +open any link in a new window. If you enable Open links in +new tab instead of in new window you can &MMB; click on a +link to have it open in a new tab. + + + +Open popups in new tab instead of in new window +Whether or not JavaScript popups if allowed shall open in a new tab or in a +new window. + + + +Open as tab in existing Konqueror when URL is called externally +When you click a &URL; in another &kde; program or call kfmclient to open a &URL;, +the current desktop will be searched for a non-minimized &konqueror; and, if +found, the &URL; opened as a new tab within it. Otherwise a new &konqueror; +window will be opened with the required &URL;. + + + +Open new tabs in the background +If you are using tabbed browsing, you can choose if a newly +opened tab becomes the active (front) tab, or goes to +the back. On a slow Internet connection, or while browsing a page +that has a list of headlines or other links in a list, you may like to +have the new tabs load in the background while you continue reading. +In this case, enable this setting. If you prefer to go +straight to the new page, leaving the old one in the background to +return to later, disable it. + + + +Open new tab after current tab +This will open a new tab opened from a page after the current tab, instead +of after the last tab. + + + +Hide the tab bar when only one tab is open +This will display the tab bar only if there are two or more tabs. Otherwise +it will always be displayed. + + + +Show close button on tabs +This will display close buttons inside each tab instead of websites' icons. + + + +Middle-click on a tab to close it +When you click on a tab using the middle mouse button or mouse wheel, it +will close that tab. &konqueror; needs to be restarted for changes to take +effect. + + + +Confirm when closing windows with multiple tabs +If you close a window in &konqueror; that has multiple tabs +open, &konqueror; will ask you if you're sure that you meant to close +it. You can toggle on and off this behavior with this +check box. + + + +Activate previously used tab when closing the current tab +When checking this the previous used or opened tab will be activated when +you close the current active tab instead of the one right to the current tab. + + + + +
diff --git a/doc/kcontrol5/khtml-java-js/CMakeLists.txt b/doc/kcontrol5/khtml-java-js/CMakeLists.txt new file mode 100644 index 0000000..1eb9379 --- /dev/null +++ b/doc/kcontrol5/khtml-java-js/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/khtml-java-js) diff --git a/doc/kcontrol5/khtml-java-js/index.docbook b/doc/kcontrol5/khtml-java-js/index.docbook new file mode 100644 index 0000000..bee23d1 --- /dev/null +++ b/doc/kcontrol5/khtml-java-js/index.docbook @@ -0,0 +1,144 @@ + + + +]> + +
+ +Java and JavaScript + +&Krishna.Tateneni; &Krishna.Tateneni.mail; + + + +2016-11-08 +Applications 16.12 + + +KDE +Systemsettings +konqueror +browsing +Java +JavaScript + + + + +&Java; and JavaScript + + +&Java; + +&Java; allows applications to be downloaded and run by a web +browser, provided you have the necessary software installed on your +machine. Many web sites make use of &Java; (for example, online +banking services or interactive gaming sites). You should be aware +that running programs from unknown sources could pose a threat to the +security of your computer, even if the potential extent of the damage +is not great. + +The check box Enable Java globally allows +you to turn &Java; support on for all web sites by default. You can +also select to turn &Java; on or off for specific hosts. To add a +policy for a specific host, click the New... +button to bring up a dialog in which you can type the host name and +then choose to accept or reject &Java; code from that particular host, +which will add the domain to the list on the left of the page. + +You can select a host in the list, and click the +Change... button to choose a different policy for +that host. Clicking the Delete button removes the +policy for the selected host; after deletion, the global settings will +then apply to that host. + +Finally, the group of controls labeled Java Runtime +Settings allows you to set some options for the way in +which &Java; should run. + +Use security +manager is normally enabled by default. This setting will +cause the JVM to run with a Security Manager in place. This will keep +applets from being able to read and write to your file system, creating +arbitrary sockets, and other actions which could be used to compromise +your system. Disable this option at your own risk. You can modify your +$HOME/.java.policy file with the +&Java; policytool utility to give code downloaded from certain sites +more permissions. + +Use KIO will cause the +JVMto use &kde;'s own KIO +transports for network connections. + +The Shutdown applet server when inactive for more than +check box allows you to save resources by closing the &Java; Applet +Server when it is not in use, rather than leaving it running in the +background. Leaving this disabled may make &Java; applets start up +faster, but it will use system resources when you are not using a +&Java; applet. If you enable this, you can set a timeout. + +You can either opt to have &konqueror; automatically detect the +&Java; installation on your system, or specify the path to the +installation yourself by selecting Path to Java +executable or 'java'. You may want to choose the latter method, for +instance, if you have multiple &Java; installations on your system, +and want to specify which one to use. If the &Java; Virtual Machine +you are using requires any special startup options, you can type them +in the text box labeled Additional Java +arguments. + + + + +JavaScript + +Despite the name, JavaScript is not related at all to +&Java;. + +The first part of this tab works the same as the &Java; settings. + +The checkbox Enable JavaScript globally allows +you to turn JavaScript support on for all web sites by default. You +can also select to turn JavaScript on or off for specific hosts. To +add a policy for a specific host, click the +New... button to bring up a dialog in which you +can type the host name and then choose to accept or reject JavaScript +code from that particular host, which will add the domain to the list +on the left of the page. + +You can select a host in the list, and click the +Change... button to choose a different policy for +that host. Clicking the Delete button removes the +policy for the selected host; after deletion, the global settings will +then apply to that host. + +The final set of options in the section Global JavaScript +Policies determine what happens +when a page uses JavaScript for specific actions. + +You can individually enable or disable the ability of JavaScript +to manipulate your windows by moving, resizing or changing focus. You +can also disable JavaScript from changing the status bar text, so that +for instance, you can always see where links will take you when +clicked. The choices for these options are Allow and +Ignore. + +For opening a new window, there is even more control. You can +set &konqueror; to Allow all such requests, +Ask each time a request is made, or +Deny all popup requests. + +The Smart setting will only allow +JavaScript popup windows when you have explicitly chosen a link that +creates one. + + + + +
diff --git a/doc/kcontrol5/performance/CMakeLists.txt b/doc/kcontrol5/performance/CMakeLists.txt new file mode 100644 index 0000000..ad628f9 --- /dev/null +++ b/doc/kcontrol5/performance/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kcontrol5/performance) diff --git a/doc/kcontrol5/performance/index.docbook b/doc/kcontrol5/performance/index.docbook new file mode 100644 index 0000000..5c38249 --- /dev/null +++ b/doc/kcontrol5/performance/index.docbook @@ -0,0 +1,46 @@ + + + +]> + +
+ +Performance + +&Mike.McBride; &Mike.McBride.mail; + + + +2016-11-08 +Applications 16.12 + + +KDE +Systemsettings +performance +preload + + + + +Performance Settings + +&konqueror;, is used on a wide variety of computers by a wide variety of users. Under the category of +performance, this dialog allows each user to adjust options which may make the computer that &konqueror; is +installed on feel more responsive. + +Preloading +The subsection labeled Preloading makes a tradeoff between memory and performance. + +Preloading refers to loading an instance of &konqueror; into memory before a user asks to start &konqueror;. The positive effect of this is that when a user asks to load &konqueror; the window appears instantly + because most of the application has been preloaded. The negative effect is that this instance of &konqueror; uses memory that +could be used by other programs. By default, when a user closes &konqueror;, the instance is not closed. +This means that the next time a user wants &konqueror; loaded, it is nearly instantaneous again. + +The final check box labeled Always try to have at least one preloaded instance signals that you always want to have one preloaded, but not used, instance of &konqueror; available. This option will actually decrease performance on some machines (especially those with limited physical memory). + + + +
diff --git a/doc/konqueror/CMakeLists.txt b/doc/konqueror/CMakeLists.txt new file mode 100644 index 0000000..692fe74 --- /dev/null +++ b/doc/konqueror/CMakeLists.txt @@ -0,0 +1,4 @@ +########### install files ############### + +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR konqueror) + diff --git a/doc/konqueror/cmndline.png b/doc/konqueror/cmndline.png new file mode 100644 index 0000000000000000000000000000000000000000..7e75303b33cd72f3a0a443718064697ddbdf0839 GIT binary patch literal 29810 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 literal 0 HcmV?d00001 diff --git a/doc/konqueror/dirtree.png b/doc/konqueror/dirtree.png new file mode 100644 index 0000000000000000000000000000000000000000..a579e4d180a4c82c6ace0c03a7631804076e17ff GIT binary patch literal 50550 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 IGd-XG1K2E9OaK4? literal 0 HcmV?d00001 diff --git a/doc/konqueror/dragdrop.png b/doc/konqueror/dragdrop.png new file mode 100644 index 0000000000000000000000000000000000000000..88f64c1d3b239fea082b9a30906c1293dc33d672 GIT binary patch literal 17849 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

L6iC++*iwc5i>n2+v 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 literal 0 HcmV?d00001 diff --git a/doc/konqueror/folders.png b/doc/konqueror/folders.png new file mode 100644 index 0000000000000000000000000000000000000000..b249fe749943eada76f8154f53808b69c26d7799 GIT binary patch literal 24357 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

wYpelO4T~}kbW>1Z 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 G^nU^T*psLL literal 0 HcmV?d00001 diff --git a/doc/konqueror/format-font-size-less.png b/doc/konqueror/format-font-size-less.png new file mode 100644 index 0000000000000000000000000000000000000000..ee2ac8dc8537c9b20357a596166143b6e1979119 GIT binary patch literal 531 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+ z;1LNlk?$}FGak=hkpdKCFY)wsWq-iIC(Nw(c*(i13=E8Ho-U3d7N_q9*m^Su3d|{I znONZHDaer-q`5@c>0e{2hjh~1NB1rZ-jd%L>1{%#W(0vrM zb4ROb_N=e(0}e?Ym{(^gyr+FT<}&~S%w(!Poc*N2=89bD~i@*l5o z)nc#enN!tMpRVEY_Qg+r??BngiWg_+7b%8u&j^_;zAybtUjBkf4%b=hK2=FdriwRJ z?n`?4n@Mu3(gxeNN6yOJzHRcwEB=a+(3F?i?Tci8Ia+=_vR|mn&~}>5TZj9Te=vRv zDVBXU$I2EMNU9~S5hW>!C8<`)MX5lF!N|bSOxM6d*U&h`$k58b(8|b2+rY@mz<~MO g`AsMqa`RI%(<*UmD4JZ(2h_me>FVdQ&MBb@0AB*ZBLDyZ literal 0 HcmV?d00001 diff --git a/doc/konqueror/format-font-size-more.png b/doc/konqueror/format-font-size-more.png new file mode 100644 index 0000000000000000000000000000000000000000..e5afc8cdbb9a77c5fc926556b7547ae9cf334197 GIT binary patch literal 513 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+ z;1LNlk?$}FGak=hkpdKCFY)wsWq-iIC(Nw(c*(i1K%p<5E{-7%|->(7Jzj zYlnnLcf$?sCEOmjwr&)O_I%HL<3`jo)*1%sZk1Mrrn&kGO}zplIyyYJUd)Tk4LRmy z_~iMn=+}4B-pwq2c82HA!4H|XC%4M3R$uI}@1%{}<}J;BSGU{N?$MiCR1ukCyXEDi zJ^52#@7F#rwP0TC6ycbcY!13R!?@h5;+8&ZXQ*R|+f%Vk|GH5_`y0ROlPwY_{F?H0 zWy|LG@pD(1KRZ`1sd+!4QMf8zf6K=uoZpQ?)FK#IZ0z|c(Bz(Uv1IK;@%%D~Xd$Vl73$jZQg`P}(UC>nC}Q!>*kacd}=T+Rp7 Oz~JfX=d#Wzp$Py`e!t)V literal 0 HcmV?d00001 diff --git a/doc/konqueror/go-jump.png b/doc/konqueror/go-jump.png new file mode 100644 index 0000000000000000000000000000000000000000..93b4cf1c1c256fab63041839176c43b982915a8d GIT binary patch literal 317 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 literal 0 HcmV?d00001 diff --git a/doc/konqueror/index.docbook b/doc/konqueror/index.docbook new file mode 100644 index 0000000..1084559 --- /dev/null +++ b/doc/konqueror/index.docbook @@ -0,0 +1,4336 @@ + +FSView"> + + +]> + + + + +The &konqueror; Handbook + + +&Pamela.Roberts; &Pamela.Roberts.mail; + + +The &kde; Team +Developers + + + + + + +2000 2002 +&Erwan.Loisant; +&Pamela.Roberts; + + +&FDLNotice; + +2016-11-05 +Applications 16.12 + +&konqueror; is &kde;'s advanced File Manager, Web Browser and + Universal Viewing Application. + + + +KDE +Konqueror +Kdebase +File Manager +Browser +Viewer + + + + + + + +&Pamela.Roberts; + + + + + +Overview + +&konqueror; is an advanced +file manager, +providing file management functions ranging from simple +cut/copy and paste operations to advanced local and remote network file +browsing. Folder contents can be displayed in a variety of text and icon +view modes, which can include thumbnail +preview images of file contents. File and folder properties can easily be +examined and changed, and applications launched with a simple click of the +&LMB;. + +In &kde; Applications &dolphin; is the default file manager. To change the +default component for browsing folders, open Default Applications +in the &systemsettings; and select &konqueror; as file manager. + +&konqueror; is an HTML 4.01 +compliant web browser with built in support for +JavaScript (ECMA-262), CSS (Cascading Style Sheets) and +bidirectional scripts (such as Arabic and Hebrew). It provides support for the secure +running of &Java; applets, &Netscape; plugins for viewing &Flash;, &RealAudio; +and &RealVideo; and SSL for secure +communications. Advanced features include automatic &URL; and form completion, +the ability to import bookmarks from other browsers and tabbed browsing. + + +&konqueror; is also an excellent full featured +FTP client. + +&konqueror; is a universal viewing application, +capable of displaying images and documents without having to launch another +application. It does this by embedding components (&kde; Parts) provided by +other applications; from &gwenview;; for image viewing, +&okular; for PDF, &PostScript; and other documents. + + +&konqueror; is a fully customizable application +which anyone can configure to suit their own +needs, from changing the overall style and the sizes of text and icons to +selecting which items appear in the Menubar, changing the number and +positions of the toolbars and even defining new shortcut key combinations. + + + + + + + + +&Pamela.Roberts; + + + + + +&konqueror; Basics + +Like all &kde; applications, &konqueror; is highly + configurable. This document describes how &konqueror; behaves with the normal, + default settings. + A three button mouse can be useful when you are running +&konqueror; or any other &kde; application. If your mouse only has two buttons +then you should be able to set your system up so that you can simulate a &MMB; +by pressing both buttons at the same time. +You can read more about mouse usage in +If you are used to having to double-click to perform an action, +then take care, because in common with the rest of &kde;, &konqueror; defaults +to single-clicking. + + +Starting &konqueror; + +Being a combined File Manager and Browser, +&konqueror; will automatically +switch between the two modes as needed when it is running, but it is convenient +to be able to choose which mode is to be used when you start it up. + + + +From the application launcher menu, select +InternetKonqueror (Web +Browser) to start it as a browser. + + +&Alt;F2 +will open &krunner;, enter a path to a folder and press +Enter to start in file manager mode, or just enter a &URL; such as + http://www.konqueror.org to start &konqueror; as a +browser. + + + +Click on the black arrow to the right of the Home Page icon +to switch to your Home Folder in the file manager mode and vice versa. + + +If &konqueror; is the default file manager it also starts automatically when you +left click on a desktop icon that represents a +folder, such as a hard disk drive or the Trash icon. + + + + + + +The Parts of &konqueror; + +A brief look at the main parts of &konqueror;'s window: + + + + +Here's a screenshot of &konqueror; + + + +The Titlebar is the strip across the top of +&konqueror;'s window, and operates in the same way as for other &kde; +applications. Right click on the central portion to +bring up the neat Titlebar menu. + +The Menubar is the strip containing the names of +the drop-down menus. Left click on a name to +alternately show and hide that menu, or use &Alt;the underlined +letter in the name as a hot key, for example &Alt;E to show the +Edit menu. The various menus are described in the Menubar section of this document. + +The Toolbar contains icons for commonly used +operations. Left clicking on an icon will activate +it. A brief description of what that icon does will appear when you hover +the pointer over it. + +Some icons, for example the Up and Back icons in the previous screenshot, +have a small black arrow at the right. If you click with the &LMB; +at this arrow a small dropdown menu will +appear. Right clicking on the +Toolbar will bring up the Toolbar Settings menu which you can use +to change the Toolbar's appearance and position. + +The Location Toolbar shows the path to the +directory, &URL; or file being viewed. You can type a path or &URL; here and +press Enter or left click on the +Go icon at the right hand end of the Location +Toolbar to go to it. The black icon at the right hand end of the +Location Toolbar clears the text entry box. + +The Bookmark Toolbar is the area under the +Location Toolbar in the previous screenshot. You can add +frequently used bookmarks here; see the Organizing Your Bookmarks section of this document. + +The Window is the main area of &konqueror; and +can show you the contents of a directory, web page, document or image. Using +the Window menu you can +split &konqueror;'s main window into one or more separate views, useful for +drag and drop operations, or set it to contain two or more tabbed views. + + +The Status Bar runs across the bottom of the +&konqueror;'s window +and often shows general information about whatever the mouse pointer is +hovering +over. If you have split the main window into a number of views you will get a +Status Bar for each view, and it will include a small green light at the left +hand end to show which is the active +view. Right clicking on the Status Bar brings up the +Status Bar Right Mouse +Button Menu. + +Don't worry if your &konqueror; doesn't look exactly like this +screenshot; it is highly configurable. In particular: + + +You can use the Settings menu to choose +whether to show or hide the Menubar, Main Toolbar, Location Toolbar and +Bookmark Toolbar, or even to add an Extra Toolbar. +If the toolbars are unlocked, you can also drag them to a new position by +left clicking on the handle at the left hand end +of a bar and move it around by holding the &LMB; down while you +drag it. + + + +For more details of how to change &konqueror;'s appearance, see the Configuring &konqueror; section + + + + +Tooltips and What's This? + +You can find out a lot about how &konqueror; works without needing to +read +this entire document if you take advantage of Tooltips and + the +What's This? feature. + +When you hover the mouse pointer over a Toolbar tab +button it should bring up a terse description of what that button does. + +What's This? is invoked by the Menubar +HelpWhat's This? item +or by &Shift;F1. +It changes the cursor to show a question mark alongside the arrow. + +When this question mark is visible, a &LMB; click won't actually do +anything until you have clicked on a control (or the text alongside it) that +supports What's This?, in which case it will +display +a reasonably comprehensive description of what the control does. +Most of the dialog boxes that &konqueror; brings up support the +What's This? feature. + + + + +<mousebutton>Left</mousebutton> and <mousebutton>Middle</mousebutton> +Mouse Button Actions + +If you click the &LMB; on an item in &konqueror;'s window, it will + be +activated. Thus + + + +Left click on an icon in the Toolbar +to perform the action that icon represents. +Left click on an item in the Menubar +to make that menu drop down. +Left click on a menu item to do that +thing. +Left click on an icon in the +Bookmark + Toolbar +to open that &URL;. +Left click on a link in a web page +to make &konqueror; follow that link. +Left click on a folder icon or +name and &konqueror; will descend into (show the contents of) that folder. + +Left click on a file name or icon +and &konqueror; will do whatever it thinks appropriate, based on the file type. +In general this means opening HTML pages, or previewing +text, image or +&okular; documents, showing them within &konqueror;'s +window (Preview means that you can see the file but not change +it). + +&konqueror; decides what the file type is by matching the filename +extension against a list of known types. If that fails it tries to guess +the type from the file contents. You can change the list of known file types +and associated actions with the File Associations page of +the SettingsConfigure Konqueror... + dialog. + + + +Clicking the &MMB; on a file or folder name or icon does essentially the +same as left clicking except that it usually does it +in a new &konqueror; window, unless the Open links in new tab instead +of in new window box has been checked in the +General page of the +SettingsConfigure +Konqueror... dialog. &konqueror; can open +links on pages and Bookmarks, +as well as the +Home, Up, +Back and Forward +entries in a new tab or window. + +Holding the &Shift; key down while pressing the &MMB; will open the link +in the background. + + + +<mousebutton>Right</mousebutton> Mouse Button Menus + +Clicking the &RMB; on almost any part of &konqueror;'s window +will bring up an appropriate context menu. + +If you have enabled the Right click goes back in +history option in &konqueror;'s +configuration settings a +simple right click is equivalent to clicking on the +Back button. In this case you can access the context +menu by moving the mouse with the right button held +down. + + + + +On the Titlebar +Right clicking on any free area of +the Titlebar brings up the Titlebar Menu, allowing you to control the position +of &konqueror;'s window as well as the decoration applied to all &kde; program +windows. + + + +On the Main Toolbar +Right click on any free area of the +Toolbar to bring up the Toolbar Menu. +You can also use the Toolbar Menu to set the size of the buttons on the +Toolbar, +and whether they are shown as icons, text or both. +Unlock the toolbar and you can move it to the top, bottom, left or +right of &konqueror;'s window. + + + + + +On the Location Toolbar +Right click in the + &URL; +entry box area to perform Cut, Copy, Paste or Clear operations in this area, or +to change the automatic Text Completion +features. + + + +Within a View +If you right click on any free area +of a view then you will get a menu that contains, among other options, the + Up, +Back, Forward and +Reload navigation commands. + + + + +On a File or Folder +This is a most useful feature. Right +clicking on the name or icon of any file or folder not only +selects that item but also brings up a menu allowing you to +Cut, Move, Copy or Remove the item in +various ways, open it with the program of +your choice or preview it, rename it, or edit the file type or +properties. + + +On the Status Bar +Right click on the Status Bar at the +bottom of a window or view to add or remove a view and lock or link views within &konqueror;'s +window. + + + + + + +Viewing Help, Man and Info Pages + +You can view &kde; Help and &UNIX; Man and Info pages directly in +&konqueror;, without having to start up &khelpcenter;. + + +To view a &kde; Help page, enter +help:/application name (for +example help:/kmail to view the &kmail; documentation.) +into &konqueror;'s Location Toolbar window. + + + +If you want to read &UNIX; Man pages &konqueror; makes it easy. For +example type man:/touch or +#touch into the Location Toolbar to see the page for +the touch command. + +To browse through &UNIX; Info pages, entering +info:/dir takes you to Info's top level directory, then +it's just a matter of clicking on the right links to find the page you +want. Alternatively, use info:/command +name to go straight to the Info page you want. + +Unfortunately, &kde; Help pages are stored in such a way that they +cannot be viewed in other browsers. If you really need to do this your only +recourse is to go online and visit +http://docs.kde.org. + + + + + + + +&Pamela.Roberts; + + + + + +&konqueror; the File Manager + + +Folders and Paths +In &UNIX; and &Linux; all folders are arranged in a simple +hierarchy. Starting from a top level folder (also called the root directory), +the structure descends and branches containing various files and subfolders. +This means that you can get from any folder to any other by going up + until you reach a common point then down through +the appropriate subfolders until you reach your target. + +The position of any file or folder in the structure (also called a +directory tree) can be described by its path, which is a simple +list of the folders you would have to descend through to get to the target +folder or file. For example /home/pam +is the subfolder pam of the subfolder +home of the top level folder, and +/home/pam/words.txt is the file words.txt + in that subfolder. The leading / in these paths +represents the top level folder. + +Every folder accessible by your system — including those on +other hard disk partitions, a USB device or &CD-ROM; — will appear +in the tree descending from /, their exact paths will depend on how your system +was set up (see also the section on Removable Devices). + +Every user on a &UNIX; / &Linux; system has their own home +folder to hold their personal files and settings; for example +/home/john and +/home/mary. The +symbol ~ is often used to represent the user's home +folder, so that ~/letter.txt refers to the file +letter.txt in my home folder. +Note that the term directory is often used instead of +folder. + + + +View Modes +In File Manager mode, &konqueror; lists which files and subfolders are +contained within a given folder and can provide you with some information about +them. The path of the current folder is shown in the Location +Toolbar. The way that &konqueror; displays the files and folders depends mainly +on your choice of view mode which can be selected from the +ViewView +Mode sub menu. The view modes &konqueror; provides +are outlined below. + + +In File Manager mode, &konqueror; uses an embedded &dolphin; +component. + + + + +In the Icons view, which is the default, files will be +represented by an icon that visualizes the file type, and a folder icon will be +shown for subfolders. The names of folders and files, and the items enabled in +ViewAdditional Information, +are displayed below the icons. + + + +The Compact view shows the folder contents as icons with +the name beside it and the items enabled in +ViewAdditional Information +below the name. The items are grouped in columns similar to the Short View +in the &kde; file dialog. + + + +In the Details view, the folder contents are displayed +as a detailed list which contains the name, size and last modification time of +each item. Additional columns can be added by clicking a column header with the +&RMB;. + +In the context menu of the header line you can choose between custom or automatic +column width. Automatic width adjusts the width of all columns once to display the longest +item in the column completely, except for the Name column where +the extension is replaced by ... + +The order of columns can be changed by drag and drop of column headers, except for +the Name header, which is always the first column in this view. + + +The details view allows you to view the current directory in a tree-like fashion if +Expandable folders are enabled: +Each subfolder of the current folder can be +expanded or collapsed by clicking on the > +or v icon next to it. + + + +Grouped View + + + + + +Grouped View + +All view modes support grouping by the sort type selected +in ViewSort by + + + + + +File Tip Info +Checking the Show tooltips box in the +File ManagementGeneral +page of the &konqueror; Configuration dialog causes a +small pop up information window to appear when the mouse pointer is hovered over +a file or folder name or icon. + + + + +File Previews +The Previews tab of the File Management +General settings page +lets you enable file previews for certain types of file. +Generally this means that the file's icon will be replaced by a small +image showing the file contents. +Because &konqueror; has to read much more data than just the file name +to generate a preview, file previews may not be appropriate when viewing +files from a remote system. To disable previews for remote files where reading +the extra data would take too long set a file size limit at the bottom of the +Previews tab. + + + + +Information in the View + +In all view modes &konqueror; shows at least an icon and a name for each item. +Using Additional Information in the View +menu or the context menu of the header in Details mode, you can select +more information for each item to be shown: + + + +Size, Date, +Type, Rating, +Tags or Comment. + + +Depending on the file type, additionally, the following criteria can be selected: + + Document: Number of words and lines + Image: Size and orientation + Audio: Artist, album, duration and track + + + +The Other submenu allows to select +Path, Link Destination, +Copied From, +Permissions, Owner or +User Group. + + + + + + + + +Folder View Properties + + +The following settings control how the contents of a folder are displayed in the +&konqueror; view, and are stored on a per-folder basis by default: + + + + +The view mode (Icons, Compact, Details) + + + +The sorting of items, which is determined by the sort order (ascending, +descending) and the attribute (such as name, size,...) that the items are +sorted by + + + +Sorting of folders and files – are folders shown first or not? + + + +Previews – are they shown instead of icons (based on the settings made in +Previews tab of &konqueror;'s General settings) or not? + + + +Are items shown in groups in the views? + + + +Are hidden files shown? + + + +What additional information (besides the name) is shown in the Icons or Details view? + + + + +The view properties can be configured in the +View menu, some (such as the view +mode) can also be changed using toolbar buttons. + + + +The View Properties Dialog + + + + +Screenshot of the View Properties dialog + + + + + +The View Properties dialog. + +The View Properties Dialog. + + + +The View Properties dialog can be used to quickly modify +several view properties at once. This is done for the current folder, for the +current folder including all subfolders, or even for all folders, depending on +the choice made in the Apply View Properties To section. + + + +If Use these view properties as default is enabled, the chosen view +properties will also be used for all folders which do not have customized view +properties yet. + + + + + + + +Navigation +To get to a file with &konqueror; you first need to navigate +through the folder tree to find the folder containing that +file. + +To move between folders you can simply step up and down the +tree: + + +To descend into a subfolder left + click on its name or +icon -- or if you have already selected it (see below) -- then just press +Enter. +To go up the folder tree you can click on the Up +button in the Toolbar, use&Alt;Up, or use the Menubar +GoUp +option. + + +To select a file or folder in the displayed folder +without opening it in any way use the up and down + arrow keys to move through the items. +The selected item will be highlighted and some information about it +will be displayed in the Status Bar. + +Setting the View Mode to +Details can help you locate folders in the tree below the +current folder; in this mode each folder is shown with a small box at +the left. If the box contains a > sign, left + clicking on the box (not on the folder name or icon) will +display a sub tree showing files and subfolders contained in that folder. +The small box will then change to show a v sign. +Left click on that to collapse the sub tree. Once +you have found the folder you are looking for, left + click on the folder name or icon to open it. + +You can go directly to any folder by switching with + FileOpen Location + or &Alt;O + to the Location Bar and typing its path. +&konqueror;'s +Text Completion feature may be useful when you do this. Don't forget +that in &Linux; / &UNIX; file and folder names are case sensitive. + +When you have moved to a new folder you can go back to your +previous choice by using the Toolbar Back button, the +Menubar +Go Back +item, or &Alt;Left. +Once you have gone back you can go forward. Use the Toolbar +Forward button, the Menubar +Go +Forward item or &Alt;Right. + +Alternatively, you can also choose to enter the parent folder by clicking on the Toolbar Up, the Go Up item, or with &Alt;Up. + +Click the checkmark at the right of the toolbar Up, +Back or Forward buttons or selecting these +items in the Go menu brings up a submenu of recently visited locations. + + + +Finding Files and Folders + +If you don't know or can't remember where a file or folder is within +your system, then use the shortcut &Ctrl;F or the +Menubar ToolsFind +File... option. This starts the file finder +application &kfind;. See the &kfind; Handbook +for help in using &kfind;. + + +If the name of a file or folder begins with a period (dot), then +it is a hidden file or folder, and will not normally be shown +by &konqueror;. To see hidden files or folders use the Menubar +ViewHidden Files + option. + +Another reason &konqueror; may not show the file or folder you are +looking for is that you may have the +Directory Filter plugin set to display only certain types of +file. + + + + + +Removable Devices + +Any removable device (USB stick, floppy disk, &CD; drive or other hard disk partition that you have +on your system) will usually appear in the / +, /media, /mnt or +/auto folder, having a path something +like /mnt/floppy or +/cdrom. The details will depend on +how your system was set up. + +&UNIX; / &Linux; requires that you mount a removable device +when you have inserted it into the drive, and mount + other hard disk partitions when you want to access them. You also +need to unmount a removable device before removing it to register that +it is no longer available. + +How you do this will depend on your system setup: + + + +Using the Device Notifier +In a &kde; session the Device Notifier +window will popup, when you insert a removable device and allows you to select +an appropriate application for this media or only mount the device. + +If you use the Folder View layout for your desktop +you may have icons for removable devices on your desktop, +in which case &LMB; click on the icon to mount it. +Doing this should also bring up a &konqueror; window showing the contents of +the device. To unmount, right +click on the icon and choose the Unmount item. +Visit the section Create New... in this Handbook +to see how to create such an icon. + +Or you can do it the traditional way by typing into a text +console window: +mount /mnt/floppy +to mount, for example, the floppy drive, and +umount /mnt/floppy +to unmount it (umount not unmount). + +Rather than having to open a text console to type the +mount + or umount commands, you may prefer to use +&konqueror;'s ToolsExecute Shell +Command +(&Ctrl;E) + feature. + + + + + + + + + + +Deleting Files and Folders + +&konqueror; gives you two ways to dispose of an unwanted file or +folder: + + +You can move it to the Trash folder, which +is the safest method as you can get it back if you realize that you have made a +mistake. + +You can just plain Delete it, which +removes the entry from the folder and adds the disk area occupied by the +file(s) to the system's list of free disk areas, in the same way as the +rm command. +If you want to use this feature check the option Show 'Delete' +menu entries which bypass the trashcan on the File +Management settings page. + + +The simplest way to remove a file or folder is to position +the mouse pointer over its name or icon and press the &RMB;, which +will bring up a menu containing the options Move to +Trash and Delete. + +Or, if you have selected the item, the Menubar +Edit menu will give you the choice of +Move to Trash and +Delete options. + +Del will move the selected item or items to Trash. + +&Shift;Del +will really, truly and irrevocably delete the selected item or +items. + +You won't be able to remove a file or folder if you don't have +the necessary permissions. + + + + +Moving and Copying + +To copy a file or subfolder between folders you can: + + +Position the mouse pointer over its name or icon and hold down +the &RMB;, which will bring up a menu containing the +Copy option. Choose that. + +Or if the item is selected you can use the +Copy button on the Toolbar or the Menubar +Edit +Copy +item, or the &Ctrl;C +shortcut key combination. You can also select multiple +files or folders to copy/move as well. + +Navigate to the folder you want to copy the item into then +Paste the item into the new folder by using the Toolbar +Paste button or the Menubar +Edit +Paste option or the &Ctrl;V shortcut, or by +moving the mouse pointer to a clear area of the window and holding the &RMB; +down to bring up a menu containing the Paste option. + + + +Moving a file or subfolder between folders can be done in the +same +way as copying, except that you choose the Cut +option +or &Ctrl;X +instead of Copy. The item that you have +Cut will be removed from the original folder when +you do the Paste into the new folder. + +You can also copy or move selected item(s) to another folder by selecting +Copy To or Move To from +the context menu you get when you right click on +a file or folder name in the File Manager window. +To enable this feature select Show 'Copy To' and 'Move To' +commands on the File Management +Services page of the settings. +You may not be able to copy or move a file or folder if +you don't have the necessary permissions. + + +Using Drag 'n Drop + +&konqueror; also supports Drag and Drop copying and moving of files and +folders. + +You can do this by having two instances of &konqueror;, one showing the +folder you want to copy from, the other showing the target folder. +Position the mouse pointer over the item you wish to copy or move, then, +holding the &LMB; pressed, drag it to a clear space in the +target folder. Release the button and you will be +presented with a menu choice of Copy Here, +Move Here or Link Here. +Take care to drop the item into an empty area of the target +folder view - dropping it on top of a subfolder will copy or move the item +into that folder. + +You can also set up &konqueror; to show more than one folder within +its window and drag & drop between them. + + + + +Split Views for Drag & Drop + + + +This screenshot illustrates the use of the Menubar +Window Split View +Left/Right option, also available with the shortcut +&Ctrl;&Shift;L, +to split the main &konqueror; window into two views, each showing the contents +of a different folder. + +To be able to show different folders in each view they should not be +linked; the little boxes at the bottom right of each view should be empty. + + +The active view, that is the one whose path is shown in +the Location Toolbar and which responds to navigation and Menubar commands, is +shown by the little green light in the bottom left corner. To make a view +active, left click on an empty area of the view or +on its Status Bar. + +To remove an active view from &konqueror;'s window use the &Ctrl;&Shift;W shortcut, +or the Menubar WindowClose +Active View option, or &RMB; click on the Status Bar +and choose the Close View option from the +resulting menu. + +If you use &konqueror; tabs, you can drag and drop between tabs +by dragging the file to the tab label, without letting go yet. The +destination tab will pop to the front, allowing you to continue +dragging and then to drop the file. + + + + +Duplicate File or Folder Names +If you try to paste a file or folder into a folder that already +contains an item with the same name, &konqueror; will pop up a dialog box warning +you that the item already exists. You can then choose to: + + +Cancel the paste operation by pressing the +Cancel button. +Give the item that is being copied a different name. You can +do this by typing a new name into the text entry box or get &konqueror; to +Suggest New Name. When you have done this press the +Continue button. + +If you have copied multiple items, Skip the current item. + + +The Apply to All button can be used if you have copied +multiple items. + + + + +Selecting Items in the View + + +There are several ways to select items in the view. Once a group of items +is selected, all actions, such as +Cut, +Copy, +Move to Trash, +and drag and drop operations, affect all selected items. + + + +Selecting Items Using the Mouse + + + + +You can press the &LMB; somewhere in the view and draw a rectangle around +a group of items before releasing the button. This will select all items in the +rectangle and clear the previous selection. If the &Shift; key is pressed during +the selection process, the previous selection is kept. + + + +If the &Ctrl; key is pressed while an item is clicked with the &LMB;, the +selection state of this item is toggled. If the &Ctrl; key is pressed while a +rectangle is drawn around a group of items as described above, the selection +state of all items in the rectangle will be toggled. + + + +If the &Shift; key is pressed while an item is clicked with the &LMB;, all items +between the previous current item and the clicked item will be selected. + + + +If Show selection marker is enabled in the +Behavior tab of the File Management +General section of the settings, a small ++ or - button appears in the top +left corner of the item which is currently hovered over with the mouse. Clicking +this sign selects or deselects the item, respectively. + + + + + + + +Selecting Items Using the Keyboard + + + + +If an arrow key, PgUp, PgDn, +Home, or End is pressed, the new current item +is selected, and the previous selection is cleared. + + + +If the &Ctrl; key is held while one of the above keys is pressed, the selection +remains unchanged. + + + +If the &Shift; key is held while one of the above keys is pressed, all items +between the previous current item and the new current item will be selected. + + + +If &Ctrl;Space is pressed, +the selection state of the current item is toggled. + + + +&Ctrl;A selects all items +in the view. + + + +&Ctrl;&Shift;A toggles the +selection state of all items in the view. + + + +Select a file or folder by typing the first few letters of its name and the +first matching item is selected. +To clear the selection and cancel the keyboard search press &Esc; or wait longer than +the timeout of 1 second. + + + + + + + + +Selecting Items Using the Menu + +You sometimes want to delete, copy or move a number of files that are +similar in some way. For example you may wish to move all of the .png graphics +files from one folder to another. &konqueror; makes this easy by letting you +select multiple files based on similarities in their file names. + +Use the Menubar +EditSelection +Select Matching Items... option or the shortcut +&Ctrl;S. This +brings up a little dialog box in which you enter a filename containing +the wildcard characters *, which matches any number +of characters, and ? which matches a single +character. Press OK and &konqueror; will +highlight all files with matching names. For example: + + + flag*.png will +select all filenames starting with the letters flag and ending +with .png. +memo?.txt will +select memo1.txt and memo9.txt but +not memo99.txt. + + +When you have selected a range of files, you can narrow down the +selection +by using the Menubar EditSelection +Unselect Matching Items... option to specify +which of the selected files should be removed from the selection. + +Use the Menubar EditSelection +Unselect All option or just +&LMB; click on a clear area of the view to cancel the +selection. + +You can even invert the selection: that is, deselect all selected +files and select those that were previously unselected. Use the +Menubar EditSelectionInvert +Selection option or &Ctrl;&Shift;A to do this. + + + + + +Create New + +When &konqueror; is in File Manager mode, picking +Create New from the Edit +menu or from the context menu you get by &RMB; clicking on a free +area in a folder view gives you a submenu letting you create any +of the following in the current folder: + + + + +Folder... +An easy way of creating a new (sub)folder. + + + +Text File... +Use this to create an ordinary, empty, text file. A +dialog box will be opened for you to enter the name of your new +file. + + + +HTML File... +Creates a skeleton HTML source file. When +you type the new file's name into the dialog box it is probably best to give +it a .html extension to avoid +confusion. + + + +Type of Document Document... +Depending on the installed applications and file associations +several menuitems for different types of documents are displayed and enable you +to create skeleton documents of the selected type. + + + +Link to Location (URL)... +This lets you create an icon to open &konqueror; at a +particular folder or web page. As with Link To Application... +you can make the application icon appear on your desktop by creating the link +in your ~/Desktop folder or going to the Create +New... sub menu by right clicking on a free area of the +desktop. + + + +Basic link to file or directory... +Create a symbolic link for local files or folder. + + + +Link to Application... +This option is most useful if you want to create an icon that +will open a particular application. It opens a dialog box with several tabbed +pages. The first, General, is where you choose an icon and +the text that will appear with it. The second page, +Permissions, lets you select who can use or modify the +icon. In the Application page you must enter the Command that +will run the application, for example, kwrite to start up +the &kwrite; text editor. kwrite /home/pam/todo.txt would +open the file /home/pam/todo.txt in &kwrite;. Advanced +options such as the file types which the application can open are also +available from this page. + +To make the application icon appear on your desktop, create the link in +your ~/Desktop folder (this may be +called something slightly different depending on how &kde; was installed on +your system) or get to the Create New... sub menu by +right clicking on a free area of the desktop +instead of within &konqueror;'s window. + +If you have a lot of specialized application links and don't want to +clutter up the desktop, then why not create them in your Applications +folder. You can get there in &konqueror; by choosing Go +Applications. Then create a single icon +on your desktop to open your Applications folder, which is usually in +~/.local/share/applications. +To put an application link icon into the panel, first create it in the +Applications folder then drag the icon onto a clear area of the +panel. + + + + + +Link to Device +Use the options in this submenu to create an icon that will mount a device +and open an instance of &konqueror; showing it's contents. To unmount the +device when you have finished with it right click on +the icon and select Unmount. +However, in most cases you will want to create the icon on your desktop. + + + + + + + + +Changing Names and Permissions + +The two easiest ways to change the name of a file or folder is to either +right click on it and select +Rename, or select the file or folder and then press the F2 key. + +To change the name or permissions of a file or folder +right click on its name or icon and select the +Properties item, or if you have +selected the file or folder, then you can use the Menubar +EditProperties + (&Alt;Return) option. + +This will bring up the Properties dialog box with several tabbed +pages: + + +General, which gives you some +information about the item and lets you change its name and, for a folder, +the associated icon. +Permissions, which shows you the item's +ownership and access permissions and lets you change the permissions. + + + + +Copy and Rename +If you want to make a copy of an existing file with a different name -- +perhaps as a backup -- in the same folder as the original file, do a normal +Copy then when you Paste +it a dialog box will pop up complaining that the file already exists. +Just type the new name into the dialog's text box and press the +Continue button (or if you are feeling lazy pressing the +Suggest New Name button will generate a new name for you). + + + + + +Configuring File Associations + + + +&kde; provides many applications which can open many different +types of file. Most of the time, the defaults will work with no +problems, but &konqueror; provides a powerful system to allow you to +change the applications used to open each file type. For more details, +choose the +SettingsConfigure +Konqueror... menu item, select +File Associations in the configuration dialog, +and click on Help. + + + + +At the Command Line + +Although &konqueror; is a very powerful and flexible +GUI file manager, there are occasions when the experienced +&Linux; / &UNIX; user wants to get down to the basics and work at the text +command line level. + +You can, of course, open an instance of &konsole;, perhaps with +&konqueror;'s Menubar ToolsOpen +Terminal option or with F4. +If you only want to launch a program or view a &URL;, the +ToolsExecute Shell Command... +(&Ctrl;E) option may be +easier. + +ToolsExecute Shell Command... + (&Ctrl; +E) opens a small command line dialog window where +you can enter a shell command such as ps -ax | grep kdeinit +. Note that it does not support full featured terminal control +characters, so applications such as top and +less will not work properly, but it is available immediately +without the delay involved in starting &konsole;. + + +For more complex operations, &konqueror; has another nice feature: the +Menubar SettingsShow Terminal +Emulator option, which opens up a terminal window as +a new view within &konqueror;. + + + +Including the terminal emulator + + + + + + + + + + + +&Pamela.Roberts; + + + + + + +&konqueror; the Web Browser + + + + +Browsing www.konqueror.org + + + + +Connecting to the Internet + +Once you are connected to the Internet you can use &konqueror; to browse +the Web just as easily as you can use it to handle your local files. Just type +a &URL; into the Location Toolbar window, press +Enter, and you are away! + + +If you use a dial-up modem connection, then you will be using +&kppp; or a similar dialer program to make the connection. + +If your machine is connected to a local area network +(LAN) that gives you a proxy connection to the Internet +then you will have to set &konqueror; up for the proxy connection. This can be +done with the Web Browsing +Proxy page of the +SettingsConfigure Konqueror... + dialog. + +If you are lucky enough to have a high speed cable connection, +then the service provider will probably give you an external cable modem which +needs an ethernet connection to your machine. Unfortunately the details of how +to establish the connection depend on the service provider and to some extent +on which Linux/&UNIX; distribution you are using. Some ISPs +connect their customers to the Internet through a proxy server, in which case +you will have to set up &konqueror; to use it. You may find it useful to +search the archives of your distribution's user group mailing list for +help. + + + +An error message such as Unknown Host +usually means that &konqueror; cannot find a connection to the Internet or that +you have entered an incorrect &URL;. + + + + +Surfing and Searching + +Once you have a connection to the Internet, you can surf with +&konqueror; just as you can with any other browser. + +Type a &URL; into the Location Toolbar window, press +Enter or left click on the + + + +Go button at the right hand end of the Location +Toolbar, and &konqueror; will download and display that page. +If you have visited the page before, &konqueror;'s +Automatic Text Completion feature can help +you type the &URL; a second time. + +If you want to use one of +the web's search engines, &konqueror;'s +Web Shortcuts feature can make this easier. + +Left click on a link in a page to +open that link. + +To open a link in a new instance of &konqueror;, leaving the +old page still visible, &RMB; click on the link and select the +Open in New Window option. Alternatively, +you might want to Open in New Tab. +Tabbed Browsing will let +you hold a number of pages in one &konqueror; window and quickly switch +between them with a single mouse click. + +You could also select multiple view modes with +Window Split View +Left/Right (&Ctrl; +&Shift;L) / Window +Split View Top/Bottom (&Ctrl; +&Shift;T) option which will let you see different +pages at the same time. This can be useful if you are looking through a +complicated set of HTML pages, but make sure the little link +box at the bottom right hand corner is empty when you are doing +this. +To go back to the previous page use the &Alt;Left +shortcut, the Back button on the Toolbar, or the menubar +Go Back +option. +Similarly, once you have gone back you can go forward by using +&Alt;Right, the +Forward button, or the menubar +Go +Forward option. + + + +There are multiple ways of scrolling the viewing area. One is to use the +Up and Down keys. You may also use +the scrollbar, your mousewheel or the PgUp and PgDn +keys. +If you want to read a long webpage use the automatic scrolling feature of &konqueror;. +Start automatic scrolling with &Shift;Down or +&Shift;Up. Then use these keys to increase and +decrease the scrolling speed. You can start or stop automatic scrolling temporarily by pressing the &Shift; key; +pressing any other key deactivates this feature. + +Automatic scrolling works only in the view mode KHTML. + +If you want to stop a download for any reason then use the +&Esc; key, the Toolbar Stop button or the +Menubar View +Stop item. + +When you are viewing a web page with the HTML Toolbar +enabled you should see two new icons in the toolbar + + and + +. Use these to adjust the size of the text in the +page if you find it difficult to read. How well this works will +depend on how the web page has been constructed. + + + +Tabbed Browsing +By using this feature you can make &konqueror; load multiple web pages in +the same window, and switch between them using tabbed pages. This way, you can +preload a page in the background while you carry on reading another. + +To use tabbed browsing, right click on a +link and choose Open in New Tab from the drop down +menu or &MMB; click. The page will be downloaded and displayed as normal, but with tabs +across the top of the view, one tab for each page. &LMB; click on a +tab to view that page, or you can use the shortcuts +&Ctrl;, and +&Ctrl;. to cycle through +the tab pages. Alternatively, you can scroll through the tabs using +the mouse wheel while the mouse pointer is +over the tab bar (presuming that your mouse has one). Also, +double-clicking over the empty tab bar space will open a new +tab. + +Using the Open new tabs in the background option in the +General page of the Settings +dialog, clicking on a link downloads the page and shows a new tab for it, but the new +page will not be displayed until you left click +on the tab. + +If you check the Open links in new tab instead of in new +window box in the General page of the +SettingsConfigure Konqueror... + dialog, &MMB; clicking on a link will open it +in a new tab page and if you hold the &Shift; key down while clicking the +&MMB; the link will be opened in a background tab page. + +Right clicking on a tab will bring up a +menu with the following options: + + + +New Tab (&Ctrl;T) +This opens a new, blank, tabbed page view. +You can then download a web page into it by typing the &URL; into the +Location Bar or by making a selection from the Bookmark Toolbar. + + + +Duplicate Tab (&Ctrl;D) +To create a duplicate tabbed page. + + + +Reload Tab (F5) +Reloads the content of the current tab. + + + +Other Tabs +Displays a submenu showing all other tabs. Choosing a tab from +this list makes it the active tab. + + + +Other TabsReload All Tabs + (&Shift;F5) +Reloads the content of every tab. + + + +Other TabsClose Other Tabs +To close all but the selected tab page. + + + +Detach Tab (&Ctrl;&Shift;B) +This option removes the selected tabbed +page from the current &konqueror; window and opens it in a new instance of +&konqueror;. + + + +Close Tab (&Ctrl;W) +To close the selected tab page. + + + + + + +Web Shortcuts + +If enabled, &konqueror;'s Web Shortcuts +feature lets you submit a query directly to a search engine or similar web site +without having to visit the site first. For example, entering +gg:konqueror into the Location Bar and pressing Enter +will ask Google to search for items related to +&konqueror;. +To see what Web Shortcuts are available, and perhaps +add your own, open the Web Shortcuts +module in the &systemsettings; category Workspace. + + + + + +Access Keys + +&konqueror; has full support for the +accesskey &HTML; attribute in +forms and links. Access keys allow you to use +the keyboard keys for functions which would perhaps normally be done +with the mouse, such as following links. The benefit of this is, quite +simply, that users can interact with a page with devices other than a +pointing device. +This feature has to be enabled by checking the Enable Access +Key activation with &Ctrl; key option on the Web +Browsing settings page. +To activate the access keys in &konqueror;, press and release +&Ctrl;. Once this is pressed, if a particular link on the website has +the accesskey attribute in the given link, then the +character(s) should appear over the link, identifying what needs to be +pressed. Then, you can enter the character(s) associated with the link +as an alternative to following the link with the mouse. To disable the +access keys once activated you can press &Ctrl; again. + +The proper use of this feature requires that the web +designer of the page has specifically assigned, using the +accesskey attribute, an access key for the +link. Many web designers might not include the +accesskey in their links and forms, and +consequently this feature will be unusable on the given +webpage. + + + + +Browser Identification +When &konqueror; connects to a web site it sends some brief browser +identification information, known as the User Agent string. +Many web sites use this information to customize the pages that they send +back, based on the strengths and weaknesses of different browsers. +Unfortunately, some badly designed sites refuse to work properly +unless you are using a browser that the site recognizes as a +valid one, even though if given a chance, &konqueror; will +work satisfactorily with the vast majority of web pages. +To overcome this problem you can change the browser identification +information that &konqueror; sends for specific sites or domains by +selecting the Browser Identification +module in the &systemsettings; category Network. +Problems with getting a web page to work properly may also be due +to its use of &Java; or JavaScript. If you suspect that this may be the case +check that they have been enabled in the Java & JavaScript +section of the settings dialog. + + + + +Saving and Printing Web Items + +When you are viewing a web page you can save it (or at least the basic +&HTML; or similar source text) to your local disk with +FileSave +As.... If the page +you are viewing uses frames, then you will also be given the +FileSave Frame +As... option. Left click + in the frame you want to save first. + +If the page uses a background image, you can get and save that with the +FileSave Background +Image As... option. + +But if what you really want is that glorious picture of the latest +Ferrari, then right clicking on the image will +give you a drop-down menu with a +Save Image As... option. Be sure to respect the +owner's copyright, and ask for permission before using any pictures saved this +way for anything other than your own viewing pleasure. + +If you right click on a link (which may be a +picture) and select Save Link As... from the pop +up menu the basic &HTML; or similar source text will be +downloaded and saved on your local disk. + +Right clicking on a link (which may be a +picture) and choosing Copy Link Address will copy +the &URL; of the link to the clipboard so you can then paste it into, say, an +e-mail to a friend telling her about this wonderful new site. + +Right clicking on a picture and choosing +Copy Image copies the &URL; of the picture +to the clipboard. + +Printing a copy of the page you are viewing is easily done with the +Menubar File +Print... or Print +Frame option or with the Toolbar Print +button. + + + + +&FTP; + +&FTP;, or File Transfer Protocol, is one of the earliest, and still +perhaps the best, way of transferring files between computers over the +Internet. + +With &FTP; you can see files and folders on the distant computer just +as if they were on your own system, download them onto your computer using +&konqueror;'s normal Copy and +Paste or Drag n' Drop methods and, if allowed, +upload files from your machine to the other computer's filesystem. To try it, +type the &URL; + + +ftp://ftp.l10n.kde.org + + +into the Location Toolbar and press Enter. As long as +you are connected to the Internet, you should end up seeing the ftp folder of the l10n server. + +Although, strictly speaking, &FTP; &URL;s should +be entered starting with ftp:// and WWW + &URL;s starting with http:// +&konqueror; is usually smart enough to figure out what is meant, and insert +these characters for you if you leave them out. + +When you access an &FTP; site it will usually need some form of username +and password from you. To simplify things, most &FTP; sites that offer files +for free downloading will accept the word +anonymous as a username and your email +address as a password, and to make your life even easier &konqueror; will +automatically supply these without troubling you. + +If you try to access an &FTP; site that does not need a proper +username or password but which is too busy to accept any more connections, +&konqueror; often interprets the busy message as a request for +a name and password and will therefore pop up a dialog box asking you to +supply them. + +Sites that are more concerned with security will need a proper username +and password, in which case &konqueror; will ask you for them or you can +include the username in the &URL; you type into the Location Toolbar, as +for example + + +ftp://username@ftp.l10n.kde.org + + +&konqueror; will then prompt you for the password. + +&konqueror; can also support automatic logins as specified in a +.netrc file. Details of how to enable this feature are +given at +https://konqueror.org/faq/#DoesKonquerorsupportautomaticftploginsvianetrcfiles + + + + +&URL;s with Port Numbers +If you specify a port number in your &URL;, as in for example +http://intranet.corp.com:1080, you might get the error +message Access to restricted port in POST denied. This is done +for security reasons. If you nevertheless need to access a server on this port, +just add a key line + +OverridenPorts=CommaSeparatedListOfAllowedPorts + +to kio_httprc in the folder +$(qtpaths --paths GenericConfigLocation). +For example +OverridenPorts=23,15 + +(it should not include any embedded spaces). +&konqueror; will reject the following ports: + + 1, 7, 9, 11, 13, 15, 17, 19, + 20, 21, 22, 23, 25, 37, 42, 43, + 53, 77, 79, 87, 95, 101, 102, 103, 104, + 109, 110, 111, 113, 115, 117, 119, 123, + 135, 139, 143, 179, 389, 512, 513, 514, + 515, 526, 530, 531, 532, 540, 556, 587, + 601, 989, 990, 992, 993, 995, 1080, + 2049, 4045, 6000, 6667 + + + + + + + + + +&Pamela.Roberts; + + + + + + +Automatic Text Completion + +You can get &konqueror; to help you enter a path or &URL; into the +Location Toolbar by enabling one of the Text Completion +features. To do this right + click on a clear part of the Location Toolbar text entry box and select +Text Completion from the pop up menu. This will let you +choose between the following options: + + + + +None +What you get is what you type. + + + +Manual + +When you have typed part of a path or &URL;, pressing +&Ctrl;E or will complete the entry if it is +possible to do so unambiguously. + + + +Automatic +As you type into the Location Toolbar window &konqueror; will +automatically extend what you type to complete one possible path or &URL;, +highlighting the characters it has added. Continue typing if that's not what +you wanted or press Enter to accept it. + + + +Dropdown List +A drop-down window will appear as you type, showing the +possible matches to what you have typed so far. When the path or &URL; that +you want appears in the window click on it with the &LMB;. +You can also use the +Down or and Up or +&Shift; +keys to select it then press Enter. + + + +Short Automatic +This is like Automatic mode except that it only extends +what you have typed as far as the next / symbol in the path +or &URL;. Press &Ctrl;E or to accept the +suggestion, Enter when the complete path or &URL; is +shown. + + + +Dropdown List & Automatic +This is a combination of both options described above. + + + +Default +This item appears at the bottom of the submenu and enables you +to switch to the default behaviour Dropdown List. + + + +You should try out these different modes and pick the one that suits you + best. + + + + + + +&Pamela.Roberts; + + + + + +Using Bookmarks + +Although you can use &konqueror;'s bookmarks to record the locations of +your own files and folders, they are most useful when you are surfing the +Web, letting you build up a list of useful sites. + +To open the Bookmarks menu +left click on the Bookmarks menu. +Once the list is visible, you can navigate through it with the arrow keys or +with your mouse, then press Enter or left +click to visit the selected location. + +To add a new item to the list use Bookmarks +Add Bookmark or +&Ctrl;B or +right click on a clear space in the web page or +folder view and select Bookmark this Page from +the pop up menu. + +The Bookmarks list can contain subfolders containing +other bookmarks, you can create these with Bookmarks +New Bookmark Folder... +To add a bookmark into a subfolder rather than into the main Bookmark list, +select the folder from within the Bookmarks list and use +the Add Bookmark item in that folder. + +If you enter bookmarks: in the location bar the +bookmarks home page with an overview of all bookmarks and folders is shown. + +If you want to edit your bookmarks use the Bookmark Editor + + + + + + + + +&Pamela.Roberts; + + + + + +Saving Settings +You can specify different View menu settings +for an individual folder. To do this select View +Adjust View Properties..., +change the View settings in the dialog to whatever you want. Then apply +the view properties to the Current folder. Doing this +creates a .directory file in that folder to hold the +folder View settings. Use this dialog again to remove the folder specific +settings (or just delete the .directory file). +One nice use of this feature is if you have a folder full of +pictures, you can set that particular folder to display thumbnails of the +pictures (by choosing the View Mode +Icons and Preview +from the View menu) when you open it, while +not displaying images as thumbnails in other folders. + + + + + + + +&Pamela.Roberts; + + + + + + +Plugins + + + + +&konqueror; Plugins + +&kde; releases several useful plugins that interact with +&konqueror; in various ways. These are explained briefly below. + +Use SettingsConfigure +Extensions... to open a dialog with all installed plugins and select +the ones you need. All plugins are accessible in the Tools menu. + +Only plugins appropriate for the current mode (file manager or browser in KHTML/WebEngine view) +are listed in the dialog. + + +Browser Mode + + +Web Page Translation +This uses the machine translation service provided by Google Translate to translate the current +HTML page to whatever language you want (within reason). It +can be launched with ToolsTranslate +Web Page. +If you have a portion of the text on the page selected, that +will be translated instead of the entire &URL;. + + +Machine translation is not a perfect science! Google will at +best give you a rough translation, and at worst will give you a very +funny read. Don't base important decisions on things you have read +from a Google translated page, without confirming that the +translation is indeed accurate. + + + +You may only translate web pages that are accessible on the +world wide web. To translate any other text, you should go directly +to the Google site itself, where you are able to paste in text for +translation. + + + + + +HTML Settings (KHTML view) +Select ToolsHTML +Settings to enable or disable a number of HTML +settings without going through the Settings dialog. + + + +JavaScript +Allows you to turn the use of JavaScript in &konqueror; on or off. + + + +Java +Allows you to turn the use of &Java; in &konqueror; on or off. + + + +Cookies +Allows you to turn the use of Cookies in &konqueror; on or off. + + + +Plugins +Allows you to turn the use of the &konqueror; plugins you have installed on or off. + + + +Autoload Images +Allows you to turn on or off the loading of images in web pages. + + + +Enable Proxy +Allows you to enable or disable the use of a proxy in the &konqueror; browser. + + + +Enable Cache +Allows you to enable or disable the use of a cache in the &konqueror; browser. + + + +Cache Policy + +The Cache Policy submenu provides you with a way to configure how +&konqueror; uses a cache. The possible uses include: + +Keep Cache in Sync +Use Cache if Possible +Offline Browsing Mode + + + + + + + + + + +Auto Refresh (KHTML view only) +This works on any readonly part (though currently it only plugs into +khtmlpart). It lets you tell &konqueror; to refresh a page automatically +after a specific period. This is useful for things like news pages, +and should be very nice for people using Kiosk mode + + + + + + +File Manager Mode + + +Directory Filter +This is controlled by +&Ctrl;&Shift;I +ToolsShow Filter Bar and allows you to choose which types of item +are displayed in a folder. + + + +Image Gallery +In File Manager mode, you can select +ToolsCreate Image +Gallery or use &Ctrl;I +to create an HTML page with thumbnails of all the images in the current folder. +By default the HTML page is called images.html and the thumbnails +are put into a new images folder. +When you start the Image Gallery plugin a dialog opens allowing you to adjust the +way the gallery is created. + + +Page Look + +The Look dialog is for adjusting the appearance of the gallery page. + + + +Look Dialog Screenshot + + + + + +Screenshot + + + + + + + +Page title +The Page title option has a text input box for changing the title of the image gallery page. + + + +Images per row +The Images per row option has a slider and a spin box for adjusting the number of thumbnails that are in a single row in the gallery. + + + +Show image file name +The Show image file name check box allows you to choose whether +to display filenames below the gallery thumbnails. + + + +Show image file size +The Show image filesize check box allows you to choose whether +to display filesizes below the gallery thumbnails. + + + +Show image dimensions +The Show image dimensions check box allows you to choose +whether to display image dimensions in pixels below the gallery thumbnails. + + + +Font name +The Font name combo box provides you with a choice of which font to use in creating the gallery. + + + +Font size +The Font size spin box is for changing the size of the font you selected. + + + +Foreground color +The Foreground color option has a selector for choosing the foreground color of the gallery, this includes the text areas. + + + +Background color +The Background color option has a selector for choosing the background color of the gallery. + + + + + +Folders + +The Folders dialog is used for choosing where to save the gallery. +This dialog is also used to configure which folders are used. + + + +Folders Dialog Screenshot + + + + + +Screenshot + + + + + + + +Save to HTML file +The Save to file selector allows you to decide where you want +to save your image gallery html page. + + + +Recurse subfolders +The Recurse subfolders check box enables recursing of subdirectories. If the check box is enabled, a slider and spin box are enabled to select the recursion depth. + + + +Copy original files +The Copy original files check box creates an image folder storing copies of the original images used in the gallery. + + + +Use comment file +The use comment file check box enables a file selector to choose a comments file to use with your gallery. +The comment file contains the subtitles for the images. +The format of this file is: +# this is a comment, lines starting with '#' are ignored +FILENAME1: +Description + +FILENAME2: +Description + + + + + + + + + + + + +Thumbnails + +The thumbnails dialog is used for adjusting the properties of the thumbnails in the gallery. + + + +Thumbnails Dialog Screenshot + + + + + +Screenshot + + + + + + + +Image format for the thumbnails +The image format combo box allows you to choose which format is +used for the thumbnail images. + + + +Thumbnail size +The thumbnail size option provides a slider and spin box for adjusting the size of the thumbnails used in the gallery. + + + +Set different color depth +The set different color depth check box enables a combo box for changing the color depth of the thumbnails if you wish to use a different color depth to that used in the original image. + + + + + + + + + + + + + + + + + + +Search Bar +Provides a text box for easy access to search engines such as Google. +Clicking on the icon on the left side of the search box opens a menu to select +and enable different search engines and configure their Web Shortcuts. + + + + + +Shell Command Plugin +This plugin enables you to execute a shell command in the current folder +and view the output in a separate window. + + + + + + + + + + + + +View Mode Extensions + + +&konqueror; provides additional views in View +View Mode in file manager and browser mode, if +the corresponding applications and plugins are installed. +The file manager mode has the additional views Radial Map +from the application Filelight and the &konqueror; plugin +File Size View. + + + + + +Josef +Weidendorfer +

Josef.Weidendorfer@gmx.de
+ + + + + + +&fsview; - the File System View + +Introduction + +The &fsview; Plugin for &konqueror; is another view mode for +objects of mimetype inode/directory for local +files. It can be viewed as an alternative to the various iconviews and +listviews for browsing the content of your local file system. + +The unique property of &fsview; is its ability to show whole +nested folder hierarchies using a so-called tree map for graphical +visualization. Tree maps allow for displaying metrics of objects in +nested structures: each object is represented by a rectangle whose +area is proportional to its metric. The sum of the children's metrics must be +equal to or smaller than the parent object's metric. + +For &fsview;, sizes of files and folders are chosen as the +metric, where the size of a folder is defined to be the sum of the +sizes of its subitems. This way, big files even deep down in the +folder hierarchy can be spotted easily be looking for large +rectangles. So &fsview; can be looked at as a graphical and interactive +version of the &UNIX; du command. + +The integration of &fsview; as part of Konqueror allows it to +use the standard features such as context file menus, and mime type +sensitive actions. But it was chosen not to implement automatic +update by watching file system changes: if you delete a file shown +in &fsview; outside of &konqueror;, you have to update manually by +⪚ pressing F5 to see the change. The reason for this +decision is the potentially huge number of files which would have to be watched +for changes, and thus, could put an unreasonable pressure on system +resources for a small feature. + + + + +Visualization Features + +This section explains the graphical visualization of &fsview; +in detail. + + +Item Drawing Options + +In &fsview;, an item of the tree map visualization is a rectangle +representing a file or folder of your file system. For easier navigation, +rectangles have meaningful coloring and labeling options. + +The color of a rectangle, switchable via menu item +ViewColor +Mode can be either representative of +Depth, for easy detection of nesting, or +a color mapping of different file attributes such as name, owner, group, +or mime type. + +A rectangle can be labeled with the various attributes +of the corresponding file or folder. For each attribute, you can +choose whether it should be shown at all, only if space is available, +or if space should be taken from children (thus introducing +errors to pure tree map drawing constraints). Additionally, you can choose +the relative location of the label in the rectangle. + + + + +TreeMap Drawing Algorithms + +For drawing algorithms in tree maps, the rule that the area +is proportional to the metric of an item should hold true. +With the tree map in &fsview;, this goal isn't always met: we draw borders +to show the nesting of items, and this border takes space for an item +which is possibly lost for the areas of child items. Note that +less space is lost for the border if the rectangle is quadratic. + +Similarly, it is better for a good overview to let each rectangle +at least have its name as a label. It is an option to +always force space for labels, or only to draw labels when empty space +is available. In the latter case, the tool tips appearing when the +mouse is held over an item can help a lot. They show +information for the item the mouse is currently over, together with +its parent folders up to the root item of the tree map. + +How the space of an item is split into subareas for children is +left to the implementation. It is always better to try to split areas +in such a way that rectangles are as quadratic as possible, both for +labeling and less space lost by borders. The best methods in this +regard are Rows, Columns, or +Recursive Bisection. + +You can choose the minimal area of items to be drawn via the +menu item ViewStop at +Area. Instead, a hash pattern will be drawn +over the parents area to signal that this space is in fact occupied by +a child or children. + + + + + + +User Interface + +&fsview; supports multiple selection of items, similar to the +iconview and listview. This allows for actions to be done +simultaneously to a set of files. A simple mouse click always selects +a single item below the mouse pointer. Use a mouse click in +combination with pressing the &Shift; key for range selection or the +&Ctrl; key for selection toggle. Note that by selecting an item, subitems can no +longer be selected. Selecting an item will also clear the selection of all its +parent items before. + +Keyboard navigation is available in tree maps: use +Left Arrow and Right Arrow keys to +move the current item between siblings, and the Up +Arrow and Down Arrow keys to go up and down +the nesting hierarchy. Space selects the item; in +conjunction with &Shift; does range selection; and with the &Ctrl; key +held down simultaneously, toggles selection of the current item. Press +Return to run the open action on the current item. + + + + +Credits and License +Originally, &fsview; was meant as a small test application and +usage tutorial for the TreeMap widget developed within +KCachegrind. +Copyright by Josef Weidendorfer, licensed using GPL V2. + + + + + + + + + +&Pamela.Roberts; + + + + + + +Configuring &konqueror; + +In common with the rest of &kde;, &konqueror; is highly configurable, so +you can really get the look and feel that best fits your needs and +wishes. + +When &kde; is newly installed, &konqueror;'s window contains a Menubar, +Main and Location Toolbars and possibly a Bookmark Toolbar. + +For detailed information how to modify toolbars and shortcuts please +read the sections about Toolbars +and Shortcuts in the Fundamentals. + + + +Other Settings +Selecting Settings +Configure Konqueror... brings up a dialog box +which you can use to control most aspects of &konqueror;'s behavior. +It contains these sections which are selected by left + clicking on one of the icons at the left of the dialog +box: + +General: +Configure general &konqueror; behavior +Performance: +Configure settings that can improve &konqueror;'s performance +Bookmarks: +Configure the bookmarks home page +File Management: +You can configure how Konqueror behaves as a file manager here +View Modes: +Configure file manager view modes +Navigation: +Configure file manager navigation +Services: +Configure file manager services +General: +Configure general file manager settings +File Associations: +Configure file associations +Trash: +Configure trash settings +Web Browsing: +Configure the browser behavior +Proxy: +Configure the proxy servers used +Appearance: +Configure how to display web pages +AdBlocK Filters: +Configure &konqueror; AdBlocK filters +Cache: +Configure web cache settings +History: +Configure the history sidebar +Cookies: +Configure the way cookies work +Browser Identification: +Configure the way Konqueror reports itself +Java & JavaScript: +Configure the behavior of Java and JavaScript + +Pressing the Help button will give you +detailed instructions about how to use each of these sections, or you can +use the What's This? feature. + + + + + + + + +&Pamela.Roberts; + + + + + +Command Reference + +The shortcut key combinations shown in this chapter are the +default ones. They can of course be changed. + + + +Special Shortcuts +There are some useful shortcuts that are not shown in any of the menus: + + + +F6 + +Sets the focus to the text entry box in the Location Toolbar. + + + + +&Ctrl;. + +Activate the next tab page. + + + + +&Ctrl;, + +Activate the previous tab page. + + + + + + + + + +The Menubar Note that some menu entries only appear when +they are applicable to the file you currently have open in &konqueror;. For +example, the +EditFind... + +item will not appear when you are viewing the contents of a directory. + +&konqueror; has different menu items in file manager and browser mode. Only +the items for these two modes are described in this chapter. + + +If &konqueror; is using embedded components (&kde; Parts) +such as &gwenview; for image viewing, &okular; for +PDF and &PostScript; documents &etc; the menu items from these +applications are merged into &konqueror;'s menu. Help for these additional menu items +you find in the handbook of the embedded application. + + +The File Menu + + + + + +&Ctrl;N + +File +New Window + +Open another &konqueror; +window. + + + + + +&Ctrl;T + +File New Tab + +Open another &konqueror; tab, containing a +blank page. + + + + + +&Alt;O + +File +Open Location... + +Sets the focus to the text entry box in the Location Toolbar. + + + + + +&Ctrl;O + +File +Open File... + +Open a file using the &kde; file dialog. + + + + +File +Sessions + +Open a submenu to save the current session (open tabs and windows) +for easy retrieval, manage sessions and switch to previously saved sessions. + + + + +File +Send Link Address... + +Send an email containing a link to the current +location. + + + + +File +Send File... + +Send an email containing the selected file as an +attachment. + + + + + +File +Save Background Image As... (Browser mode - KHTML view) + +Only applies if you are viewing a web page with a background image. Opens +the Save As dialog box to let you save the background +image file to your own computer. + + + + + +File +Save As... (Browser mode) +Only applies if you are viewing a document or web page, uses +the Save As... dialog box to let you save a copy to your own +computer. + + + + +File +Save Frame As... (Browser mode) +Similar to Save As... but for +use with a web site that uses frames. + + + + + +&Ctrl;P + +File +Print... + +Print. + + + + +File +Print Frame (Browser mode) +Print selected frame of a Web +page. + + + + +File +Open With + +Displays a list of applications installed on the system associated +with the mimetype of the current URL. + + + + + +&Ctrl;Q + +File +Quit + +Close down this instance of +&konqueror;. + + + + + + + +The Edit Menu + +Some items in the Menubar Edit menu can also be +found by &RMB; clicking on a free area of a view. + + + + + + +&Ctrl;Z + +Edit +Undo: Action + +Sometimes lets you reverse a mistaken +action. + + + + + +&Ctrl;X + +Edit +Cut + +Puts selected item(s) into the clipboard. If +you then paste the items they will be moved +from the original location to the new one. + + + + + +&Ctrl;C + +Edit +Copy + +Copy selected item(s) to the +clipboard. + + + + + +&Ctrl;V + +Edit +Paste (Browser mode) +Paste the clipboard content into the Location Bar, if the Location Bar has the focus. + + + + + +&Ctrl;V + +Edit +Paste Clipboard Contents... or +EditPaste one File or +EditPaste one Folder or +EditPaste x Items (File Manager mode) +Paste the currently copied/cut item(s) to the current folder. If the +clipboard does not contain files or folders, the clipboard contents (such as text +or image data) will be pasted into a new file. + + + + + +&Ctrl;A +Edit +Select All (Browser mode) +Selects all text in an &HTML; +page or in a text page being previewed, you can then +Copy it and Paste it into +a text editor. + + + +Edit +Create New (File Manager mode) +Creates a new object (such as a folder or a text file) in +the current folder. See the Create +New... section for more details. + + + + +F2 +Edit +Rename (File Manager mode) +Lets you rename a file or folder without +having to open the Properties... dialog box. + + + + + +Del +Edit +Move to Trash (File Manager mode) +Move selected item(s) to the Trash +folder. + + + + + +&Shift;Del + +Edit +Delete (File Manager mode) +Delete the selected item(s). + + + + +Edit +Edit File Type... (File Manager mode) +Open the Edit File Type +dialog box + + + + + +&Alt;Return + +Edit +Properties... (File Manager mode) +Shows the properties dialog for the currently selected item(s). + + + + + +&Ctrl;S + +Edit +Selection +Select Items Matching... (File Manager mode) +Together with the Unselect Items Matching..., +Unselect All and Invert Selection +commands, this provides an easy and powerful way of selecting +multiple files. +It brings up a simple dialog box where you can enter a file +name using the wild card characters * and ?, for example entering +*.html will select all files ending with +.html while ?a* will +select all files which have the letter a as the second character in their +filename. + + + + +Edit +Selection +Unselect Items Matching... (File Manager mode) +Unselect files or folders via a dialog similar to the one used +by Select.... + + + + + +&Ctrl;A +Edit +Selection +Select All (File Manager mode) +Selects all items in a folder; you can then +Copy or Cut them and +Paste them into a different folder. + + + + +Edit +Selection +Unselect All (File Manager mode) +Unselect all selected files or +folders. + + + + + +&Ctrl;&Shift;A +Edit +Selection +Invert Selection (File Manager mode) +Invert current selection. + + + + + +&Ctrl;F + +Edit +Find... (Browser mode) +Displays the search bar at the bottom of the current window. +Start typing to find a text string in a text page you are previewing or in an &HTML; +page. + + + + +F3 +Edit +Find Next (Browser mode - KHTML view) +Find the next occurrence of the text string +in the text or &HTML; page. + + + + +&Shift;F3 +Edit +Find Previous (Browser mode - KHTML view) +Find the previous occurrence of the text string +in the text or &HTML; page. + + + + + + + + +The View Menu + + + + +View +View Mode + +In browser mode this submenu holds items to select embedded +views like KHTML, WebEngine, Embedded Advanced +Text Editor and more embedded views. +In file manager mode this submenu holds items to select Icon, +Details, Compact, +Terminal Emulator and more view modes. + + + + +View +Lock to Current Location + +A locked view cannot change folders. Use in combination +with Link View to explore many files from +one folder. + + + + +View +Link View + +Link current view to others in a multiple view +window. A linked view follows folder changes made in other linked views. +This is especially useful with different types of views, such as a folder tree +with an icon view or detailed view, and possibly a terminal emulator window. + + + + +F5 +View +Reload + +Reload. + + + + +&Esc; +View +Stop + +Stop load (particularly useful when web +browsing). + + + + +&Ctrl;+ +View +Enlarge Font / + +&Ctrl;- +View +Shrink Font (Browser mode - KHTML view) +Use these to adjust the size of the text in the +page if you find it difficult to read. How well this works will +depend on how the web page has been constructed. + + + + +&Ctrl;U + + +View +View Document Source (Browser mode - KHTML view) +View document source text. +Only available if you are viewing a document or &HTML; +page. + + + + + +View +View Frame Source (Browser mode) +View frame source text +Only applies if you are viewing a web site that uses frames. Similar to +View Document Source. + + + + + +View +Zoom In Zoom Out +Actual Size Zoom Text Only +Zoom To DPI (Browser mode - WebEngine view) +These menuitems offer different actions to modify the size of the items +in the page. + + + + + +&Ctrl;I + + +View +View Document Information (Browser mode - KHTML view) +View document information, such as title, &URL;, and &HTTP; +headers used in retrieving the document. +Only available if you are viewing an &HTML; +page. + + + + + +View +Set Encoding (Browser mode) +Allows you to choose the character encoding used to display +&HTML; pages. Default is usually the best +choice. + + + + + +View +Sort By (File Manager mode) +Changes whether items are sorted by Name +or other criteria described in Information in the View. +Descending reverses the sort order. +Folders First sorts folders before files. + + + + + +View +Additional Information (File Manager mode) +Displays additional information +described in Information in the View. + + + + + +View +Preview (File Manager mode) +Displays a symbolic preview of the file contents in the different +view modes. + + + + +View +Show in Groups (File Manager mode) +Displays the content of the +current folder grouped by the option selected in Sort By +(only available in the Icons view mode). + + + + + +&Alt;. + +View +Show Hidden Files (File Manager mode) +Shows all the hidden files and sub-folders within the current +folder. + + + + +View +Adjust View Properties... (File Manager mode) +Opens the View Properties +Dialog. + + + + + + +The Go Menu + + + + + + +&Alt;Up +Go +Up + +Go up a level in the folder +hierarchy or select a folder in the hierarchy from the submenu. + + + + + +&Alt;Left +Go +Back + +Go back to the previous +view or select a previously visited item from the submenu. + + + + + +&Alt;Right +Go +Forward + +You can only go forward if you've previously gone +back. + + + + + +&Alt;Home +Go +Home Page (Browser mode) +Go to your home page as defined on the General +page of the settings dialog. + + + + + +&Alt;Home +Go +Home Folder (File Manager mode) +Changes to the users home folder, ⪚, +/home/Peter/. + + + + +Go +Applications (File Manager mode) +Open the folder holding your +applications. + + + + +Go +Network Folders (File Manager mode) +Network folders show up in a special location of &konqueror; and +&dolphin; called a virtual folder. You can find more information on how to use this folder +in the KNetAttach Handbook. + + + + +Go +Settings (File Manager mode) +Open a virtual folder with all &systemsettings; modules in +Icons, Details or +Columns view. Select an item to display the +settings module in a separate dialog window. + + + + +Go +Trash (File Manager mode) +Open your Trash +folder. + + + + +Go +Autostart (File Manager mode) +Open your Autostart +folder. + + + + + +&Ctrl;&Shift;H +Go +Show History + +Shows a tree view of your browsing history in a separate window. + + + + + +Go +Most Often Visited + + +Displays a submenu showing the &URL;s you visit most often. Selecting one +of these will make &konqueror; open that &URL;. + + + + + +Go +Recently Visited + + +Displays a submenu showing the &URL;s you recently visited. Selecting one +of these will make &konqueror; open that &URL;. + + + + + +Go +Closed Items + + +Displays a submenu showing the closed &URL;s you visit. Selecting one +of these will make &konqueror; open that &URL;. Use Empty Closed Items +History to clear the submenu. + + + + + + + + +The Bookmarks Menu + +See the section Using Bookmarks +in this manual for a fuller description of these menu items. + + + + + + +&Ctrl;B + +Bookmarks +Add Bookmark + +Add current selection to your +bookmarks. + + + + +Bookmarks +Bookmark Tabs as Folder... + + +Create a bookmark folder containing links to all of the &URL;s currently +open in &konqueror; tabs. + + + + + +Bookmarks +New Bookmark Folder... + +Create a new folder in your Bookmarks +folder. + + + + +Bookmarks +Edit Bookmarks... + +Open the Bookmark Editor. + + + + + + + +The Tools Menu + + + + + +F4 +Tools +Open Terminal (File Manager mode) +Open a &konsole; terminal + window. + + + + + +&Ctrl;F +Tools +Find File... (File Manager mode) +Open the &kfind; application. + + + + +Tools +Select Remote Charset (File Manager mode) +Offers to choose the charset used by a remote +connection manually. + + + + +If you have &konqueror; plugins installed there will be additional +entries in the Tools menu. See the &konqueror; Plugins chapter for further +details. + + + +The Settings Menu + +Apart from the common &kde; Settings menu items described in the +Settings Menu +chapter of the &kde; Fundamentals &konqueror; has these application specific menu entries: + + + + + +Settings +Show Terminal Emulator + +Open a small text terminal view at the bottom of the +main window. + + + + + +&Ctrl;&Shift; +F + +Settings +Full Screen Mode + + +Changes &konqueror; to full screen mode, in which the &konqueror; window +takes up the whole screen, and does not have the usual window decorations. To +exit full screen mode, click on the Exit Full Screen Mode +icon on the toolbar, or press &Ctrl;&Shift; +F. + + + + + +Settings +Configure Extensions... + +Opens a dialog with all installed plugins (⪚ from the KDE module extragear) +and allows you to select the ones you need. All plugins are accessible in the +Tools menu. + + + + Settings +Configure Spell Checking... + +Displays the spell checking configuration dialog box, in which you can +change settings associated with spell checking in &konqueror;. + + + + + + + + +The Window Menu + + + + + + +&Ctrl;&Shift;L +Window +Split View Left/Right + +Split View Left/Right. + + + + + +&Ctrl;&Shift;T +Window +Split View Top/Bottom + +Split View Top/Bottom. + + + + + +&Ctrl;&Shift;W +Window +Close Active View + +Remove Active View. + + + + + +&Ctrl;N +Window +New Window + +Open another &konqueror; window. + + + + + +&Ctrl;&Shift;D +Window +Duplicate Window + +Open another &konqueror; window, duplicating the +current one. + + + + + +&Ctrl;T +Window +New Tab + +Open a new, empty, tab page. + + + + + +&Ctrl;D +Window +Duplicate Current Tab + +Open a duplicate tab page. + + + + + +&Ctrl;&Shift;B +Window +Detach Current Tab + +Show the current tab page in a new instance of +&konqueror;. + + + + + +&Ctrl;W +Window +Close Current Tab + +Close the current tab page. + + + + + +&Ctrl;&Shift;Left +Window +Move Tab Left + +Move the current tab one place left in the list of tabs. + + + + + +&Ctrl;&Shift;Right +Window +Move Tab Right + +Move the current tab one place right in the list of tabs. + + + + + + + +The Help Menu +Apart from standard &kde; Help menu items +described in the section Help Menu +of the &kde; Fundamentals you will have the menu entry &konqueror; Introduction +to revisit the introductory pages that you got when +&konqueror; was first started. + + + + + + + + + +&Pamela.Roberts; + + + + + +Questions and Answers + + + + +Can I run &konqueror; from another window +manager? + +Just install &Qt;, &kf5; and &konqueror;, and from your favorite +window manager, launch &konqueror;. It should work just fine, but if it +doesn't (&kde; developers don't test that case often), report it to http://bugs.kde.org and try running +kdeinit before running &konqueror;; it usually +helps. + + + +Where does &konqueror; keep all its configuration +data? +Generally in the qtpaths --paths GenericDataLocation folder (this may +be ~/.local/share on your system, depending on how &konqueror; +was installed). Don't alter these files unless you really know what you are +doing. + + + +Your bookmarks are held in konqueror/bookmarks.xml +Cookies are held in kcookiejar/cookies + +Your history, as used for the auto-completion feature, is in +konq_history in the folder +qtpaths --paths GenericConfigLocation. + +In the folder qtpaths --paths GenericConfigLocation the file +konquerorrc holds a whole lot of general configuration +settings. + +The folder kio_http/ in +qtpaths --paths GenericCacheLocation +contains the browser cache. + + +Any folder specific view settings are put into .directory files in the individual +folders. + + + +How do I clear out the history file? +There are two histories: + +One is used for text completion in the Location Toolbar text entry +box. To clear this right click on the text entry +box and select Clear History +. + +The other is the log of visited locations. Select Show History +in the menu Go and right click on an entry and choose +Remove Entry (∇) to remove just that entry or +Clear History to delete all +entries. + +You can also use the application &sweeper; from +the kdeutils module which allows you to clean up cookies, favicons, web history and cache, +form completion entries and cache policies of visited websites. + + + + +How do I enable, disable or clear the browser +cache? +If you select Web BrowsingCache + in the dialog launched by selecting +SettingsConfigure Konqueror... +, you will be presented with a dialog box that lets +you disable the cache, clear it or set its size, and change the caching +policy. + + + + +How can I change the timeout values used by &konqueror; +when web browsing? +In the &systemsettings; category Network +on the Settings +Connection Preferences page. + + + + +How do I set my home page - the page loaded +on startup? +&konqueror; has a Home Folder used in file manager mode +and a Home Page used in browser mode. + +To change these settings launch +SettingsConfigure +KonquerorGeneral. + +To set the &konqueror; startup page in filemanager mode select +Show Introduction Page, Show My Home +Page, Show Blank Page or Show +My Bookmarks from the drop down box labeled When +Konqueror starts. + +In browser mode &konqueror; starts with the Home +page entry. + + + + + +I can't find the answer to my question here. + +Take a look at +https://konqueror.org/faq/ or + +https://konqueror.org/contact/. +You may find further information in the +KDE Community Forums or on +Konqueror's KDE Userbase page. + + + + + + + + + + + +&Pamela.Roberts; + + + + + + +Credits and License + +&konqueror;. Program copyright 1999-2003, the &konqueror; + developers: + + + + +&David.Faure; &David.Faure.mail; +developer (parts, JavaScript, I/O lib) and maintainer + + + +&Simon.Hausmann; &Simon.Hausmann.mail; +developer (framework, parts) + + + +&Michael.Reiher; &Michael.Reiher.mail; +developer (framework) + + + +&Mattias.Welk; &Mattias.Welk.mail; +developer + + + +&Alexander.Neundorf; &Alexander.Neundorf.mail; +developer (list views) + + + +&Michael.Brade; &Michael.Brade.mail; +developer (list views, I/O lib) + + + +&Lars.Knoll; &Lars.Knoll.mail; +developer (HTML rendering +engine) + + + +&Antti.Koivisto; &Antti.Koivisto.mail; +developer (HTML rendering +engine) + + + +&Dirk.Mueller; &Dirk.Mueller.mail; +developer (HTML rendering +engine) + + + +&Peter.Kelly; &Peter.Kelly.mail; +developer (HTML rendering engine, +JavaScript) + + + +&Waldo.Bastian; &Waldo.Bastian.mail; +developer (HTML rendering engine, I/O +lib) + + + +&Matt.Koss; &Matt.Koss.mail; +developer (I/O lib) + + + +&Alex.Zepeda; &Alex.Zepeda.mail; +developer (I/O lib) + + + +&Stephan.Kulow; &Stephan.Kulow.mail; +developer (HTML rendering engine, I/O lib, regression test framework) + + + +&Richard.J.Moore; &Richard.J.Moore.mail; +developer (&Java; applet support) + + + +Dima Rogozin dima@mercury.co.il +developer (&Java; applet support) + + + +Wynn Wilkes wynnw@calderasystems.com +developer (&Java;2 manager support and other major improvements +to applet support) + + + +&Harri.Porten; &Harri.Porten.mail; +developer (JavaScript) + + + +Stefan Schimanski schimmi@kde.org +developer (&Netscape; plugin support) + + + +&Carsten.Pfeiffer; &Carsten.Pfeiffer.mail; +developer (framework) + + + +&George.Staikos; &George.Staikos.mail; +developer (SSL support, Netscape plugins) + + + +Dawit Alemayehu adawit@kde.org +developer (I/O lib, Authentication support) + + + +&Torsten.Rahn; &Torsten.Rahn.mail; +Graphics / icons + + + +Torben Weis weis@kde.org +kfm author + + + +&Joseph.Wenninger; &Joseph.Wenninger.mail; +developer (navigation panel framework) + + + +&Stephan.Binner; &Stephan.Binner.mail; +developer (misc stuff) + + + +Leo Savernik l.savernik@aon.at +JavaScript access controls, per-domain policies extensions, HTML rendering engine + + + +Germain Garand germain@ebooksfrance.org +Developer (HTML rendering engine) + + + +Zack Rusin zack@kde.org +Developer (HTML rendering engine) + + + +Tobias Anton anton@stud.fbi.fh-darmstadt.de +Developer (HTML rendering engine) + + + +Lubos Lunak l.lunak@kde.org +Developer (HTML rendering engine) + + + +Maks Orlovich maksim@kde.org +Developer (HTML rendering engine, JavaScript) + + + +Allan Sandfeld Jensen kde@carewolf.com +Developer (HTML rendering engine) + + + +Apple Safari Developers +Developer (HTML rendering engine, JavaScript) + + + +Koos Vriezen koos.vriezen@xs4all.nl +Developer (Java applets and other embedded objects) + + + +Ivor Hewitt ivor@ivor.org +Developer (AdBlock filter) + + + +Eduardo Robles Elvira edulix@gmail.com +Developer (framework) + + + + +Documentation copyright 2000-2003 + + +&Erwan.Loisant; &Erwan.Loisant.mail; +&Pamela.Roberts; &Pamela.Roberts.mail; + + +Documentation updated for &kde; 3.2 by &Philip.Rodrigues; &Philip.Rodrigues.mail;. + +Documentation proofreading for &kde; 4.11 by David Palser davidpalser179@btinternet.com. + + + +&underFDL; +&underGPL; + + + +&documentation.index; + + + diff --git a/doc/konqueror/konqorg.png b/doc/konqueror/konqorg.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6cb5c68cb95fe2a3dd1c459a591cee60521c61 GIT binary patch literal 89127 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 z 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 Kx{lL*fc!sF75@bQ literal 0 HcmV?d00001 diff --git a/doc/konqueror/look.png b/doc/konqueror/look.png new file mode 100644 index 0000000000000000000000000000000000000000..62bf6726d17ba773b61025b7d9e47cf0e7d4a84a GIT binary patch literal 26246 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 JkOPeZ|34ZvZj=B3 literal 0 HcmV?d00001 diff --git a/doc/konqueror/reset.png b/doc/konqueror/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..02a20bd0f8674ce83030795683cf99c111be4036 GIT binary patch literal 627 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 Ma%!@5((l6lFBxI);s5{u literal 0 HcmV?d00001 diff --git a/doc/konqueror/viewproperties-dialog.png b/doc/konqueror/viewproperties-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..6c3a762ae176dd8fe332940935a34007b047c5cf GIT binary patch literal 23793 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 Oj-#fep;)0{5%gb$bsnq$ literal 0 HcmV?d00001 diff --git a/kfmclient.desktop b/kfmclient.desktop new file mode 100755 index 0000000..821c249 --- /dev/null +++ b/kfmclient.desktop @@ -0,0 +1,104 @@ +[Desktop Entry] +# This desktop file is the one used by KApplication::invokeBrowser +Type=Application +Exec=kfmclient openURL %u +Icon=konqueror +Terminal=false +InitialPreference=9 +NoDisplay=true +X-KDE-StartupNotify=false +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +X-DBUS-StartupType=None +Categories=Qt;KDE;System; +X-KDE-HasTempFileOption=true diff --git a/kfmclient_dir.desktop b/kfmclient_dir.desktop new file mode 100755 index 0000000..551edc0 --- /dev/null +++ b/kfmclient_dir.desktop @@ -0,0 +1,103 @@ +[Desktop Entry] +# This desktop file is the one used by kcmshell5 componentchooser +Type=Application +Exec=kfmclient openURL %u inode/directory +Icon=konqueror +Terminal=false +MimeType=inode/directory; +# Must be less than Dolphin (=10) but more than Gwenview (=8) +InitialPreference=9 +NoDisplay=true +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +Categories=Qt;KDE;System; diff --git a/kfmclient_html.desktop b/kfmclient_html.desktop new file mode 100755 index 0000000..c8ddfd3 --- /dev/null +++ b/kfmclient_html.desktop @@ -0,0 +1,102 @@ +[Desktop Entry] +Type=Application +Exec=kfmclient openURL %u text/html +Icon=konqueror +Terminal=false +MimeType=text/html;application/xhtml+xml;application/xml;x-scheme-handler/http;x-scheme-handler/https; +InitialPreference=9 +NoDisplay=true +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +Categories=Qt;KDE;Network;WebBrowser; +X-KDE-HasTempFileOption=true diff --git a/kfmclient_war.desktop b/kfmclient_war.desktop new file mode 100755 index 0000000..2aca255 --- /dev/null +++ b/kfmclient_war.desktop @@ -0,0 +1,102 @@ +[Desktop Entry] +Type=Application +Exec=kfmclient openURL %u application/x-webarchive +Icon=konqueror +Terminal=false +MimeType=application/x-webarchive; +InitialPreference=9 +NoDisplay=true +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +Categories=Qt;KDE;System; +X-KDE-HasTempFileOption=true diff --git a/konqbrowser.desktop b/konqbrowser.desktop new file mode 100755 index 0000000..672654d --- /dev/null +++ b/konqbrowser.desktop @@ -0,0 +1,191 @@ +[Desktop Entry] +Type=Application +Exec=konqueror +Icon=konqueror +X-DocPath=konqueror/index.html + +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +GenericName=Web Browser +GenericName[af]=Webblaaier +GenericName[ar]=متصفح الوِب +GenericName[as]=ৱেব চৰক +GenericName[ast]=Restolador web +GenericName[be]=Вандроўнік па Сеціве +GenericName[be@latin]=Hartač sieciva +GenericName[bg]=Уеб браузър +GenericName[bn]=ওয়েব ব্রাউজার +GenericName[bn_IN]=ওয়েব ব্রাউজার +GenericName[br]=Furcher ar Gwiad +GenericName[bs]=Veb pregledač +GenericName[ca]=Navegador web +GenericName[ca@valencia]=Navegador web +GenericName[cs]=Webový prohlížeč +GenericName[csb]=Przezérnik WWW +GenericName[cy]=Porydd Gwe +GenericName[da]=Browser +GenericName[de]=Webbrowser +GenericName[el]=Περιηγητής ιστού +GenericName[en_GB]=Web Browser +GenericName[eo]=TTT-foliumilo +GenericName[es]=Navegador web +GenericName[et]=Veebibrauser +GenericName[eu]=Web arakatzailea +GenericName[fa]=مرورگر وب‌ +GenericName[fi]=Verkkoselain +GenericName[fr]=Navigateur Web +GenericName[fy]=Webblêder +GenericName[ga]=Brabhsálaí Gréasáin +GenericName[gl]=Navegador web +GenericName[gu]=વેબ બ્રાઉઝર +GenericName[he]=דפדפן אינטרנט +GenericName[hi]=वेब ब्राउज़र +GenericName[hne]=वेब ब्राउजर +GenericName[hr]=Web preglednik +GenericName[hsb]=Web Browser +GenericName[hu]=Webböngésző +GenericName[ia]=Navigator Web +GenericName[id]=Penelusur Web +GenericName[is]=Vafri +GenericName[it]=Browser Web +GenericName[ja]=ウェブブラウザ +GenericName[ka]=ვებ–ბრაუზერი +GenericName[kk]=Веб браузер +GenericName[km]=កម្មវិធី​រុករក​បណ្ដាញ +GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ +GenericName[ko]=웹 브라우저 +GenericName[ku]=Geroka Torê +GenericName[lt]=Žiniatinklio naršyklė +GenericName[lv]=Tīmekļa pārlūks +GenericName[mai]=वेब ब्राउजर +GenericName[mk]=Прелистувач на Интернет +GenericName[ml]=വെബ് ബ്രൌസര്‍ +GenericName[mr]=वेब ब्राऊजर +GenericName[ms]=Pelayar Web +GenericName[nb]=Nettleser +GenericName[nds]=Nettkieker +GenericName[ne]=वेब ब्राउजर +GenericName[nl]=Webbrowser +GenericName[nn]=Nettlesar +GenericName[oc]=Navigador web +GenericName[or]=ୱେବ ବ୍ରାଉଜର +GenericName[pa]=ਵੈੱਬ ਬਰਾਊਜ਼ਰ +GenericName[pl]=Przeglądarka sieciowa +GenericName[pt]=Navegador Web +GenericName[pt_BR]=Navegador Web +GenericName[ro]=Navigator de Internet +GenericName[ru]=Веб-браузер +GenericName[si]=ජාල ගවේශකය +GenericName[sk]=Webový prehliadač +GenericName[sl]=Spletni brskalnik +GenericName[sr]=Веб прегледач +GenericName[sr@ijekavian]=Веб прегледач +GenericName[sr@ijekavianlatin]=Veb pregledač +GenericName[sr@latin]=Veb pregledač +GenericName[sv]=Webbläsare +GenericName[ta]=இணைய உலாவி +GenericName[te]=వెబ్ బ్రౌజర్ +GenericName[tg]=Намоишгари сомона +GenericName[th]=เว็บเบราว์เซอร์ +GenericName[tr]=Web Tarayıcı +GenericName[ug]=توركۆرگۈ +GenericName[uk]=Переглядач інтернету +GenericName[uz]=Veb-brauzer +GenericName[uz@cyrillic]=Веб-браузер +GenericName[vi]=Trình duyệt mạng +GenericName[wa]=Betchteu waibe +GenericName[xh]=Umkhangeli zincwadi we Web +GenericName[x-test]=xxWeb Browserxx +GenericName[zh_CN]=网页浏览器 +GenericName[zh_TW]=網頁瀏覽器 +Categories=Qt;KDE;Network;WebBrowser; diff --git a/konqueror-version.h.cmake b/konqueror-version.h.cmake new file mode 100644 index 0000000..dbb06a0 --- /dev/null +++ b/konqueror-version.h.cmake @@ -0,0 +1,7 @@ +#ifndef KONQUEROR_VERSION_H +#define KONQUEROR_VERSION_H + + +#define KONQUEROR_VERSION "@KONQUEROR_VERSION@" + +#endif diff --git a/konqueror.categories b/konqueror.categories new file mode 100644 index 0000000..6792129 --- /dev/null +++ b/konqueror.categories @@ -0,0 +1,2 @@ +org.kde.webenginepart webenginepart IDENTIFIER [WEBENGINEPART_LOG] +org.kde.konqueror konqueror IDENTIFIER [KONQUEROR_LOG] diff --git a/konqy_preload.desktop b/konqy_preload.desktop new file mode 100644 index 0000000..f6fb74d --- /dev/null +++ b/konqy_preload.desktop @@ -0,0 +1,45 @@ +[Desktop Entry] +Exec=konqueror --preload +Type=Application +Name=Konqueror preloading during desktop environment startup +Name[ast]=Precarga de Konqueror nel aniciu del entornu d'escritoriu +Name[ca]=Precàrrega del Konqueror durant l'engegada de l'entorn d'escriptori +Name[ca@valencia]=Precàrrega del Konqueror durant l'engegada de l'entorn d'escriptori +Name[cs]=Načtení Konqueroru dopředu během spuštění pracovního prostředí +Name[da]=Forhåndsindlæsning af Konqueror ved opstart af skrivebordsmiljø +Name[de]=Konqueror beim Start der Arbeitsfläche im Hintergrund laden +Name[el]=Προφόρτωση του Konqueror κατά την εκκίνηση της επιφάνειας εργασίας +Name[en_GB]=Konqueror preloading during desktop environment startup +Name[es]=Precarga de Konqueror durante el arranque del entorno de escritorio +Name[et]=Konquerori eellaadimine töökeskkonna käivitamisel +Name[eu]=Konqueror aurrezama mahaigaineko ingurua abioatzean +Name[fi]=Konquerorin esilataus työpöytäympäristöä käynnistettäessä +Name[fr]=Préchargement de Konqueror lors du démarrage de l'environnement de bureau +Name[gl]=Precarga de Konqueror durante o inicio do contorno de escritorio +Name[ia]=Precargamento de Konqueror durante le startar de ambiente de scriptorio +Name[id]=Prapemuatan Konqueror sewaktu pemulaian lingkungan desktop +Name[is]=Forhleðsla á Konqueror þegar skjáborðsumhverfi ræsir +Name[it]=Precaricare Konqueror all'avvio dell'ambiente desktop +Name[ko]=데스크톱 환경 시작 중 Konqueror 미리 불러오기 +Name[nl]=Konqueror vooraf laden tijdens opstarten van bureaubladomgeving +Name[nn]=Førehandslast Konqueror ved start av skrivebordet +Name[pl]=Wstępne wczytanie Konquerora przy uruchamianiu środowiska pulpitu +Name[pt]=Pré-carregamento do Konqueror no arranque do ambiente de trabalho +Name[pt_BR]=Pré-carregamento do Konqueror na inicialização do KDE +Name[ru]=Предварительная загрузка Konqueror при запуске рабочей среды +Name[sk]=Prednahratie Konquerora počas štartu desktopového prostredia +Name[sl]=Prednalaganje Konquerorja med zaganjanjem namiznega okolja +Name[sr]=Предучитавање К‑освајача при покретању површи +Name[sr@ijekavian]=Предучитавање К‑освајача при покретању површи +Name[sr@ijekavianlatin]=Predučitavanje K‑osvajača pri pokretanju površi +Name[sr@latin]=Predučitavanje K‑osvajača pri pokretanju površi +Name[sv]=Förladdning av Konqueror vid start av skrivbordsmiljön +Name[tr]=Masaüstü ortamı açılışında Konqueror önyüklemesi +Name[uk]=Попереднє завантаження Konqueror при старті стільничного середовища +Name[x-test]=xxKonqueror preloading during desktop environment startupxx +Name[zh_CN]=在桌面环境启动时预先加载 Konqueror +Name[zh_TW]=啟動桌面環境時預先載入 Konqueror +X-KDE-autostart-condition=konquerorrc:Reusing:PreloadOnStartup:false +X-KDE-StartupNotify=false +X-KDE-autostart-phase=2 +OnlyShowIn=KDE; diff --git a/libkonq/AUTHORS b/libkonq/AUTHORS new file mode 100644 index 0000000..e33d1ed --- /dev/null +++ b/libkonq/AUTHORS @@ -0,0 +1,7 @@ +The classes in this library were written by: +Torben Weis +David Faure +Simon Hausmann +Holger Freyther +and are all available under the LGPL license. +See the individual files for more. diff --git a/libkonq/CMakeLists.txt b/libkonq/CMakeLists.txt new file mode 100644 index 0000000..76fcdf6 --- /dev/null +++ b/libkonq/CMakeLists.txt @@ -0,0 +1,55 @@ +project(LibKonq) +add_definitions(-DTRANSLATION_DOMAIN="libkonq") + +set(LIBKONQ_VERSION "5.97.0") + +ecm_setup_version(${LIBKONQ_VERSION} VARIABLE_PREFIX KONQ + VERSION_HEADER "${LibKonq_BINARY_DIR}/konq_version.h" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5KonqConfigVersion.cmake" + SOVERSION 6 +) + +# Build dependencies +find_package(Qt5 CONFIG REQUIRED COMPONENTS Core DBus Widgets) +find_package(KF5 REQUIRED COMPONENTS Bookmarks Parts) + +find_package(ZLIB) +set_package_properties(ZLIB PROPERTIES DESCRIPTION "Support for gzip compressed files and data streams" + URL "https://www.zlib.net" + TYPE REQUIRED + PURPOSE "Required for building LibKonq" + ) + +# Targets +add_subdirectory(src) +if(BUILD_TESTING) + add_subdirectory(autotests) +endif() + +# CMake files +set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Konq") + +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/KF5KonqConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/KF5KonqConfig.cmake" + INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} +) + +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/KF5KonqConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5KonqConfigVersion.cmake" + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + COMPONENT Devel +) + +install(EXPORT KF5KonqTargets + DESTINATION "${CMAKECONFIG_INSTALL_DIR}" + FILE KF5KonqTargets.cmake + NAMESPACE KF5:: +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/konq_version.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} + COMPONENT Devel +) diff --git a/libkonq/COPYING b/libkonq/COPYING new file mode 100644 index 0000000..5185fd3 --- /dev/null +++ b/libkonq/COPYING @@ -0,0 +1,346 @@ +NOTE! The GPL below is copyrighted by the Free Software Foundation, but +the instance of code that it refers to (the kde programs) are copyrighted +by the authors who actually wrote it. + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libkonq/COPYING.LIB b/libkonq/COPYING.LIB new file mode 100644 index 0000000..2d2d780 --- /dev/null +++ b/libkonq/COPYING.LIB @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/libkonq/DESIGN b/libkonq/DESIGN new file mode 100644 index 0000000..ed7ac9b --- /dev/null +++ b/libkonq/DESIGN @@ -0,0 +1,44 @@ +libkonq is the construction kit for a file manager +(together with libkio, which is at a lower level) + +It is used by konqueror, of course, but also by kdesktop, which is +another file manager in fact, and by apps that want to use +the properties dialog boxes (like kpanel and kfind) or the bookmark +classes. + +libkonq contents : +================== + +1) menus +kbookmark.* : general purpose bookmark class +kbookmarkmenu.* : bookmark menu +kbookmarkbar.* : bookmark bar +konq_popupmenu.*: popupmenu for URLs +konq_xmlguiclient.* : general purpose xmlgui manipulating class +knewmenu.* : implements the 'new' menu (file templates) + +2) files +konq_operations.*: common operations to all views, like deleting files, and + dropping files. +konq_fileundomanager.* : undo feature for file operations + +3) icons +kfileivi.* : icon representing a file (inherits QListViewItem and + uses KFileItem for holding file information) +konq_iconviewwidget.* : the specialisation of QIconView that knows about files. + Basic widget for icon views in konqueror and kdesktop. +konq_drag.* : the drag object for konqiconviewwidget (adds text/uri-list + support to QIconView's drag object). + +4) configuration +konq_propsview.* : view properties (global and per-directory) +konq_settings.* : settings + +5) directory views +konq_bgnddlg.* : background chosing dialog + +6) other +konq_events.* : events sent by konqueror, for use by the views [& metaviews] + +7) plugin interface +konq_popupmenu.h : class KonqPopupMenuPlugin diff --git a/libkonq/KF5KonqConfig.cmake.in b/libkonq/KF5KonqConfig.cmake.in new file mode 100644 index 0000000..c93dde2 --- /dev/null +++ b/libkonq/KF5KonqConfig.cmake.in @@ -0,0 +1,11 @@ +@PACKAGE_INIT@ + +​include(CMakeFindDependencyMacro) +find_dependency(KF5XmlGui) +find_dependency(KF5Config) +find_dependency(KF5KIO) +find_dependency(KF5CoreAddons) +find_dependency(KF5Service) +find_dependency(KF5Parts) + +include("${CMAKE_CURRENT_LIST_DIR}/KF5KonqTargets.cmake") diff --git a/libkonq/Mainpage.dox b/libkonq/Mainpage.dox new file mode 100644 index 0000000..4464cb0 --- /dev/null +++ b/libkonq/Mainpage.dox @@ -0,0 +1,28 @@ +/** @mainpage libkonq + +Provides high-level file management functions, such as history, +bookmarks, popup menus and undo functionality. +KDE File Manager & Web Browser + Xestor de ficheros y restolador web de KDE + KDE datotečni menadžer & Web Browser + El gestor de fitxers i navegador web del KDE + El gestor de fitxers i navegador web del KDE + Správce souborů & prohlížeč Webu pro prostředí KDE + KDE's filhåndtering og webbrowser + Dateiverwaltung & Webbrowser von KDE + Διαχειριστής αρχείων του KDE & περιηγητής Ιστού + KDE File Manager & Web Browser + Administrador de archivos de KDE y navegador web + KDE failihaldur & veebibrauser + KDE fitxategi-kudeatzailea eta web-arakatzailea + KDE:n tiedostonhallinta ja verkkoselain + Gestionnaire de fichiers pour KDE & navigateur Web + Xestor de ficheiros e navegador web de KDE + KDE fájlkezelő és webböngésző + Gerente de file de KDE & Navigator de Web + Pengelola File KDE & Penelusur Web + Gestore dei file e browser web di KDE + KDE 파일 관리자 및 웹 브라우저 + KDE filbehandler og nettleser + KDE sien Dateipleger un Nettkieker + KDE's bestandsbeheerder & webbrowser + Filhandsamar og nettlesar for KDE + ਕੇਡੀਊ ਫਾਇਲ ਮੈਨੇਜਰ ਤੇ ਵੈੱਬ ਬਰਾਊਜ਼ਰ + Przeglądarka plików i sieci dla KDE + Gestor de Ficheiros & Navegador Web do KDE + Gerenciador de arquivos e navegador Web do KDE + Диспетчер файлов и веб-браузер от KDE + KDE správca súborov & webový prehliadač + Upravljalnik datotek in spletni brskalnik za KDE + КДЕ‑ов менаџер фајлова и веб прегледач + KDE‑ov menadžer fajlova i veb pregledač + КДЕ‑ов менаџер фајлова и веб прегледач + KDE‑ov menadžer fajlova i veb pregledač + KDE:s filhanterare och webbläsare + KDE Dosya Yöneticisi ve Web Tarayıcısı + Програма для керування файлами та перегляду сторінок інтернету у KDE + xxKDE File Manager & Web Browserxx + KDE 文件管理器 & 网页浏览器 + KDE 檔案管理員與網頁瀏覽器 + +

Konqueror is KDE's Webbrowser and swiss-army-knife for any kind of file-management and file previewing.

+

Konqueror ye'l restolador web de KDE y una navaya suiza pa cualesquier xestión y previsualización de ficheros.

+

Konqueror je KDE's Webbrowser i švicarski nož za sve vrste upravljanja datotekama i pregled datoteka.

+

Konqueror és el navegador web del KDE i una autèntica navalla suïssa per a qualsevol tipus de gestió de fitxers i vista prèvia de fitxers.

+

Konqueror és el navegador web del KDE i una autèntica navalla suïssa per a qualsevol tipus de gestió de fitxers i vista prèvia de fitxers.

+

Konqueror er KDE's Webbrowser og schweizerkniv til alle former for filhåndtering og forhåndsvisning af filer.

+

Konqueror ist KDE's Webbrowser und Schweizer Taschenmesser für alle Arten von Dateiverwaltung und -vorschau.

+

Ο Konqueror είναι ο περιηγητής Ιστού του KDE και πολυεργαλείο για κάθε είδος διαχείρισης και προεπισκόπησης αρχείων.

+

Konqueror is KDE's Webbrowser and swiss-army-knife for any kind of file-management and file previewing.

+

Konqueror es el navegador web predeterminado de KDE y también es una navaja suiza para la gestión y previsualización de archivos.

+

Konqueror on KDE veebilehitseja ja ülim töövahend failide igakülgseks haldamiseks ja vaatamiseks.

+

Konqueror da KDEren web-arakatzailea eta suitzar-armadako-ganibeta edozein motako fitxategi-kudeaketarako eta fitxategi-aurreikusteko.

+

Konqueror on KDE:n verkkoselain ja yleistyökalu kaikenlaiseen tiedostonhallintaan ja esikatseluun.

+

Konqueror est l'outil KDE servant de navigateur Web et de couteau suisse pour n'importe quelle opération de gestion et de prévisualisation de fichier.

+

Konqueror é o navegador web de KDE e unha navalla suíza para calquera tipo de xestión ou vista previa de ficheiros.

+

A Konqueror a KDE webböngészője és svájci bicskája mindenféle fájlkezelési és fájl előnézeti feladathoz.

+

Konqueror es le navigator web de KDE e le instrumento universal pro omne typo de gestion de file e de lor vista preliminar.

+

Konqueror adalah aplikasi Penelusur Web KDE dan bagaikan pisau lipat swiss-army-knife untuk pengelolaan file dan peninjauan file berupa apa pun.

+

Konqueror è un browser web di KDE e un coltellino svizzero per qualsiasi tipo di gestione e anteprima dei file.

+

Konqueror는 KDE의 웹 브라우저이자 만능 파일 관리 및 미리 보기 도구입니다.

+

Konqueror er KDEs nettleser og multiverktøy for all slags filbehandling og forhåndsvisning.

+

Konqueror is KDE sien Nettkieker un dat swiezer Offiziersmetz för all Problemen bi de Dateipleeg un för Vöransichten.

+

Konqueror is de webbrowser van KDE en Zwitsers mes voor elk soort van bestandsbeheer en bekijken van bestanden.

+

Konqueror er KDEs nettlesar og multiverktøy for all slags handsaming og førehandvising av filer.

+

Konqueror jest przeglądarką sieciową KDE i szwajcarskim scyzorykiem we wszystkich działaniach związanych z zarządzaniem i podglądem plików.

+

O Konqueror é o navegador Web do KDE e o canivete-suíço para qualquer tipo de gestão e visualização de ficheiros.

+

Konqueror é o navegador Web do KDE e um canivete-suíço para gerenciamento e visualização de arquivos.

+

Konqueror — веб-браузер от KDE и универсальный инструмент для управления файлами и предварительного просмотра файлов.

+

Konqueror je webový prehliadač pre KDE a švajčiarsky nožík pre akúkoľvek správu súborov a náhľady pre súbory.

+

Konqueror je spletni brskalnik za KDE in švicarski nož za upravljanje ter predoglede datotek.

+

К‑освајач је КДЕ‑ов веб прегледач и швајцарски ножић за свакакво управљање и прегледање фајлова.

+

K‑osvajač je KDE‑ov veb pregledač i švajcarski nožić za svakakvo upravljanje i pregledanje fajlova.

+

К‑освајач је КДЕ‑ов веб прегледач и швајцарски ножић за свакакво управљање и прегледање фајлова.

+

K‑osvajač je KDE‑ov veb pregledač i švajcarski nožić za svakakvo upravljanje i pregledanje fajlova.

+

Konqueror är KDE:s webbläsare och Schweiziska armékniv för alla sorters hantering och förhandsgranskning av filer.

+

Konqueror, KDE'nin Web tarayıcısı ve dosya yönetimi ve dosya ön izleme işlemlerindeki İsviçre çakısıdır.

+

Konqueror — програма для перегляду інтернету у KDE та універсальна програма для керування та попереднього перегляду файлів.

+

xxKonqueror is KDE's Webbrowser and swiss-army-knife for any kind of file-management and file previewing.xx

+

Konqueror 是 KDE 的网页浏览器,以及文件管理和预览的全能利器。

+

Konqueror 是 KDE 的網頁瀏覽器,以及檔案管理與預覽的好工具。

+

Features:

+

Carauterístiques:

+

Svojstva:

+

Característiques:

+

Característiques:

+

Vlastnosti:

+

Funktioner:

+

Funktionen:

+

Χαρακτηριστικά:

+

Features:

+

Funcionalidades:

+

Omadused:

+

Eginbideak:

+

Ominaisuudet:

+

Fonctionnalités :

+

Funcionalidades:

+

Szolgáltatások:

+

Characteristicas:

+

Fitur:

+

Funzionalità

+

기능:

+

Egenskaper:

+

Markmalen:

+

Mogelijkheden:

+

Funksjonar:

+

ਲੱਛਣ:

+

Możliwości:

+

Funcionalidades:

+

Funcionalidades:

+

Возможности:

+

Funkcie:

+

Zmožnosti:

+

Могућности:

+

Mogućnosti:

+

Могућности:

+

Mogućnosti:

+

Funktioner:

+

Özellikler:

+

Можливості:

+

xxFeatures:xx

+

功能:

+

功能:

+
    +
  • Webbrowsing using KHTML or KDEWebKit as rendering engines
  • +
  • Restola la web usando los motores de renderizáu KHTML o KDEWebKit
  • +
  • Pregled weba koristeći KHTML ili KDEWebKit kao pogona za obratu
  • +
  • Navegació web usant KHTML o KDEWebKit com a motors de renderització
  • +
  • Navegació web usant KHTML o KDEWebKit com a motors de renderització
  • +
  • Webbrowsing med KHTML eller KDEWebKit som renderingsmotorer
  • +
  • Browsen im Web mit KHTML oder KDEWebKit als Anzeige-Modul
  • +
  • Περιήγηση Ιστού με χρήση μηχανών αποτύπωσης KHTML ή KDEWebKit
  • +
  • Webbrowsing using KHTML or KDEWebKit as rendering engines
  • +
  • Navegación web con KHTML o KDEWebKit como motores de representación
  • +
  • Veebilehitsemine KHTML-i või KDEWebKiti renderdamismootoriga
  • +
  • Web-arakatzea KHTML edo KDEWebKit errendatzeko motor gisa erabiliz
  • +
  • Verkkoselaus KHTML- tai KDEWebKit-hahmonnusmoottorein
  • +
  • Navigation Web en utilisant les moteurs de rendu KHTML ou KDEWebKit
  • +
  • Navegación web usando KHTML ou KDEWebKit como motores de renderización.
  • +
  • Webböngészés a KHTML vagy KDEWebKit - mint megjelenítő motorok - használatával
  • +
  • Navigation de web usante KHTML o KDEWebKit como motores de rendering
  • +
  • Penelusuran web menggunakan KHTML atau KDEWebKit sebagai mesin rendering
  • +
  • Navigazione web utilizzando KHTML o KDEWebKit come motori di resa
  • +
  • KHTML 및 KDEWebKit 엔진 기반 웹 브라우징
  • +
  • Nettlesing med KHTML eller KDEWebkit som opptegningsmotorer
  • +
  • Nettkieken mit KHTML oder KDEWebKit as Dorstellkarns
  • +
  • Webbrowsing met KHTML of KDEWebKit als engines voor weergave
  • +
  • Nettlesing med KHTML eller KDEWebkit som oppteikningsmotorar
  • +
  • Przeglądanie sieci przy użyciu KHTML lub KDEWebKit jako silniki wyświetlania
  • +
  • Navegação com o KHTML ou o KDEWebKit como motores de visualização
  • +
  • Navegação Web usando KHTML ou KDEWebKit como mecanismo de renderização
  • +
  • Веб-браузер на основе KHTML или KDEWebKit;
  • +
  • Prehliadanie webu pomocou renderovacích enginov KHTML alebo KDEWebKit
  • +
  • Brskanje po spletu s pomočjo izrisovalnih pogonov KHTML ali KDEWebKit
  • +
  • Веб прегледање, преко КХТМЛ‑а или К‑вебкита као рендерског мотора.
  • +
  • Veb pregledanje, preko KHTML‑a ili KWebKita kao renderskog motora.
  • +
  • Веб прегледање, преко КХТМЛ‑а или К‑вебкита као рендерског мотора.
  • +
  • Veb pregledanje, preko KHTML‑a ili KWebKita kao renderskog motora.
  • +
  • Webbläsning med KHTML eller KDEWebKit som Ã¥tergivningsgränssnitt
  • +
  • Gerçekleme motoru olarak KHTML veya KDEWebKit kullanarak web tarama
  • +
  • перегляд сторінок інтернету за допомогою рушіїв обробки і показу даних KHTML та KDEWebKit;
  • +
  • xxWebbrowsing using KHTML or KDEWebKit as rendering enginesxx
  • +
  • 网页浏览使用 KHTML 或 KDEWebKit 作为渲染引擎
  • +
  • 使用 KHTML 或 KDEWebKit 做成像引擎來瀏覽網頁
  • +
  • File management using most of Dolphin's features (including version-control, service menus and the basic UI)
  • +
  • Xestión de ficheros qu'usa la mayoría de carauterístiques de Dolphin (incluyendo'l control versiones, los menús de servicios y una IU básica)
  • +
  • Upravljanje datotekama s većinom Dolphin mogućnosti (kontrola verzija, servisni meniji i osnovni UI)
  • +
  • Gestió de fitxers usant la major part de les característiques del Dolphin (incloent-hi el control de versions, menús de servei i la interfície d'usuari bàsica)
  • +
  • Gestió de fitxers usant la major part de les característiques del Dolphin (incloent-hi el control de versions, menús de servei i la interfície d'usuari bàsica)
  • +
  • FilhÃ¥ndtering med de fleste af Dolphins funktioner (inklusiv servicemenuer til versionsstyring og basal UI)
  • +
  • Die Dateiverwaltung verwendet die meisten Funktionen von Dolphin, einschließlich der Dienstmenüs für Versionskontrolle und die zugrunde liegende grafische Oberfläche.
  • +
  • Διαχείριση αρχείων που χρησιμοποιεί τα περισσότερα από τα χαρακτηριστικά του Dolphin (όπως τον έλεγχο εκδόσεων, τα μενού υπηρεσιών και το βασικό γραφικό περιβάλλον)
  • +
  • File management using most of Dolphin's features (including version-control, service menus and the basic UI)
  • +
  • Administración de archivos mediante la mayoría de las funcionalidades de Dolphin (incluido el control de versiones, los menús de mantenimiento y la interfaz de usuario básica)
  • +
  • Failihaldus enamiku Dolphini võimalustega (sealhulgas versioonihaldus, teenustemenüüd ja põhimõtteline kasutajaliides)
  • +
  • Fitxategi-kudeaketa Dolphinen eginbide gehienak erabiliz (bertsio-kontrola, zerbitzu menuak eta oinarrizko EI erabiliz)
  • +
  • Tiedostonhallinta useimmin Dolphinin ominaisuuksin (myös versionhallinta, palveluvalikot ja peruskäyttöliittymä)
  • +
  • Gestion de fichiers en utilisant la plupart des fonctionnalités de Dolphin (y compris les services de contrôle de révision, les menus de services et l'interface utilisateur de base)
  • +
  • Xestión de ficheiros coa meirande parte das funcionalidades de Dolphin, incluíndo a compatibilidade cos sistemas de control de versións, os menús de servizos, e a interface gráfica básica.
  • +
  • Fájlkezelés a Dolphin szolgáltatásai nagy részének használatával (beleértve a verziókezelést, szolgáltatásmenüket és az alap felhasználói felületet)
  • +
  • Gerente de file usante le plus de characteristicas de Dolphin (includente le controlo de version, le menu de servicio e le UI basic)
  • +
  • Pengelolaan file menggunakan sebagian besar fitur dari Dolphin (termasuk kendali versi, menu-menu layanan dan basis UI)
  • +
  • Gestione dei file utilizzando la maggior parte delle funzionalità di Dolphin (incluse il controllo di versione, i menu di servizio e l'interfaccia di base)
  • +
  • Dolphin의 기능을 사용하는 파일 관리(버전 관리, 서비스 메뉴, 기본 UI 포함)
  • +
  • Filbehandling som buker de fleste av Dolphins muligheter (bl.a. versjonsstyring, tjenestemenyer og den grunnleggende brukerflaten)
  • +
  • Dateipleeg mit de mehrsten vun Dolphin sien Funkschonen (ok Verschoonkuntrull, Deenstmenüs un de Brukerböversiet)
  • +
  • Bestandsbeheer met gebruik van de meeste functies van Dolphin (inclusief beheer van versies, service-menu's en de basis UI)
  • +
  • Filhandsaming som brukar dei fleste funksjonane i Dolphins (mellom anna versjonsstyring, tenestemenyar og den grunnleggjande brukarflata)
  • +
  • Zarządzanie plikami przy wykorzystaniu większości z możliwości Dolphina (włączając w to zarządzanie wersjami, menu usług i podstawowy układ sterowania)
  • +
  • Gestão de ficheiros, usando a maioria das funcionalidades do Dolphin (incluindo o controlo de versões, os menus de serviços e a interface básica)
  • +
  • Gerenciamento de arquivos usando muitas das funcionalidades do Dolphin (incluindo controle de versão, menus de serviço e interface básica)
  • +
  • Функциональность диспетчера файлов, включая большинство возможностей Dolphin (поддержка систем управления версиями, меню действий и основной графический интерфейс Dolphin);
  • +
  • Správa súborov pomocou väčšiny funkcií Dolphina (vrátane správy verzií, servisných ponúk a základného UI)
  • +
  • Upravljanje datotek z večino zmožnosti Dolphina (vključno z nadzorom različic, meniji s storitvami ter osnovnim uporabniÅ¡kim vmesnikom)
  • +
  • Управљање фајловима, користећи већину Делфинових могућности (укључујући управљање верзијама, сервисне меније, и основно сучеље).
  • +
  • Upravljanje fajlovima, koristeći većinu Dolphinovih mogućnosti (uključujući upravljanje verzijama, servisne menije, i osnovno sučelje).
  • +
  • Управљање фајловима, користећи већину Делфинових могућности (укључујући управљање верзијама, сервисне меније, и основно сучеље).
  • +
  • Upravljanje fajlovima, koristeći većinu Dolphinovih mogućnosti (uključujući upravljanje verzijama, servisne menije, i osnovno sučelje).
  • +
  • Filhantering med användning av de flesta funktioner i Dolphin (inklusive versionshantering, tjänstmenyer och det grundläggande användargränssnittet)
  • +
  • Dolphin'in çoğu özelliğini (sürüm kontrolü, servis menüleri ve temel UI dahil) kullanarak dosya yönetimi
  • +
  • керування файлами за допомогою основних можливостей Dolphin (зокрема можливостей з використання систем керування версіями, службових меню та базового інтерфейсу користувача);
  • +
  • xxFile management using most of Dolphin's features (including version-control, service menus and the basic UI)xx
  • +
  • 文件管理器拥有 Dolphin 的大部分特性 (包括版本控制,服务菜单和基本用户界面)
  • +
  • 用大部份 Dolphin 的功能來做檔案管理(包括版本控制、服務選單與基本介面等)
  • +
  • File management on ftp and sftp servers
  • +
  • Xestión de ficheros en sirvidores FTP y SFTP
  • +
  • Upravljanje datotekama na ftp i sftp serverima
  • +
  • Gestió de fitxers als servidors FTP i SFTP
  • +
  • Gestió de fitxers als servidors FTP i SFTP
  • +
  • FilhÃ¥ndtering pÃ¥ ftp- og sftp-servere
  • +
  • Dateiverwaltung für FTP- und SFTP-Server
  • +
  • Διαχείριση αρχείων σε ftp και sftp εξυπηρετητές
  • +
  • File management on ftp and sftp servers
  • +
  • Administración de archivos en servidores ftp y sftp
  • +
  • Failihaldus FTP- ja SFTP-serverites
  • +
  • Fitxategi-kudeaketa ftp eta sftp zerbitzarietan
  • +
  • Tiedostonhallinta ftp- ja sftp-palvelimilla
  • +
  • Gestion de fichiers à travers les serveurs FTP et SFTP
  • +
  • Xestión de ficheiros de servidores FTP e SFTP.
  • +
  • Fájlkezelés FTP és SFTP kiszolgálókon
  • +
  • Gestion complete su servitores ftp e sftp
  • +
  • Pengelolaan file pada server-server ftp dan sftp
  • +
  • Gestione dei file su server ftp e sftp
  • +
  • FTP 및 SFTP 서버 파일 관리
  • +
  • Filbehandling pÃ¥ ftp- og sftp-tjenere
  • +
  • Dateipleeg op FTP- un SFTP-Sersvers
  • +
  • Bestandsbeheer op ftp- en sftp-servers
  • +
  • Filhandsaming pÃ¥ FTP og SFTP-tenarar
  • +
  • Zarządzanie plikami na serwerach ftp i sftp
  • +
  • Gestão de ficheiros em servidores de FTP e SFTP
  • +
  • Gerenciamento de arquivos em servidores ftp e sftp
  • +
  • Работа с файлами на серверах FTP и SFTP;
  • +
  • Správa súborov na ftp a sftp serveroch
  • +
  • Upravljanje datotek na strežnikih ftp in sftp
  • +
  • Управљање фајловима на ФТП и СФТП серверима.
  • +
  • Upravljanje fajlovima na FTP i SFTP serverima.
  • +
  • Управљање фајловима на ФТП и СФТП серверима.
  • +
  • Upravljanje fajlovima na FTP i SFTP serverima.
  • +
  • Filhantering pÃ¥ FTP- och SFTP-servrar
  • +
  • Ftp ve sftp sunucularında dosya yönetimi
  • +
  • керування файлами на серверах ftp та sftp;
  • +
  • xxFile management on ftp and sftp serversxx
  • +
  • 管理 FTP 和 SFTP 服务器上的文件
  • +
  • 在 ftp 與 sftp 伺服器的檔案管理
  • +
  • Full featured FTP-client (you can split views to display local and remote folders and previews in the same window)
  • +
  • Un veceru completu de FTP (pues dixebrar la vista p'amosar les carpetes llocales y remotes, y previsualizales na mesma ventana)
  • +
  • Puni FTP-klijent (možete podijeliti poglede da prikazuje lokalne i udaljene direktorije i preglede u istom prozoru)
  • +
  • Un complet client FTP (podeu dividir les vistes per a mostrar les carpetes locals i remotes, així com les vistes prèvies a la mateixa finestra)
  • +
  • Un complet client FTP (podeu dividir les vistes per a mostrar les carpetes locals i remotes, així com les vistes prèvies a la mateixa finestra)
  • +
  • FTP-klient med fuld funktionalitet (du kan opdele visningen for at se lokale og eksterne mapper og forhÃ¥ndsvisninger i det samme vindue)
  • +
  • Vollwertiger FTP-Client, Sie können geteilte Ansichten zur Anzeige der lokalen und entfernten Dateien und Vorschauen im gleichen Fenster verwenden
  • +
  • Πλήρης εφαρμογή FTP (μπορείτε να διαιρέσετε τις επισκοπήσεις για να εμφανίσετε τοπικούς και απομακρυσμένους φακέλους και προεπισκοπήσεις στο ίδιο παράθυρο)
  • +
  • Full featured FTP-client (you can split views to display local and remote folders and previews in the same window)
  • +
  • Cliente FTP totalmente equipado (se puede dividir las vistas para mostrar carpetas locales y remotas y vistas previas en la misma ventana)
  • +
  • Kõigi võimalustega FTP-klient (vaate võib poolitada kohalike ja võrgukataloogide ja nende sisu kõrvuti nägemiseks)
  • +
  • Eginbide osoko FTP-bezeroa (ikuspegia zatitu dezakezu leiho berean bertako eta urruneko karpetak eta aurreikuspegiak azaltzeko)
  • +
  • Täyspiirteinen FTP-asiakas (voit nähdä paikallis- ja etäkansiot ja esikatselut samassa ikkunassa jakamalla näkymän)
  • +
  • Client FTP complet (vous pouvez partager la vue pour afficher les dossiers locaux et distants dans la même fenêtre)
  • +
  • Potente cliente de FTP. Permítelle dividir a vista para mostrar tanto os cartafoles locais como os remotos e vistas previas, todo na mesma xanela.
  • +
  • Teljes felszereltségű FTP-kliens (feloszthatja a nézeteket a helyi és távoli mappák megjelenítéséhez, és előnézetet jelenít meg ugyanabban az ablakban)
  • +
  • Complete cliente de FTP (tu pote scinder vistas pro monstrar dossieres local e remote e vistas preliminar in le mesme fenestra)
  • +
  • FTP klien yang berfitur lengkap (kamu bisa membelah tampilan untuk menampilkan folder-folder lokal dan jarak jauh dan mempratinjau dalam window yang sama)
  • +
  • Client FTP completo di tutte le funzionalità (è possibile dividere la vista per visualizzare le cartelle locali e remote e le anteprime nelle stessa finestra)
  • +
  • 완전한 FTP 클라이언트(같은 창에서 로컬 및 원격 폴더를 나눠서 ë³¼ 수 있음)
  • +
  • Fullt utstyrt FTP-klient (du kan dele vinduer slik at mapper pÃ¥ tjeneren og lokale mapper kan vises i samme vindu, sammen med forhÃ¥ndsvisninger)
  • +
  • FTP-Client mit all nödig Funkschonen (deelt Ansicht för lokaal un feern Ornern un Vöransichten binnen dat sülve Finster)
  • +
  • FTP-client met alle functies (u kunt weergaven splitsen om lokale mappen en die op afstand te tonen en voorbeelden in hetzelfde venster)
  • +
  • Funksjonsrik FTP-klient (du kan dela vindauge slik at mapper pÃ¥ tenaren og lokale mapper kan visast i same vindauge, saman med førehandsvisingar)
  • +
  • W pełni funkcjonalny klient FTP (można dzielić widoki tak, aby wyświetlały lokalne i zdalne katalogi wraz z podglądami w tym samym oknie)
  • +
  • Cliente de FTP completo (poderá dividir as janelas para mostrar os ficheiros locais, remotos e as antevisões na mesma janela)
  • +
  • Cliente FTP completo e repleto de recursos (você pode dividir a área de exibição para mostrar as pastas locais e remotas na mesma janela)
  • +
  • Полнофункциональный клиент FTP, включающий двухпанельный режим и предварительный просмотр файлов;
  • +
  • Plne funkčný FTP klient (môžete rozdeliÅ¥ pohľady na zobrazenie miestnych a vzdialených priečinkov a náhľadov v rovnakom okne)
  • +
  • Polno zmogljiv odjemalec za FTP (poglede lahko razdelite, da prikazujejo krajevne in oddaljene mape, v istem oknu pa tudi predoglede)
  • +
  • Свеобухватни ФТП клијент (можете поделити приказ тако да се у истом прозору виде и локална и удаљена фасцикла, као и прегледи).
  • +
  • Sveobuhvatni FTP klijent (možete podeliti prikaz tako da se u istom prozoru vide i lokalna i udaljena fascikla, kao i pregledi).
  • +
  • Свеобухватни ФТП клијент (можете поделити приказ тако да се у истом прозору виде и локална и удаљена фасцикла, као и прегледи).
  • +
  • Sveobuhvatni FTP klijent (možete podeliti prikaz tako da se u istom prozoru vide i lokalna i udaljena fascikla, kao i pregledi).
  • +
  • FTP-klient med fullständiga funktioner (det gÃ¥r att dela vyer för att visa lokala kataloger, fjärrkataloger och förhandsgranskningar i samma fönster)
  • +
  • Tam özellikli FTP istemcisi (yerel ve uzak klasör görünümlerini ayırabilir ve ön izlemelerini aynı pencerede gösterebilirsiniz)
  • +
  • повноцінний клієнт FTP (ви можете розділити вікно перегляду на панелі локальної копії та відповідної теки на сервері і переглядати дані з обох тек у одному вікні);
  • +
  • xxFull featured FTP-client (you can split views to display local and remote folders and previews in the same window)xx
  • +
  • 全功能的 FTP 客户端 (您可以拆分视图,在同一窗口显示本地和远程文件夹)
  • +
  • 完整功能的 FTP 用戶端程式(您可以分割檢視,在同一視窗中同時顯示本地端與遠端的資料夾)
  • +
  • Embedded applications to preview files (e.g. Okular and Calligra for documents, Gwenview for pictures, KTextEditor for text-files)
  • +
  • Aplicaciones empotraes pa previsualizar ficheros (Okular y Calligra pa documentos, GWenview pa semeyes o pa ficheros de testu… etc)
  • +
  • Ugrađene aplikacije za pregled datoteka (npr.. Okular i Calligra za dokumente, Gwenview za slike, KTextEditor za tekst datoetke)
  • +
  • Aplicacions incrustades per a previsualitzar fitxers (p. ex., Okular i Calligra pels documents, Gwenview per a les fotografies, KTextEditor pels fitxers de text)
  • +
  • Aplicacions incrustades per a previsualitzar fitxers (p. ex., Okular i Calligra pels documents, Gwenview per a les fotografies, KTextEditor pels fitxers de text)
  • +
  • Indlejrede programmer til forhÃ¥ndsvisning af filer (f.eks. Okular og Calligra til dokumenter, Gwenview til billeder, KTextEditor til tekstfiler)
  • +
  • Eingebettete Programme zur Anzeige von Dateien (.z. B. Okular und Calligra für Dokumente, Gwenview für Bilder, KTextEditor für Textdateien)
  • +
  • Ενσωματωμένες εφαρμογές για προεπισκόπηση αρχείων (π.χ. Okular και Calligra για έγγραφα, Gwenview για εικόνες, KTextEditor για αρχεία κειμένου)
  • +
  • Embedded applications to preview files (e.g. Okular and Calligra for documents, Gwenview for pictures, KTextEditor for text-files)
  • +
  • Aplicaciones integradas para previsualizar archivos (por ejemplo, Okular y Calligra para documentos, Gwenview para imágenes, KTextEditor para archivos de texto)
  • +
  • Lõimitud rakendused falide eelvaatluseks (nt Okular ja Calligra dokumentide, Gwenview piltide, KTextEditor tekstifailide jaoks)
  • +
  • Txertatutako aplikazioak fitxategiak aurreikusteko (adib. Okular eta Calligra dokumentuetarako, Gwenview irudietarako, KTextEditor testu-fitxategietarako)
  • +
  • Upotteiset sovellukset tiedostojen esikatseluun (esim. Okular ja Calligra tekstiasiakirjoille, Gwenview kuville ja KTextEditor tekstitiedostoille)
  • +
  • Applications embarquées pour prévisualiser les fichiers (p.ex. Okular et Calligra pour les documents, Gwenview pour les images, KTextEditor pour les fichiers texte)
  • +
  • Aplicacións incrustadas para previsualizar ficheiros. Por exemplo, Okular e Calligra para documentos, Gwenview para imaxes, KTextEditor para ficheiros de texto, etc.
  • +
  • Beágyazott alkalmazások fájlok előnézetéhez (például Okular és Calligra a dokumentumokhoz, Gwenview a képekhez, KTextEditor a szövegfájlokhoz)
  • +
  • Applicationes includite pro vista preliminar de files (p.ex. Okular e Calligra pro documentos, Gwenview pro images, KTextEditor pro files de texto)
  • +
  • Aplikasi tertanam untuk mempratinjau file-file (untuk dokumen yaitu Okular dan Calligra, untuk gambar yaitu Gwenview, untuk file-file teks yaitu KTextEditor)
  • +
  • Applicazioni integrate per l'anteprima dei file (ad es. Okular e Calligra per i documenti, Gwenview per le immagini, KTextEditor per i file di testo)
  • +
  • 파일을 미리 ë³¼ 수 있는 내장형 프로그램(예: 문서용 Okular, Calligra, 그림용 Gwenview, 텍스트용 KTextEditor)
  • +
  • Innebygde programmer som kan forhÃ¥ndsvise filer (f.eks. Okular og Calligra for dokumenter, Gwenview for bilder, KTextEditor for tekstfiler)
  • +
  • Ingebedde toepassingen om bestanden te bekijken (bijv. Okular en Calligra voor documenten, Gwenview voor afbeeldingen, KTextEditor voor tekstbestanden)
  • +
  • Innebygde program som kan førehandsvisa filer (for eksempel Okular og Calligra for dokument, Gwenview for bilete og KTextEditor for tekstfiler)
  • +
  • Osadzone aplikacje do podglądania plików (np. Okular i Calligra dla dokumentów, Gwenview dla zdjęć, KTextEditor dla plików tekstowych)
  • +
  • Aplicações incorporadas para antever e editar os ficheiros (p.ex., o Okular e o Calligra para os documentos, o Gwenview para as imagens, o KTextEditor para os ficheiros de texto)
  • +
  • Visualização de arquivos com aplicativos incorporados (p.ex., Okular e Calligra para documentos, Gwenview para imagens, KTextEditor para arquivos de texto)
  • +
  • Встраивание приложений для просмотра файлов (например, Okular и Calligra — для просмотра документов, Gwenview — для изображений, KTextEditor — для текстовых файлов);
  • +
  • Zabudované aplikácie na náhľad a úpravu súborov (napr. Okular a Calligra pre dokumenty, Gwenview pre obrázky, KTextEditor pre textové súbory)
  • +
  • Vgrajeni programi za predogled datotek (npr. Okular in Calligra za dokumente, Gwenview za slike, KTextEditor za besedilne datoteke)
  • +
  • Угнежђени програми за прегледање фајлова (нпр. Окулар и Калигра за документе, Гвенвју за слике, К‑писање за текстуалне фајлове).
  • +
  • Ugnežđeni programi za pregledanje fajlova (npr. Okular i Calligra za dokumente, GwenView za slike, K‑pisanje za tekstualne fajlove).
  • +
  • Угнежђени програми за прегледање фајлова (нпр. Окулар и Калигра за документе, Гвенвју за слике, К‑писање за текстуалне фајлове).
  • +
  • Ugnežđeni programi za pregledanje fajlova (npr. Okular i Calligra za dokumente, GwenView za slike, K‑pisanje za tekstualne fajlove).
  • +
  • Inbäddade program för att förhandsgranska och redigera filer (t.ex. Okular och Calligra för dokument, Gwenview för bilder, Ktexteditor för textfiler)
  • +
  • Dosyaların ön izlemeleri için gömülü uygulamalar (belgeler için Okular ve Calligra, resimler için Gwenview, metin dosyaları için KTextEditor gibi)
  • +
  • вбудовування програм для попереднього перегляду файлів (документи Okular та Calligra, зображення Gwenview, текстові файли KTextEditor)
  • +
  • xxEmbedded applications to preview files (e.g. Okular and Calligra for documents, Gwenview for pictures, KTextEditor for text-files)xx
  • +
  • 内嵌文件预览 (例如 Okular 和 Calligra 预览文档,Gwenview 预览图片,KTextEditor 预览文本文件)
  • +
  • 嵌入式的應用程式,預覽檔案(如 Okular 與 Calligra 預覽文件,Gwenview 預覽圖片,KTextEditor 編輯文字檔等)
  • +
  • Different kinds of plugins: Service-menus, KParts (embedded applications), KIO (accessing files using special protocols like http or ftp) and KPart-plugins (like AdBlocker...)
  • +
  • Tribes diferentes de plugins: Menús de servicios, KParts (aplicaciones empotraes), KIO (accesu a ficheros usando protocolos especiales como http o ftp) y plugins de KPart (como'l bloquiador d'anuncios…)
  • +
  • Razne vrste dodataka: Servisni meniji, KParts (ugrađene aplikacije), KIO (pristup datotekama specijalnim protokolima poput http ili ftp) i KPart-dodacima (kao Å¡to je AdBlocker...)
  • +
  • Diferents tipus de connectors: menús de servei, les KPart (aplicacions incrustades), KIO (accés a fitxers usant protocols especials com HTTP o FTP) i connectors amb KPart (com AdBlocker...)
  • +
  • Diferents tipus de connectors: menús de servei, les KPart (aplicacions incrustades), KIO (accés a fitxers usant protocols especials com HTTP o FTP) i connectors amb KPart (com AdBlocker...)
  • +
  • Forskellige slags plugins: Servicemenuer, KParts (indlejrede programmer), KIO (tilgang til filer med særlige protokoller sÃ¥som http eller ftp) og KPart-plugins (sÃ¥som AdBlocker...)
  • +
  • Verschiedene Arten von Modulen: Dienstmenüs, KParts (eingebettete Anwendungen), KIO (Zugriff auf Dateien mit den speziellen Protokollen wie http oder ftp) und KParts.-Module wie Werbeblocker usw.
  • +
  • Διαφορετικά είδη προσθέτων: Μενού υπηρεσιών, KParts (ενσωματωμένες εφαρμογές), KIO (για πρόσβαση σε αρχεία με χρήση ειδικών πρωτοκόλλων όπως http ή ftp) και KPart-plugins (όπως AdBlocker...)
  • +
  • Different kinds of plugins: Service-menus, KParts (embedded applications), KIO (accessing files using special protocols like http or ftp) and KPart-plugins (like AdBlocker...)
  • +
  • Diferentes tipos de complementos: menús de mantenimiento, KParts (aplicaciones integradas), KIO (archivos de acceso que utilizan protocolos especiales como http o ftp) y complementos de KPart (como AdBlocker, etc.)
  • +
  • Arvukad pluginad: teenustemenüüd, KParts (lõimitud rakendused), KIO (failide kasutamiseks spetsiaalsete protokollide vahendusel, nt http või ftp) ja KPart-pluginad (nt AdBlocker)
  • +
  • Plugin mota desberdinak: zerbitzu-menuak, KParts (txertatutako aplikazioak), KIO (fitxategiak atzitu protokolo bereziak erabiliz, hala nola http edo ftp) eta KPart-plugins (AdBlocker, ..., bezalakoa)
  • +
  • Eri liitännäiset: palveluvalikot, KPartit (upotteiset sovellukset), KIO (tiedostojen käsittely eri yhteyskäytännöin kuten http:llä tai ftp:llä) sekä KPart-liitännäiset (kuten AdBlocker)
  • +
  • Différents types d'extensions : menus services, KParts (applications embarquées), KIO (accès aux fichiers à travers des protocoles particuliers comme HTTP ou FTP) et les extensions KParts (telle qu'AdBlocker…)
  • +
  • Distintos tipos de complementos: menús de servizos, KParts (aplicacións incrustadas), KIO (acceso a ficheiros mediante protocolos especiais como HTTP ou FTP) e complementos de KPart (como AdBlocker).
  • +
  • Különféle bővítménytípusok: Szolgáltatásmenük, KParts (beágyazott alkalmazások), KIO (fájlok elérése speciális protokollok - mint például http vagy ftp - használatával) és KPart-bővítmények (mint például AdBlocker…)
  • +
  • Differente typos de pluigin: Menus de servicio, KParts (applicationes insertate), KIO (accesso a files per protocollos special como http o ftp) e plugins de KPart (como AdBlocker...)
  • +
  • Plugin-plugin yang berbeda berupa: Menu-menu layanan, KParts (aplikasi tertanam, KIO (mengakses file menggunakan protokol khusus seperti http atau ftp) dan plugin-plugin KPart (seperti AdBlocker...)
  • +
  • Diversi tipi di estensioni: menu di servizio, KPart (applicazioni integrate), KIO (accesso ai file utilizzando protocolli specifici come http o ftp) e estensioni KPart (come AdBlocker...)
  • +
  • 다양한 플러그인: 서비스 메뉴, KParts(내장형 프로그램), KIO(HTTP, FTP 등 프로토콜을 사용한 파일 접근), KPart 플러그인(광고 차단 등)
  • +
  • Diverse tilleggsmoduler: Tjenestemenyer, KParts (innebygde programmer), KIO (tilgang til filer ved bruk av spesielle protokoller som http elle ftp) og KPart-moduler (slik som AdBlocker osv.)
  • +
  • Verscheden Moduul-Oorden: Deenstmenüs, KParts (inbett Programmen), KIO-In-/Utgaavmodulen (Togriep op Dateien över besünner Protokollen as HTTP oder FTP) un KPart-Modulen (as AdBlocker ...)
  • +
  • Verschillende soorten plug-ins: Service-menu's, KParts (ingebedde toepassing), KIO (toegang tot bestanden met speciale protocollen zoals http of ftp) en KPart-plug-ins (zoals AdBlocker...)
  • +
  • Ymse tilleggsmodular: tenestemenyar, KParts (innebygde program), KIO (tilgang til filer ved bruk av spesielle protokollar som HTTP eller FTP) og KPart-tillegg (som for eksempel AdBlocker)
  • +
  • Różne rodzaje wtyczek: Menu usług, KParts (osadzone aplikacje), KIO (dostęp do plików przy użyciu protokołów takich jak http czy ftp) oraz wtyczki KPart (takie jak AdBlocker...)
  • +
  • Diferentes tipos de 'plugins': menus de serviços, KParts (aplicações incorporadas), KIO (acesso a ficheiros usando protocolos especiais como o HTTP ou o FTP) e os 'plugins' de KParts (como o bloqueio de anúncios, ...)
  • +
  • Vários tipos de plugins: Menus de serviço, KParts (aplicativos incorporados), KIO (acesso a arquivos usando protocolos especiais, como o http ou ftp) e plugins KParts (como o AdBlocker...)
  • +
  • Расширяемость с помощью различных модулей: меню действий, KParts (встраиваемые приложения), KIO (доступ к файлам по специальным протоколам, например HTTP и FTP) и модули KPart (например, модуль для блокировки рекламы).
  • +
  • Rôzne typy pluginov: Servisné ponuky, KParts (zabudované aplikácie), KIO (prístup k súborom pomocou Å¡peciálnych protokolov ako http alebo ftp) a KPart-pluginy (ako AdBlocker...)
  • +
  • Različne vrste vstavkov: meniji s storitvami, KParts (vgrajeni programi), KIO (dostop do datotek s protokoli kot sta http ali ftp) ter vstavki KPart (npr. AdBlock ...)
  • +
  • Разне врсте прикључака: сервисни менији, К‑делови (угнежђени програми), К‑У/И (приступ фајловима преко специјалних протокола, попут ХТТП‑а и ФТП‑а) и прикључци над К‑деловима (нпр. Адблок).
  • +
  • Razne vrste priključaka: servisni meniji, K‑delovi (ugnežđeni programi), K‑U/I (pristup fajlovima preko specijalnih protokola, poput HTTP‑a i FTP‑a) i priključci nad K‑delovima (npr. AdBlock).
  • +
  • Разне врсте прикључака: сервисни менији, К‑дијелови (угнежђени програми), К‑У/И (приступ фајловима преко специјалних протокола, попут ХТТП‑а и ФТП‑а) и прикључци над К‑дијеловима (нпр. Адблок).
  • +
  • Razne vrste priključaka: servisni meniji, K‑dijelovi (ugnežđeni programi), K‑U/I (pristup fajlovima preko specijalnih protokola, poput HTTP‑a i FTP‑a) i priključci nad K‑dijelovima (npr. AdBlock).
  • +
  • Olika typer av insticksprogram: Tjänstmenyer, KParts (inbäddade program), KIO (Ã¥tkomst av filer med särskilda protokoll sÃ¥som http och ftp) och KPart-insticksprogram (som reklamblockering ...)
  • +
  • Çeşitli eklentiler: Servis menüleri, KParts (gömülü uygulamalar), KIO (http ve ftp gibi protokoller kullanarak dosyalara erişim) ve Kpart eklentileri (AdBlocker gibi)
  • +
  • додатки різних типів: службові меню, модулі KPart (вбудовані програми), KIO (доступ до файлів на основі спеціалізованих протоколів, зокрема http та ftp) та додатки KPart (зокрема додатки блокування реклами).
  • +
  • xxDifferent kinds of plugins: Service-menus, KParts (embedded applications), KIO (accessing files using special protocols like http or ftp) and KPart-plugins (like AdBlocker...)xx
  • +
  • 多种多样的插件:服务菜单,KParts (嵌入应用),KIO (通过特殊协议访问文件,比如 HTTP 和 FTP) 和 KPart 插件 (例如 AdBlocker)
  • +
  • 各種外掛程式:服務選單,KParts 部件(嵌入應用程式),KIO(使用特殊協定如 http 或 ftp 來存取檔案)與 KPart 外掛程式(如 AdBlocker 等等)
  • +
+
+ https://www.konqueror.org + https://bugs.kde.org/enter_bug.cgi?format=guided&product=konqueror + https://docs.kde.org/stable5/en/applications/konqueror/index.html + https://www.kde.org/community/donations/?app=konqueror&source=appdata + + + https://cdn.kde.org/screenshots/konqueror/konqueror.png + + + KDE + + konqueror + + diff --git a/org.kde.konqueror.desktop b/org.kde.konqueror.desktop new file mode 100644 index 0000000..978eb5a --- /dev/null +++ b/org.kde.konqueror.desktop @@ -0,0 +1,226 @@ +[Desktop Entry] +Type=Service +NoDisplay=true +Name=Konqueror +Name[af]=Konqueror +Name[ar]=كونكيورر +Name[as]=Konqueror +Name[ast]=Konqueror +Name[be]=Konqueror +Name[be@latin]=Konqueror +Name[bg]=Konqueror +Name[bn]=কনকরার +Name[bn_IN]=Konqueror +Name[br]=Konqueror +Name[bs]=K‑osvajač +Name[ca]=Konqueror +Name[ca@valencia]=Konqueror +Name[cs]=Konqueror +Name[csb]=Konqueror +Name[cy]=Konqueror +Name[da]=Konqueror +Name[de]=Konqueror +Name[el]=Konqueror +Name[en_GB]=Konqueror +Name[eo]=Konkeranto +Name[es]=Konqueror +Name[et]=Konqueror +Name[eu]=Konqueror +Name[fi]=Konqueror +Name[fr]=Konqueror +Name[fy]=Konqueror +Name[ga]=Konqueror +Name[gl]=Konqueror +Name[gu]=કોન્કરર +Name[he]=Konqueror +Name[hi]=कॉन्करर +Name[hne]=कान्करर +Name[hr]=Konqueror +Name[hsb]=Konqueror +Name[hu]=Konqueror +Name[ia]=Konqueror +Name[id]=Konqueror +Name[is]=Konqueror +Name[it]=Konqueror +Name[ja]=Konqueror +Name[ka]=Konqueror +Name[kk]=Konqueror +Name[km]=Konqueror +Name[kn]=ಕಾಂಕರರ್ +Name[ko]=Konqueror +Name[ku]=Konqueror +Name[lt]=Konqueror +Name[lv]=Konqueror +Name[mai]=कोन्करर +Name[mk]=Konqueror +Name[ml]=കോണ്‍ക്വറര്‍ +Name[mr]=कॉन्करर +Name[ms]=Konqueror +Name[nb]=Konqueror +Name[nds]=Konqueror +Name[ne]=कन्क्वेरर +Name[nl]=Konqueror +Name[nn]=Konqueror +Name[oc]=Konqueror +Name[or]=Konqueror +Name[pa]=ਕੋਨਕਿਉਰੋਰ +Name[pl]=Konqueror +Name[pt]=Konqueror +Name[pt_BR]=Konqueror +Name[ro]=Konqueror +Name[ru]=Konqueror +Name[se]=Konqueror +Name[si]=Konqueror +Name[sk]=Konqueror +Name[sl]=Konqueror +Name[sr]=К‑освајач +Name[sr@ijekavian]=К‑освајач +Name[sr@ijekavianlatin]=K‑osvajač +Name[sr@latin]=K‑osvajač +Name[sv]=Konqueror +Name[ta]=கான்கொயரர் +Name[te]=కాంకెరర్ +Name[tg]=Konqueror +Name[th]=Konqueror +Name[tr]=Konqueror +Name[ug]=Konqueror +Name[uk]=Konqueror +Name[uz]=Konqueror +Name[uz@cyrillic]=Konqueror +Name[vi]=Konqueror +Name[wa]=Konqueror +Name[xh]=Konqueror +Name[x-test]=xxKonquerorxx +Name[zh_CN]=Konqueror +Name[zh_TW]=Konqueror +GenericName=Web Browser, File Manager and Viewer +GenericName[ast]=Restolador web, xestor de ficheros y visor +GenericName[ca]=Navegador web, gestor i visualitzador de fitxers +GenericName[ca@valencia]=Navegador web, gestor i visualitzador de fitxers +GenericName[cs]=Webový prohlížeč, správce souborů a prohlížeč dokumentů +GenericName[da]=Webbrowser, filhåndtering og fremviser +GenericName[de]=Webbrowser, Dateiverwaltung und Dokumentenbetrachter +GenericName[el]=Περιηγητής ιστού, διαχειριστής αρχείων και προβολέας +GenericName[en_GB]=Web Browser, File Manager and Viewer +GenericName[es]=Navegador web, gestor y visor de archivos +GenericName[et]=Veebilehitseja, failihaldur ja -näitaja +GenericName[eu]=Web arakatzailea, fitxategi kudeatzailea eta erakuslea +GenericName[fi]=Verkkoselain, tiedostonhallinta ja tiedostokatselin +GenericName[fr]=Navigateur Web, gestionnaire de fichiers et visionneuse +GenericName[gl]=Navegador web, xestor de ficheiros e visor +GenericName[ia]=Navigator de Web, Gerente de File e Visor +GenericName[id]=Penampil Web, Pengelila File dan Penampil +GenericName[is]=Vafri, skráastjóri og skjalarýnir +GenericName[it]=Browser Web, gestore di file e visore +GenericName[ko]=웹 브라우저, 파일 관리자, 문서 뷰어 +GenericName[nl]=Webbrowser, bestandsbeheerder en viewer +GenericName[nn]=Nettlesar, filhandsamar og filvisar +GenericName[pl]=Przeglądarka internetowa i plików +GenericName[pt]=Navegador Web, Gestor de Ficheiros e Visualizador +GenericName[pt_BR]=Navegador web, gerenciador e visualizador de arquivos +GenericName[sk]=Webový prehliadač, Správca súborov a Prezerač +GenericName[sv]=Webbläsare, filhanterare och visare +GenericName[uk]=Веббраузер, програма для керування файлами та перегляду документів +GenericName[x-test]=xxWeb Browser, File Manager and Viewerxx +GenericName[zh_CN]=Web 浏览器,文件管理器和查看器 +GenericName[zh_TW]=瀏覽器、檔案管理器及檢視器 +Exec=konqueror %U +Comment=KDE File Manager & Web Browser +Comment[af]=Kde Lêer Bestuurder & Web Blaaier +Comment[ar]=مدير ملفات كدي و متصفح الوِب +Comment[as]=KDE File Manager & Web Browser +Comment[ast]=Xestor de ficheros y restolador web de KDE +Comment[be]=Файлавы кіраўнік і вандроўнік па Сеціве для KDE +Comment[be@latin]=Kiraŭnik fajłaŭ i hartač sieciva dla KDE +Comment[bg]=Файлов и уеб браузър +Comment[bn]=কে.ডি.ই ফাইল ম্যানেজার এবং ওয়েব ব্রাউজার +Comment[bn_IN]=KDE ফাইল পরিচালন ব্যবস্থা ও ওয়েব ব্রাউজার +Comment[br]=Merour restroù ha merdeer gwiad KDE +Comment[bs]=KDE‑ov menadžer datoteka i veb pregledač +Comment[ca]=El gestor de fitxers i navegador Web del KDE +Comment[ca@valencia]=El gestor de fitxers i navegador Web del KDE +Comment[cs]=Správce souborů a prohlížeč Webu pro prostředí KDE +Comment[csb]=KDE Menadżera lopków ë przezérnik WWW +Comment[cy]=Trefnydd Ffeiliau a Porydd Gwe KDE +Comment[da]=KDE's filhåndtering og webbrowser +Comment[de]=Dateiverwaltung und Webbrowser von KDE +Comment[el]=Διαχειριστής αρχείων & Περιηγητής ιστού του KDE +Comment[en_GB]=KDE File Manager & Web Browser +Comment[eo]=KDE-dosieradministrilo kaj TTT-legilo +Comment[es]=Gestor de archivos y navegador web de KDE +Comment[et]=KDE failihaldur & veebibrauser +Comment[eu]=KDEko fitxategi-kudeatzailea eta web arakatzailea +Comment[fa]=مدیر پرونده و مرورگر وب KDE +Comment[fi]=KDE:n tiedostonhallinta ja selain +Comment[fr]=Gestionnaire de fichiers et navigateur Web de KDE +Comment[fy]=KDE's Triembehearder en webblêder +Comment[ga]=Bainisteoir Comhad agus Brabhsálaí KDE +Comment[gl]=Xestor de ficheiros e navegador web de KDE +Comment[gu]=KDE ફાઇલ વ્યવસ્થાપક અને વેબ બ્રાઉઝર +Comment[he]=מנהל הקבצים ודפדפן האינטרנט של KDE +Comment[hi]=केडीई फ़ाइल प्रबंधक व वेब ब्राउज़र +Comment[hne]=केडीई फाइल प्रबंधक अउ वेब ब्राउजर +Comment[hr]=KDE-ov upravitelj datoteka i web preglednik +Comment[hsb]=KDE datajowy manager & web browser +Comment[hu]=KDE fájlkezelő és webböngésző +Comment[ia]=KDE: Gerente de file & Navigator web +Comment[id]=Pengelola file & Penelusur Web KDE +Comment[is]=KDE skráastjóri og vafri +Comment[it]=Gestore dei file e browser Web di KDE +Comment[ja]=KDE ファイルマネージャ & ウェブブラウザ +Comment[ka]=ფაილური მენეჯერი და ვებ ბრაუზერი +Comment[kk]=KDE файл менеджері және Веб шолғышы +Comment[km]=កម្មវិធី​គ្រប់គ្រង​ឯកសារ និង​កម្មវិធី​រុករក​បណ្ដាញ​របស់ KDE​ +Comment[kn]=ಕೆಡಿಇ ಕಡತ ವ್ಯವಸ್ಥಾಪಕ ಮತ್ತು ಜಾಲ ವೀಕ್ಷಕ +Comment[ko]=KDE 파일 관리자와 웹 브라우저 +Comment[ku]=Rêveberiya pelan û Geroka KDE'yê +Comment[lt]=KDE failų tvarkyklė ir žiniatinklio naršyklė +Comment[lv]=KDE failu pārvaldnieks un tīmekļa pārlūks +Comment[mai]=केडीई फाइल प्रबंधक आ वेब ब्राउजर +Comment[mk]=Менаџер на датотеки и веб-прелистувач во KDE +Comment[ml]=കെഡിഇയിലെ ഫയലുകളുടെ നടത്തിപ്പുകാരനും വെബ് ബ്രൌസറും +Comment[mr]=केडीई फाईल प्रबंधक व वेब ब्राऊजर +Comment[ms]=Pengurus Fail KDE & Pelayar Web +Comment[nb]=Filbehandler og nettleser for KDE +Comment[nds]=KDE sien Dateipleger un Nettkieker +Comment[ne]=केडीई फाइल प्रबन्धक र वेब ब्राउजर +Comment[nl]=KDE's bestandsbeheerder en webbrowser +Comment[nn]=Filhandsamar og nettlesar for KDE +Comment[or]=KDE ଫାଇଲ ପରିଚାଳକ ଏବଂ ୱେବ ବ୍ରାଉଜର +Comment[pa]=KDE ਫਾਇਲ ਮੈਨੇਜਰ ਅਤੇ ਵੈੱਬ ਬਰਾਊਜ਼ਰ +Comment[pl]=Zarządzanie plikami i przeglądarka WWW dla KDE +Comment[pt]=Gestor de ficheiros e navegador na WWW +Comment[pt_BR]=Gerenciador de arquivos e navegador da Internet do KDE +Comment[ro]=Gestionar de fișiere KDE și navigator de web +Comment[ru]=Диспетчер файлов и веб-браузер +Comment[se]=KDE fiilagieđahalli ja fierpmádatlogan +Comment[si]=KDE ගොනු කළමණාකරු සහ වෙබ් ගවේශකය +Comment[sk]=Správca súborov a Web prehliadač pre KDE +Comment[sl]=Upravljalnik datotek in spletni brskalnik za KDE +Comment[sr]=КДЕ‑ов менаџер фајлова и веб прегледач +Comment[sr@ijekavian]=КДЕ‑ов менаџер фајлова и веб прегледач +Comment[sr@ijekavianlatin]=KDE‑ov menadžer fajlova i veb pregledač +Comment[sr@latin]=KDE‑ov menadžer fajlova i veb pregledač +Comment[sv]=KDE:s filhanterare och webbläsare +Comment[ta]=கேபசூ கோப்பு மேலாளர் & வலை உலாவி +Comment[te]=కెడిఈ దస్త్ర అభికర్త & వెబ్ బ్రౌజర్ +Comment[tg]=Мудири файлҳои KDE ва Браузери Интернет +Comment[th]=จัดการแฟ้ม & เว็บเบราว์เซอร์ของ KDE +Comment[tr]=KDE Dosya Yöneticisi ve Web Tarayıcısı +Comment[ug]=KDE ھۆججەت باشقۇرغۇچ ۋە توركۆرگۈ +Comment[uk]=Керування файлами KDE та навігатор інтернету +Comment[uz]=KDE uchun fayl boshqaruvchi va veb-brauzer +Comment[uz@cyrillic]=KDE учун файл бошқарувчи ва веб-браузер +Comment[vi]=Trình quản lý Tập tin và Duyệt mạng KDE +Comment[wa]=Manaedjeu di fitchîs eyet betchteu waibe di KDE +Comment[xh]=Umphathi Wefayile ye KDE & Umkhangeli zincwadi we Web +Comment[x-test]=xxKDE File Manager & Web Browserxx +Comment[zh_CN]=KDE 文件管理器和 Web 浏览器 +Comment[zh_TW]=KDE 檔案管理程式和網頁瀏覽器 +Categories=Qt;KDE;Internet;Network; +Icon=konqueror +X-DBUS-StartupType=multi +X-KDE-StartupNotify=true +X-KDE-HasTempFileOption=true +X-KDE-Protocols=KIO +X-DBUS-ServiceName=org.kde.konqueror diff --git a/pics/128-apps-konqueror.png b/pics/128-apps-konqueror.png new file mode 100644 index 0000000000000000000000000000000000000000..8becfe14d96717c6143558ce0ad41799b2ba1baf GIT binary patch literal 15670 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 cusrt<74^)o>FhRsQ*w~R2 zFfuVRva|DmMHqo3GZQ;MzX%VHkc5N`kip3%z`(4?!onjhtt6o0=Irb#Bco<$XzAza zXKwBs6ci$kf8Zrhw@3 z$lA5(ox9@V3UgXFE?BUtuWRD=?FVx*Y8EZoSW?(n-#mTMqK)O{eH+&9oIGR0gb7Qg zPhGZr%f;=xE?&NHW9Rlmj~>0cckk7cCvT?jc)n%x;oG;LGN>PCFgd|sb&A3641?2o zhREk^Vb^&BE(k_ll`VcMmwsC=@2-5>P1U@+YWa873+`$Zzt(MdY|!z|s^p$W-*d0} z8?log#m{{iKkr@gf>$XEzND=9kh<`7>hkw#i{GSg_>!~nOW~^brESNn7Cvp8ajtXb zsh)%1`geWpKly9=v2W9lf1iHg|IF+EXWsZfch}2>XTB}j|7pp&?@KQHTz2>W@;m=m z-TA-f(f_U2e{J7-V*B+!+i(2cdH(yZi?8=weRJT;|AX)TA3JvS#Pk0re*Hi7`2U$l z-_HE}f9BW!%lE$A`1b$K?Z(8Ix{{rLv{EO@Z!1xO&3GxeOU}R!uW#{1H=H?TXk(Jlb(9zX5F}JYx z^78Qw3QtPUEhw#QYH975JayiJm8;im+_H7g{zHcj9ldz*(v|DC?>>0^eR02eeLV)M%dZT*lgtEwfnMaz%2aOxOzs%{0Np8RDTmsfs)dE)v!k6)g|k Q2Ktu4)78&qol`;+0M-kz@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ=+et)0RCwC0m3vH6R{)0(w51dTu|b}bL^C7XbZ(fr z8RiRyqM-9Rr%oZ$3CZRvMn#PY;{G5*r;`;lkqs3j8;@#30q3$|E2X~Z+Crhw0z#2K zLD~YPE%4jz)Ox3&6q(b0s;aFgH9u_Ol)l2=KlU+xN(m;IhP;I zpTBrr>fY4dv)CbQLTFxu__GM{^?li;K6DcL2Gjt?#lYHA)~zdK(6p^ zR%uuJ$s%R*juYkO5ld5331P8bD!yXHy7b;&Gi=sj=yU_PDzxC2Mmr1+z=h}7DK%Dr z!@Vc=310Z_w6UO|S;XHzfOw#vI`y5`*-env6g*rOW_4)=!|38k@|3 zdIUIhLu;UiEct*;B_t$_goV9EJ-L5YRa971c1K}H{6!tAR4&}1tkaA`)CKTcTqtjH zpn|eYL5e+Kk#on2>>4YwYAlpiym7_^zXcn1O$u{3$4_#(MLdB(*ddd)IwdUw zn0H)@O@(F@N}VWGPT-ty6dNw;k#s?iEz}LS78tROa@Q3T;?L^9_*{qJ#Pg+IUN3|@ zI}P|3$M7(C4JOdHsleLahL3XfC}2i5?+ct!XdLu|uGe{!k3ON$b>2SRRsOSNBT43qvUXYE- zzvp94_2RRVXIPVO!TRjq8)-D!^VcsS;o~pU(lYs6ZfTELB*i^NKW1)KB5;$E3d@jL zZNsl-pxy#VM}aS{nZVktM96LxavGf2#5E$N*p9>_*KU&O@nWx9xi-B^Yewv04Hg|x z<6zkU{-A<#2hijM)Bt{x4&fb+2IoaKlyr<^ zr6qM{?8wzZHVVjGK91{iodQ z?7T;Ec^3u;?NF-?SiO4NwW%A&+_&%G1s<=?nvn3xk4)x_w>?vgl$5XX74lA~+qxlb zY(vW4jC<4-5uSYsSiU?d^U|eqb8+$QF+RV}6c#pT37GDruJ_4H^nN0o<00000NkvXXu0mjf;F*fx literal 0 HcmV?d00001 diff --git a/pics/32-apps-konqueror.png b/pics/32-apps-konqueror.png new file mode 100644 index 0000000000000000000000000000000000000000..f58ee92251e2c85065563d40c59e6cba4c2b63a5 GIT binary patch literal 2176 zcmV-`2!Hp9P)fTL>=ZwEGc)_eSXLce(b9-V@J95;q@Ls z?gZ>(z%T&y2v8>jc3v_4BO>Y8Wdh;67693g_w73)9Ub+7wf=q+0$wl5TkPQStZ35& z!S;-iJR}!2MoDe}fzWd;b$razo0%!`TVEM~Rd{$*W_fvoU!yT$%;&@TJ2w2X%m$eq z(2M}mAwV_=$VpOC-%v=Qw#o?@h_ax;6JR2f_q;LytL*H&KL@;iGzgvG6zEZ_@S{~r z()iI%;`ay8r3<268^m3ee_V~R9NgYIGuNT*Z9$Y0|>2{++=tkK$Ztw(dRP}nWv)+rz8}9y% z#*BVxfW*XA+d)=#-wq~6g`CPEd_|5b$;nNL57p8DzLxoM@qrsh8k{(BZx|<=hH{%K{HB3w^jM@}s=Rk3H26P|H0idw3 z>~4L1hn3Io3#ip*7>!QobruX*T$q)w!;C`)WL_P@g>Sql75Y)yJYhug z85351ZbHggGggJfw%;$dAhpm8hN}XzMvll_$tVFVm;fM?=^x@LvzTlUD25TfRRbnP z3TC4c%TAebu9G0d0hCDsIMw07vg1a~J1~IvNU?kMh~1~hY*zXD@#m4-HJFr3W90N> z>c`qgO!$n92>>FI=3jWi0)a7D381CV3Fa4aFw4bYR!G1kh%x7Y9w+$(Aq}EjF@{T$ zAb5R2tSzQB&Qu_5vkH^4XvQBZ!KBL(OArf=8Zq;L5uDE~U?S#jodD3{pZXWP(T%fmzan40>dI1!2J=6v#!Z*n&3Q__f z=NtjTvlJ*6Q3e=+MjOy(2f9XqE8-x2%2i_WMj4ouB23$+#uvQ-O%R2_z!4hN@ znNULOPN@z-$SHehOZ<+HzM&eyV$eyOwI$dNBPUBfQi<{Pn$!rN;H20#vi-#b;4G~Zpv02N6V>N5b) z(tV8y5UA|9cUOR!Gv|N#QcDmQ7r*gdQ@4+b6NapIRJ0ks&H;9MO$rq!r@For(EY$qp2#`frRMhF5PB+YEJ30x%WE@0ow;3&ij|cYQ`Q{=G zu+FVOqj(U4E-6Y%YCr`KwY6PXv}k4N3jucQI9RUJ4I*UhS2FkyBruz3CK4lVi|xoQ z8o-uQdK|xIMdkfr@ai3?q=QIc1Vm2Yo^k|T5;OQ6VwCafAg8o;I$d-fKtTbIO~;gH z0&qBsJ`#&{kMNW=H}|5rxEczXj(~qyg6T7UEK~Aq_ngiEiFQKOw7Ff^xouW zWGXpl^KZ7^Jhu+8bT8qxbfNB?Jiob(jX1^%KwtD4Um}l{_liB-S`)jNHjp}zn9%u zv)>p1!-OSpI0?U>J$rFUOiUavEG#mg{l$OPasCT(bw)d|OoA@}0000Xh}ptRCwCW zSqo59SDJ2PCL|=TijP%CbVLz{XoBmgiR*hdzOYaS%z)9c)Ii)AHI(=)1v88qOh!RS zp(qpr0>e|5x5b+hc@6L0en9v36Q;XqAPqE4Z+CzD-`kzRQBlWet$)?WJ$>%I-0%C( zfByfRdpQ6egNw_ekDQzqtY+G;J09!UzTNu|9UWcWJf2+d5QLWaYr)LnA zm2K$j)1#?LjL66g?dsL;pTEumSU5V)+nAhOq^+*zVPL?3pG=|9A|as|d-eq6PM++z z^0gH(Wy*Bt^z@Q0hWsN&f`*ZsTZ@w?!~ZsC&WB%6*p0KdA2;30YtMc!uig9T_b>k6 z1uR~?e051lGX@8TF`99?Qk*#xg;S@({#sc0K-%ALMrC=eh6FfT=hNHoa5xUXGNpq!16OfiT$?RQqG5A5u7&`E`KEg2#k{^UcMYF zrgZv*FfyQ}RfOK&K`_Rb8*nsAf{mAy_&U{s!VVIM(M?9Tg_Z+e;kqG*EipGZV-_rX z*#cOsTer+SJPy0IVQoCq9OE{Mo2QvVS<4$WP`!hXTgXG zdI676osr`jaE!b*=A{Z?0@>U9tJK26dN8Kf8`0R<&bBSY-#0>v9oIA{lK=w%)Woin zm?|0Qsm)@fZv@u9E>hHE2GmCDh)i;iNu_7L_p$`Am^g9zilCtA;o4e0xI8Jvz6ll! za57c~w?C>-r39pdK%3SIt_}PiD|iIze=7LBB#OlRPz}7j{`y}?#FUpMfW^v{+y9iD zTx#j<831G7B+B7I_I~F(IYZ zjFdJr(z#}2@GJ*{zPR%U68^FOAlqkaCt8o=z9L6`CV+Eb zH{O}OYS&W*?A*EM_mPo_N%8TylBA^Kq14n;l$W=mxmm&#EINw7Sah)#;}0vaAXo{X zBpnVU^&s*Ag+iSX(G3*mq%)pIBD&E8uSgAcgsYk3b79v_>(Tp$1}iQq!SNA*vy+ea z{ChF=W8aXc3aF~$577<`8qEOu`wcJ}N9v?pt^toHW!oXy-Iy1s!q@{Hm`S6s{+bFG zD~Az7p1(-~ZZ(;xZAKi8!i5q&)?e<#iVI4tzSN0TL~0Ek*M9prRui^dRbgAWioI^~ z5iv`iqV6&az)=O{=2rbkh3Sdb(V>J`)XBC_CaExHp9GvOJaF6zo&wB1 zE`wikAFkJv2qJ%r5YuWwq7Vqk8o;t|lyEz%z(>KIa66~K`={kt_&C^eAJBCZX?`sU zR^V-45hfj>d9X{0-yE-LApx^T6_A-((PuQ8@gx%nk)8^}xB z`8b-{hiHoZ=r$mR3*6=b2_zzl1Vxg#TXb&ycPcpei7@>u$=@-<|p$9pD%-4re@oRVmgU5pGJU7N5U2xHnw35 z#q4H^`D+anMgkyCNCMh{L@|&=xZ4TriR%T&i;p*V3t?vi$6LS)nDHa=SY;G}#;*TY!7_8rcoJOr}9?Ef3r_ z2^hPQtG0&C_BOox8F_7eGZAPZ@=dV+g8;!5Lx>~d$ug_Qi->f2j}_JZKy;HC&WA;q z>DLasPwD@B(oFXfc5rd7#DFLsa4cVsPr}p)sWKvtexI!ZHlIk$BLP#NS_jDHO`JGw z^SpU({>zqah}^sP^k2`OyEU|I2{sUW2g$ra^QNanMnw& zuyx#hxEj$d?241|Xvoh-jn=UN8t}I=}ij zWu1lnlNF;5@wJ4LIM^oTI$W^%E4G+jTG}KKabtigydQS3RPeQln*fE zM@VxCJo7(-Z?PW3X|9Bo>(Mj>2tb03VAJf;jDF;6fLyK_3l9nL(Rn3OE9Gcv=)m#g z*VIfVdLaRJcJ{O40r>(@>0dx>VkD$W_AuG^&eVgsxP5??mna-NY3K})&)9UcucS#sOe%2{w z!~dcinzyc8xs{uqUV+X|Ertg4NU4y~YO^1CN}wB7s0s3ih>HnQf@}orZ?Wx~c3Ypy zcE5(uLSk~YKx(xLa!TXbS(UhWF&-WsK7W4ENlf0~`DtY(7iDElC@idn*<^u$FGX5S zCrbJOp2bR{k1$BkJw!-73N(b?N3Q1+iu-{02U@g?)o5vM2c>ev#}^_j?2dwxqw7B{ zV9uO*v-9(-6}7bjTV<9bJG+W)x3?=0TPQ|pAHcN{8z7hnW`fbyHa>!38w@r98XNf% zQj$=mVV@xs$PgSH3+Cl=U7Y}Nardxy@3Cx(2D^VsKxk-8%7X`dT4oQyW>na?C@84G z;D7-NxdzDvTx1CiXffNuh?wc|Y#Xq}Jk4L^NP)~sDMS)A_&g~~J}0M&eQsA*FY`Qh zF3gxQ_xH~&z}tJ@){>H@VTnYAN3FcP8T1W-eZ{Eh(xRZG6&clCxI<;v=b{2zPqgD? zq!QQCwaBm2BfW9}DP{dgrhHpS)vZbfv=i})E+D(92YKZJC}e6h)C=(Kw{ghJt7ge- zG=1pq?x$saCt_mq;p5|fpDD7>6fkSnT&L{p%03=XhEa@0f`{wZGbxma1(DIHdXSt^ zjmt6h*n6oRv$oZN^L{Zn3rfLpAvjap=^iGotHRD83X6hv6cjf@spv+xS_dXcoH!AI zs;V}tV>CLbRJ}9;Jxuy$L+QeWJ6N)0L&P%$Y~Sv4y1rhFCv9}hX7<%O>yd*8FT>aO zY)eW?3FT}x`gKFlcK1@Y(ty{YLMau#q#Pci5*v_kmy5hI5o($h5Q)1e{M2lwDJ^NC zSM(A3!-p@nr=^u6KfeZTZ4$=wtN^7_%YbcXWRzpquCrQtdH&&31-Q6;;7%JI9ka!J z*m`^Qv|6pB7>&c`&3^wqY0@0#h3p(hN7p^{4mCe4EKyxt)WEJ_l?pW@hPB$Z2_S zcR$4J58R$P2WHHey(Kz2XMpy~w%wTmH*RF(%P%hv&zrY2l-VUcygnhbV@Uk&cL#1o zL}bvUy8~LHBRo8f4K-?0e8*F2jKco?=X)F+=A5MK|BW!=;pe{l?s&JOM}zA^L(`F& zSqZ6B&5}<@D8SXL$w)~l(%RWg-1b~q$kEZ+Gb}7wos(0`7L>JXcjk;8`;G@abo^+Q zalwLxo9MxomKHG$dmqFUE+SDUm}DRn%5n2%4ta5Z72W@@Pbr?07cE-h9}p1MOHL!l zW#Pz?P}Yfz(fs^z>QpBmhQl)p+4Sj7UY?$ZDkx0O&<&2ydWS!C>darq#pMq-G_=ED zFhj2&W1Qx2k=8gKS!4UeN~y#bD-4*8l*|`|N-D>8-@H zY0jQhBl`F5JtL>S^@O)x$(O@Zr@l|j$*D$9&j69vGoPZUJxEKDI(+_la1TBB-(U29 z)8=di{rQ+7&-{KR0#>cs@}FsGm23vl>8t`Mud_>nHETXC8YxCU53fwX?Ab1^l!=B# zqAvEc6cr}6Acce^QTQwhWir-lEr9I3z`z^w#KbbHu$7eaOA!^7i^GS*FmBxRLrfxg z-35$sc6Rf2b^R#V$!YQVS+hPoKXc{>-#9uh3ZiohUgop@59h6!=diI^WB>pF07*qo IM6N<$f)PEZI{*Lx literal 0 HcmV?d00001 diff --git a/pics/64-apps-konqueror.png b/pics/64-apps-konqueror.png new file mode 100644 index 0000000000000000000000000000000000000000..03233a5a018d8f94360e0009c80c0693683ab264 GIT binary patch literal 6384 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 a;E!a(ygBV|zWw*(C)!_v^rF0vpa1}fs1U~h literal 0 HcmV?d00001 diff --git a/pics/indicators/CMakeLists.txt b/pics/indicators/CMakeLists.txt new file mode 100644 index 0000000..e350184 --- /dev/null +++ b/pics/indicators/CMakeLists.txt @@ -0,0 +1,3 @@ + +install( FILES indicator_connect.png indicator_noconnect.png indicator_empty.png indicator_viewactive.png DESTINATION ${KDE_INSTALL_DATADIR}/konqueror/pics ) + diff --git a/pics/indicators/indicator_connect.png b/pics/indicators/indicator_connect.png new file mode 100644 index 0000000000000000000000000000000000000000..4a73585eed39e98a007a915cb9a022cbe0aecac1 GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4u6ByT*@`3|Hw3p^r=85p=bK$!7qpQa~JkR{#G z*O7r?V_(hhz{xALBTqggYL#{B~-lRJ-Qn0P<= zyH4)^ISun)z2_}U`;66kgwB~C?4PpSY3|Bio{Yzr#l6|{?pR(6dx00002VoOIv0RM-N z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru-2)F4GXo3y@bLfu03CEiSad^g zZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@009(9L_t&-)2)!pNqk5Bq44O2IphAeEW1TKuj&>p)RP=uh4n9Gx z>DufK8~%cYjUcc(uPeo^$AJ@-zG7%|e6-Pgj#NJj`Qm3G_< zc@SR);)^R+vfY|n1hBEOROPGS(56clj~4fk*VR$A(VL1BR>%?KlP>2Z$dm(ZVa2C3 z77biteDi@p^PUMb5bdPWngrv7_#r}+AuoQgElBT3kt9u)JXz8tQS|G9HpugV)6ytX zOfrE&287AE=JO)78&qol`;+ E0Bzna9smFU literal 0 HcmV?d00001 diff --git a/pics/indicators/indicator_viewactive.png b/pics/indicators/indicator_viewactive.png new file mode 100644 index 0000000000000000000000000000000000000000..745a48b9bae950dd3074fdd33f8dea916b4992f1 GIT binary patch literal 643 zcmV-}0(||6P)WFU8GbZ8({Xk{QrNlj4iWF>9@00HMoL_t(2&&`s{YZFlv z#=p)?a_2pXcj_eC)>m~AXh9K|ic%5Lg-e&kO7F1vm5sK>&syXo77wf$9oRJlryKU|zIAu)6RXuCKx!Xsxoem?r<`IBc8 zl#D}w0LB=ay(WCLaOsAlukNnQHF!M3OT{VxNJCiF$kUosnaGy&V39EdY5-Z3(Pdo} z{UWx!E$rKQN2Q5{KS1(WvUMk#YD~HIj=v36RMF}6P;I;T;T7=l_Xb|=zC=}YVS0}3 zXUi{+C3CAEQ)~$=)WX~P5;g(~C8VJ}@KJ5M=t%)IDuU~SQ$ywumI*3~Zbimr1D2-2 zPzXekLmh+>A{0uf1*r=#uGB~1pu{uhuF@-(DZ$oEM0FjqB%#yqgS1+Jz#w`d?EMTc zA1--l>N`Su@F89{BLt={!!~rBr4+Vlz*Gqgi-5hKI;a)=)X1s$7w@1_bv7xF%}ve{ zoyNk55(OX(fd}lpHr$n^T9SQQdw1f8iL=)dXD&n*F3#xpWJ{nOkJrBCo6EnxHd6iU ddJg}E{sMM}!+yRR&qM$K002ovPDHLkV1oD_8&UuO literal 0 HcmV?d00001 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..8b81c99 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,28 @@ + +find_package(Qt5TextToSpeech ${QT_REQUIRED_VERSION} QUIET) +set_package_properties(Qt5TextToSpeech PROPERTIES + PURPOSE "Gives Konqueror a plugin to speak portions or all of a website") + +add_subdirectory( khtmlsettingsplugin ) +add_subdirectory( kimgalleryplugin ) +add_subdirectory( dirfilter ) +# TODO add_subdirectory( uachanger ) +add_subdirectory( babelfish ) + +if (Qt5TextToSpeech_FOUND) + add_subdirectory(ttsplugin) +endif() + +if(UNIX) + add_subdirectory( shellcmdplugin ) +endif(UNIX) + +# TODO add_subdirectory( imagerotation ) +add_subdirectory( autorefresh ) +if(UNIX) + add_subdirectory( fsview ) +endif() +add_subdirectory( searchbar ) + +add_subdirectory( akregator ) + diff --git a/plugins/COPYING b/plugins/COPYING new file mode 100644 index 0000000..5185fd3 --- /dev/null +++ b/plugins/COPYING @@ -0,0 +1,346 @@ +NOTE! The GPL below is copyrighted by the Free Software Foundation, but +the instance of code that it refers to (the kde programs) are copyrighted +by the authors who actually wrote it. + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/COPYING.DOC b/plugins/COPYING.DOC new file mode 100644 index 0000000..4a0fe1c --- /dev/null +++ b/plugins/COPYING.DOC @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/plugins/COPYING.LIB b/plugins/COPYING.LIB new file mode 100644 index 0000000..2d2d780 --- /dev/null +++ b/plugins/COPYING.LIB @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/plugins/README b/plugins/README new file mode 100644 index 0000000..280cd01 --- /dev/null +++ b/plugins/README @@ -0,0 +1,45 @@ +Konqueror Plugins +===================================================================== +This module contains plugins that interact with Konqueror. + +babelfish +------------------- +This works on KHTMLPart/KWebKitPart. It uses Google to +translate the current page to whatever language you want (within +reason). + +dirfilter +------------------- +This works on dolphin part. This allows you to filter the current +directory in a variety of ways. + +khtmlsettingsplugin +------------------- +This works on KHTMLPart. This allows you to enable or disable a bunch +of HTML settings without going through the settings dialog. + +kimgalleryplugin +------------------- +This works on a directory part. It creates an HTML page with thumbnails of +all the images in the current directory. + +uachanger +------------------- +This works on KHTMLPart/KWebKitPart. It allows you to change the user agent +without going through the settings dialog. + +autorefresh +------------------- +This works on any readonly part (though currently it only plugs into +khtmlpart/kwebkitpart). It lets you tell konqueror to refresh a page automatically +after a specific period. This is useful for things like news pages, +and should be very nice for people using kiosk mode. + +fsview +------------------- +Graphical Disk Usage as konqueror plugin for inode/directory, for local files. + +akregator +------------------- +This works on KHTMLPart/KWebKitPart and allows you to add feeds to Akregator directly from Konqueror. + diff --git a/plugins/akregator/CMakeLists.txt b/plugins/akregator/CMakeLists.txt new file mode 100644 index 0000000..8b58055 --- /dev/null +++ b/plugins/akregator/CMakeLists.txt @@ -0,0 +1,39 @@ + +ecm_qt_declare_logging_category(akregatorplugin_DEBUG_SRCS HEADER akregatorplugindebug.h IDENTIFIER AKREGATORPLUGIN_LOG CATEGORY_NAME org.kde.konqueror.akregatorplugin) + +########### next target ############### + +set(akregatorplugin_PART_SRCS akregatorplugin.cpp pluginutil.cpp ) + +kcoreaddons_add_plugin(akregatorplugin SOURCES ${akregatorplugin_PART_SRCS} ${akregatorplugin_DEBUG_SRCS} INSTALL_NAMESPACE "kf5/kfileitemaction") +kcoreaddons_desktop_to_json(akregatorplugin akregator_konqplugin.desktop) + +target_compile_definitions(akregatorplugin PRIVATE TRANSLATION_DOMAIN="akregator_konqplugin") +target_link_libraries(akregatorplugin KF5::I18n KF5::KIOWidgets Qt5::DBus) + +########### next target ############### + +set(akregatorkonqfeedicon_PART_SRCS konqfeedicon.cpp feeddetector.cpp pluginutil.cpp ) + +add_library(akregatorkonqfeedicon MODULE ${akregatorkonqfeedicon_PART_SRCS} ${akregatorplugin_DEBUG_SRCS}) + +target_compile_definitions(akregatorkonqfeedicon PRIVATE TRANSLATION_DOMAIN="akregator_konqplugin") +target_link_libraries(akregatorkonqfeedicon KF5::Parts KF5::IconThemes) + +install(TARGETS akregatorkonqfeedicon DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + +########### install files ############### + +install( FILES akregator_konqplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) +install( FILES akregator_konqfeedicon.desktop akregator_konqfeedicon.rc DESTINATION ${KDE_INSTALL_DATADIR}/khtml/kpartplugins ) +install( FILES akregator_konqfeedicon.desktop akregator_konqfeedicon.rc DESTINATION ${KDE_INSTALL_DATADIR}/kwebkitpart/kpartplugins ) +install( FILES akregator_konqfeedicon.desktop akregator_konqfeedicon.rc DESTINATION ${KDE_INSTALL_DATADIR}/webenginepart/kpartplugins ) + +install( FILES feed.png DESTINATION ${KDE_INSTALL_DATADIR}/akregator/pics ) + +# contains list of debug categories, for kdebugsettings +if (${ECM_VERSION} STRGREATER "5.58.0") + install(FILES akregatorplugin.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) +else() + install(FILES akregatorplugin.categories DESTINATION ${KDE_INSTALL_CONFDIR}) +endif() diff --git a/plugins/akregator/Messages.sh b/plugins/akregator/Messages.sh new file mode 100644 index 0000000..1faabec --- /dev/null +++ b/plugins/akregator/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/akregator_konqplugin.pot diff --git a/plugins/akregator/akregator_konqfeedicon.desktop b/plugins/akregator/akregator_konqfeedicon.desktop new file mode 100644 index 0000000..e94a64a --- /dev/null +++ b/plugins/akregator/akregator_konqfeedicon.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +Name=Konqueror Feed Icon +Name[ar]=أيقونة تغذية الكونكيور +Name[ast]=Iconu de feeds de Konqueror +Name[bg]=Икона за емисия в Konqueror +Name[bs]=Ikona dovoda K‑osvajača +Name[ca]=Icona de font del Konqueror +Name[ca@valencia]=Icona de font del Konqueror +Name[cs]=Ikona kanálu v Konqueroru +Name[da]=Feed-ikon til Konqueror +Name[de]=Symbol für RSS-Quellen in Konqueror +Name[el]=Εικονίδιο ροής του Konqueror +Name[en_GB]=Konqueror Feed Icon +Name[es]=Icono de fuentes de Konqueror +Name[et]=Konquerori uudistevoo ikoon +Name[eu]=Konqueror jario ikonoa +Name[fi]=Konquerorin syötekuvake +Name[fr]=Icône de flux Konqueror +Name[ga]=Deilbhín Fotha Konqueror +Name[gl]=Icona de fonte de Konqueror +Name[he]=אייקון הזנה של Konqueror +Name[hne]=कान्करर फीड चिनहा +Name[hr]=Konquerorova ikona za kanale +Name[hu]=Konqueror hírforrás-ikon +Name[ia]=Icone de syndication de Konqueror +Name[id]=Ikon Feed Konqueror +Name[is]=Fréttastraumstáknmynd fyrir Konqueror +Name[it]=Icona fonti di Konqueror +Name[ja]=Konqueror フィードアイコン +Name[kk]=Konqueror ақпарының таңбашасы +Name[km]=រូប​តំណាង​មតិ​ព័ត៌មាន Konqueror +Name[ko]=Konqueror 피드 아이콘 +Name[ku]=Îkona Çavkanî ya Konqueror +Name[lt]=Konqueror kanalo piktograma +Name[lv]=Konqueror barotņu ikona +Name[mr]=कॉन्करर फीड चिन्ह +Name[nb]=Konqueror kildeikon +Name[nds]=Stroomlüttbild för Konqueror +Name[nl]=Konqueror Feed-pictogram +Name[nn]=Konqueror-kjeldeikon +Name[oc]=Icòna de flus de Konqueror +Name[pa]=ਕੋਨਕਿਊਰੋਰ ਫੀਡ ਆਈਕਾਨ +Name[pl]=Ikona kanału Konquerora +Name[pt]=Ícone de Fonte do Konqueror +Name[pt_BR]=Ícone de fontes do Konqueror +Name[ro]=Pictogramă flux Konqueror +Name[ru]=Значок ленты новостей в Konqueror +Name[sk]=Ikona kanálu v Konqueroru +Name[sl]=Ikona vira novic za Konqueror +Name[sr]=Иконица довода К‑освајача +Name[sr@ijekavian]=Иконица довода К‑освајача +Name[sr@ijekavianlatin]=Ikonica dovoda K‑osvajača +Name[sr@latin]=Ikonica dovoda K‑osvajača +Name[sv]=Konqueror-kanalikon +Name[tg]=Нишонаи ахбороти Konqueror +Name[th]=ภาพไอคอนแหล่งป้อนของ Konqueror +Name[tr]=Konqueror Haber Kaynağı Simgesi +Name[ug]=Konqueror خەۋەر مەنبە سىنبەلگىسى +Name[uk]=Піктограма подач для Konqueoror +Name[wa]=Imådjete di floû po Konqueror +Name[x-test]=xxKonqueror Feed Iconxx +Name[zh_CN]=Konqueror 种子图标 +Name[zh_TW]=Konqueror Feed 圖示 +Icon=akregator +Comment=Displays an icon in the status bar if the page contains a feed +Comment[ar]=تعرض أيقونة في شريط الحالة إذا كانت الصفحة تحوي تغذية +Comment[ast]=Amuesa un iconu na barra d'estáu si la páxina contién un feed +Comment[bg]=Показване на икона в лентата за състояние, когато страницата съдържа емисия +Comment[bs]=Ako stranica sadrži dovod, ikona se prikazuje u traci stanja +Comment[ca]=Mostra una icona a la barra d'estat si la pàgina conté una font d'informació +Comment[ca@valencia]=Mostra una icona a la barra d'estat si la pàgina conté una font d'informació +Comment[cs]=Pokud stránka obsahuje kanál, zobrazí ikonu ve stavovém panelu +Comment[da]=Viser et ikon i statuslinjen hvis siden indeholder et feed +Comment[de]=Zeigt das RSS-Symbol in der Statusleiste, wenn die Seite eine RSS-Quelle enthält +Comment[el]=Εμφανίζει ένα εικονίδιο στη γραμμή κατάστασης όταν η σελίδα περιέχει μια ροή +Comment[en_GB]=Displays an icon in the status bar if the page contains a feed +Comment[es]=Muestra un icono en la barra de estado si la página contiene una fuente RSS +Comment[et]=Näitab olekuribal ikooni, kui lehekülg sisaldab uudistevoogu +Comment[eu]=Egoera-barran ikono bat bistaratzen du orriak jario bat daukanean +Comment[fi]=Näyttää kuvakkeen tilarivillä, jos sivulle on olemassa syöte +Comment[fr]=Affiche une icône dans la barre d'état quand la page contient un flux +Comment[ga]=Taispeáin deilbhín sa bharra stádais nuair atá fotha ar an leathanach +Comment[gl]=Mostra unha icona na barra de estado se a páxina contén unha fonte +Comment[he]=הצג אייקון בשורת המצב אם הדף מכיל הזנה +Comment[hr]=Prikaži ikonu u statusnoj traci ako stranica sadrži kanal +Comment[hu]=Megjelenít egy ikont az állapotsorban, ha az oldal tartalmaz hírforrást +Comment[ia]=Monstra un icone in le barra de stato si le pagina contine un syndication +Comment[id]=Menampilkan sebuah ikon di statusbar jika halaman berisi sebuah feed +Comment[is]=Birtir táknmynd í stöðuslá ef síðan innigeldur fréttastraum (feed) +Comment[it]=Mostra un'icona nella barra di stato se la pagina contiene una fonte +Comment[ja]=フィードを含むページでステータスバーにフィードアイコンを表示します +Comment[kk]=Бетте ақпар бар болса, күй-жай жолағында таңбашасы көрсетіледі +Comment[km]=បង្ហាញ​រូប​តំណាង​ក្នុង​របារ​ស្ថានភាព ប្រសិន​បើ​​ទំព័រ​មាន​មតិ​ព័ត៌មាន +Comment[ko]=페이지에 RSS 피드가 들어 있을 때 상태 표시줄에 아이콘 표시 +Comment[lt]=Rodo kanalo piktogramą statuso eilutėje, jei puslapyje yra naujienų kanalas. +Comment[lv]=Parāda ikonu statusa joslā, ja lapa satur barotni +Comment[mr]=जर पाना फीड समाविष्ट असेल तर स्थितीपट्टीत चिन्ह दर्शवितो +Comment[nb]=Viser et ikon i statuslinja hvis det er en kilde på siden +Comment[nds]=Wiest en Lüttbild op den Statusbalken, wenn de Siet en Narichtenstroom bargt. +Comment[nl]=Toont een pictogram in de statusbalk als de pagina een feed bevat +Comment[nn]=Viser eit ikon i statuslinja dersom det finst ei tilhøyrande kjelde +Comment[pa]=ਜੇ ਪੇਜ਼ ਲਈ ਫੀਡ ਹੋਵੇ ਤਾਂ ਹਾਲਤ-ਪੱਟੀ ਵਿੱਚ ਇੱਕ ਆਈਕਾਨ ਵੇਖਾਓ +Comment[pl]=Wyświetla ikonę na pasku stanu, jeżeli strona zawiera kanał +Comment[pt]=Mostra um ícone na barra de estado se a página tiver uma fonte +Comment[pt_BR]=Exibe um ícone na barra de status se a página possui uma fonte de notícias +Comment[ro]=Afișează o pictogramă în bara de stare dacă pagina conține un flux +Comment[ru]=Отображает значок в строке состояния если текущая страница содержит ленту новостей +Comment[sk]=Pokiaľ stránka obsahuje kanál, zobrazí ikonu v stavovej lište +Comment[sl]=V vrstici stanja prikaže ikono, če stran vsebuje vir novic +Comment[sr]=Ако страница садржи довод, иконица се приказује у траци стања +Comment[sr@ijekavian]=Ако страница садржи довод, иконица се приказује у траци стања +Comment[sr@ijekavianlatin]=Ako stranica sadrži dovod, ikonica se prikazuje u traci stanja +Comment[sr@latin]=Ako stranica sadrži dovod, ikonica se prikazuje u traci stanja +Comment[sv]=Visar en ikon i statusraden om sidan innehåller en kanal +Comment[tg]=Агар ахборот дорад, ин нишона дар навори ҳолат пайдо мешавад +Comment[th]=แสดงภาพไอคอนไว้ในแถบสถานะ หากหน้าเว็บมีส่วนป้อนหัวข้อบทความ +Comment[tr]=Sayfa bir RSS haber kaynağı içeriyorsa durum çubuğunda bir simge gösterir +Comment[ug]=ئەگەر بەتتە خەۋەر مەنبەسى بولسا ھالەت بالداقتا بىر سىنبەلگە كۆرسىتىدۇ +Comment[uk]=Показує піктограму у рядку стану, якщо сторінка містить подачу +Comment[wa]=Håyene ene imådjete el bår ås messaedjes s' i gn a on floû el pådje +Comment[x-test]=xxDisplays an icon in the status bar if the page contains a feedxx +Comment[zh_CN]=如果页面上包含种子,就在状态栏上显示一个图标 +Comment[zh_TW]=如果頁面中有 RSS feed,則在狀態列中顯示圖示 +Type=Service +X-KDE-Library=akregatorkonqfeedicon +X-KDE-PluginInfo-Author=Teemu Rytilahti +X-KDE-PluginInfo-Email=tpr@d5k.net +X-KDE-PluginInfo-Name=konqfeedicon +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-Website=https://akregator.kde.org/ +X-KDE-PluginInfo-Category=Statusbar +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-ParentApp=konqueror diff --git a/plugins/akregator/akregator_konqfeedicon.rc b/plugins/akregator/akregator_konqfeedicon.rc new file mode 100644 index 0000000..d84677b --- /dev/null +++ b/plugins/akregator/akregator_konqfeedicon.rc @@ -0,0 +1,3 @@ + + + diff --git a/plugins/akregator/akregator_konqplugin.desktop b/plugins/akregator/akregator_konqplugin.desktop new file mode 100644 index 0000000..c4e288e --- /dev/null +++ b/plugins/akregator/akregator_konqplugin.desktop @@ -0,0 +1,133 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KFileItemAction/Plugin +X-KDE-Library=akregatorplugin +MimeType=application/octet-stream +Icon=akregator +Name=Add Feed to Akregator +Name[ar]=أضف التغذية إلى Akregator +Name[ast]=Amiestu de feed a Akregator +Name[be]=Дадаць стужку ў Akregator +Name[bg]=Добавяне на емисия към Akregator +Name[bs]=Dodaj dovod u Akregator +Name[ca]=Afegeix aquesta font a l'Akregator +Name[ca@valencia]=Afig aquesta font a l'Akregator +Name[cs]=Přidat kanál do Akregatoru +Name[da]=Tilføj feed til Akregator +Name[de]=Nachrichtenquelle zu Akregator hinzufügen +Name[el]=Προσθήκη Καναλιού Ειδήσεων στον aKregator +Name[en_GB]=Add Feed to Akregator +Name[eo]=Aldoni fluon al Akregatoro +Name[es]=Añadir una fuente a Akregator +Name[et]=Lisa uudistevoog Akregatorile +Name[eu]=Gehitu jarioa Akregatorri +Name[fi]=Lisää syöte Akregatoriin +Name[fr]=Ajouter un flux à Akregator +Name[ga]=Cuir Fotha le hAkregator +Name[gl]=Engadir a fonte a Akregator +Name[he]=הוסף הזנה ל־Akregator +Name[hne]=फीड ल एकेरेगेटर मं जोड़व +Name[hr]=Dodaj kanal u Akregator +Name[hu]=Hírforrás hozzáadása az Akregatorhoz +Name[ia]=Adde syndication a Akregator +Name[id]=Tambah Feed ke Akregator +Name[is]=Bæta fréttastraumi við Akregator +Name[it]=Aggiungi la fonte ad Akregator +Name[ja]=Akregator にフィードを追加 +Name[kk]=Akregator-ға ақпарды қосу +Name[km]=បន្ថែម​មតិព័ត៌មាន​ទៅ Akregator +Name[ko]=Akregator에 피드 추가하기 +Name[ku]=Lê Akregator Çavkanî Zêde Bike +Name[lt]=Įdėti kanalą į Akregator +Name[lv]=Pievienot barotni Akregator +Name[mr]=एक्रीगेटरला फीड जोडतो +Name[ms]=Tambah Feed ke Akregator +Name[nb]=Legg til kilde i Akregator +Name[nds]=Stroom na Akregator tofögen +Name[nl]=Feed aan aKregator toevoegen +Name[nn]=Legg til kjelda i Akregator +Name[oc]=Apondre lo flus a Akregator +Name[pa]=ਅਕਰੀਗੇਟਰ ਲਈ ਫੀਡ ਸ਼ਾਮਿਲ +Name[pl]=Dodaj kanał do Akregatora +Name[pt]=Adicionar a Fonte ao Akregator +Name[pt_BR]=Adicionar fonte de notícias ao Akregator +Name[ro]=Adaugă flux la Akregator +Name[ru]=Добавить ленту новостей в Akregator +Name[sk]=Pridať kanál do Akregatoru +Name[sl]=Dodaj vir v Akregator +Name[sr]=Додај довод у Акрегатор +Name[sr@ijekavian]=Додај довод у Акрегатор +Name[sr@ijekavianlatin]=Dodaj dovod u Akregator +Name[sr@latin]=Dodaj dovod u Akregator +Name[sv]=Lägg till kanal i Akregator +Name[tg]=Иловаи ахборот ба Агрегатор +Name[th]=เพิ่มแหล่งป้อนไปยัง Akregator +Name[tr]=Haber Kaynağını Akregator uygulamasına ekle +Name[ug]=Akregator غا خەۋەر مەنبە قوش +Name[uk]=Додати подачу в Akregator +Name[wa]=Radjouter floû a Akgregator +Name[x-test]=xxAdd Feed to Akregatorxx +Name[zh_CN]=向 Akregator 添加种子 +Name[zh_TW]=將 Feed 新增到 Akregator +icon=akregator +Comment=Adds selected feed to Akregator +Comment[ar]=تضيف التغذية المختارة إلى Akregator +Comment[ast]=Amiesta'l feed esbilláu a Akregator +Comment[bg]=Добавяне на избраната емисия към четеца Akregator +Comment[bs]=Dodaje izabrani dovod u Akregator +Comment[ca]=Afegeix la font seleccionada a l'Akregator +Comment[ca@valencia]=Afig la font seleccionada a l'Akregator +Comment[cs]=Přidá vybraný kanál do Akregatoru +Comment[da]=Tilføjer det valgte feed til Akregator +Comment[de]=Fügt die ausgewählte Nachrichtenquelle zu Akregator hinzu +Comment[el]=Προσθήκη της επιλεγμένης ροής στο aKregator +Comment[en_GB]=Adds selected feed to Akregator +Comment[es]=Añade la fuente RSS seleccionada a Akregator +Comment[et]=Lisab valitud uudistevoo Akregatorile +Comment[eu]=Hautatutako jarioak gehitzen dizkio Akregatorri +Comment[fi]=Lisää valitun syötteen Akregatoriin +Comment[fr]=Ajoute le flux sélectionné dans Akregator +Comment[ga]=Cuir an fotha roghnaithe le hAkregator +Comment[gl]=Engade a fonte escollida a Akregator +Comment[he]=הוסף הזנות נבחרות ל־Akregator +Comment[hne]=चुने गे आरएसएस फीड ल एकेरेगेटर मं जोड़थे +Comment[hr]=Dodaj odabrani kanal u Akregator +Comment[hu]=A kiválasztott hírforrások hozzáadása az Akregatorhoz +Comment[ia]=Adde syndication seligite a Akregator +Comment[id]=Tambah feed terpilih ke Akregator +Comment[is]=Bæta völdum fréttastraumi við Akregator +Comment[it]=Aggiunge la fonte RSS selezionata ad Akregator +Comment[ja]=選択したフィードを Akregator に追加します +Comment[kk]=Akregator-ға таңдалған ақпарды қосу +Comment[km]=បន្ថែម​មតិព័ត៌មាន​ដែលបាន​ជ្រើស​ទៅ Akregator +Comment[ko]=선택한 RSS 피드를 Akregator에 추가하기 +Comment[ku]=Lê Akregator çavkaniya hilbijartî zêde bike +Comment[lt]=Įdėti pasirinktą kanalą į Akregator +Comment[lv]=Pievieno izvēlēto barotni Akregator +Comment[mr]=एक्रीगेटरला निवडलेले फीड जोडतो +Comment[nb]=Legger til den valgte kilden til Akregator +Comment[nds]=Föögt den utsöchten Narichtenstroom na Akregator to +Comment[nl]=Voegt geselecteerde feeds toe aan aKregator +Comment[nn]=Legg til den valde kjelda i Akregator +Comment[pa]=ਚੁਣੀ ਫੀਡ ਅਕਰੀਗੇਟਰ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ +Comment[pl]=Dodaje wybrany kanał do Akregatora +Comment[pt]=Adiciona a fonte seleccionada ao Akregator +Comment[pt_BR]=Adiciona a fonte selecionada ao Akregator +Comment[ro]=Adaugă fluxul selectat la Akregator +Comment[ru]=Добавляет выбранную ленту новостей в Akregator +Comment[sk]=Pridá vybraný kanál do Akregatoru +Comment[sl]=Doda izbran vir v Akregator +Comment[sr]=Додаје изабрани довод у Акрегатор +Comment[sr@ijekavian]=Додаје изабрани довод у Акрегатор +Comment[sr@ijekavianlatin]=Dodaje izabrani dovod u Akregator +Comment[sr@latin]=Dodaje izabrani dovod u Akregator +Comment[sv]=Lägger till vald kanal i Akregator +Comment[tg]=Ахбороти интихобшударо ба Агрегатор илова мекунад +Comment[th]=เพิ่มแหล่งป้อนที่เลือกไว้ไปยัง Akregator +Comment[tr]=Seçili RSS haber kaynağını Akregator uygulamasına ekler +Comment[ug]=Akregator تاللانغان خەۋەر مەنبەسىنى قوشىدۇ +Comment[uk]=Додає вибрану подачу у Akregator +Comment[wa]=Radjoute floû tchoezi a Akgregator +Comment[x-test]=xxAdds selected feed to Akregatorxx +Comment[zh_CN]=向 Akregator 添加选中的种子 +Comment[zh_TW]=將所選取的 RSS feed 加到 Akregator diff --git a/plugins/akregator/akregatorplugin.categories b/plugins/akregator/akregatorplugin.categories new file mode 100644 index 0000000..fe909c8 --- /dev/null +++ b/plugins/akregator/akregatorplugin.categories @@ -0,0 +1 @@ +org.kde.konqueror.akregatorplugin akregator feed plugin (akregator) IDENTIFIER [AKREGATORPLUGIN_LOG] diff --git a/plugins/akregator/akregatorplugin.cpp b/plugins/akregator/akregatorplugin.cpp new file mode 100644 index 0000000..4a4f343 --- /dev/null +++ b/plugins/akregator/akregatorplugin.cpp @@ -0,0 +1,121 @@ +/* This file is part of the KDE project + + Copyright (C) 2004 Gary Cramblitt + + Adapted from kdeutils/ark/konqplugin by + Georg Robbers + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "akregatorplugin.h" + +#include "pluginutil.h" +#include "akregatorplugindebug.h" + +#include +#include +#include +#include + +#include +#include + +using namespace Akregator; + +K_PLUGIN_FACTORY_WITH_JSON(AkregatorMenuFactory, "akregator_konqplugin.json", registerPlugin();) + +AkregatorMenu::AkregatorMenu(QObject *parent, const QVariantList &args) + : KAbstractFileItemActionPlugin(parent) +{ + Q_UNUSED(args); + +#if 0 + if (QByteArray(kapp->name()) == "kdesktop" && !KAuthorized::authorizeKAction("editable_desktop_icons")) { + return; + } +#endif + // Do nothing if user has turned us off. + // TODO: Not yet implemented in aKregator settings. + + /* + m_conf = new KConfig( "akregatorrc" ); + m_conf->setGroup( "AkregatorKonqPlugin" ); + if ( !m_conf->readEntry( "Enable", true ) ) + return; + */ + + m_feedMimeTypes << "application/rss+xml" << "text/rdf" << "application/xml"; +} + + +QList AkregatorMenu::actions(const KFileItemListProperties &fileItemInfos, QWidget *parent) +{ + Q_UNUSED(parent); + + QList acts; + const KFileItemList items = fileItemInfos.items(); + foreach (const KFileItem &item, items) { + if (isFeedUrl(item)) { + qCDebug(AKREGATORPLUGIN_LOG) << "found feed" << item.url(); + + QAction *action = new QAction(this); + action->setText(i18nc("@action:inmenu", "Add Feed to Akregator")); + action->setIcon(QIcon::fromTheme("akregator")); + action->setData(item.url()); + connect(action, &QAction::triggered, this, &AkregatorMenu::slotAddFeed); + acts.append(action); + } + } + + return acts; +} + + +static bool isFeedUrl(const QString &urlPath) +{ + // If URL ends in .htm or .html, it is not a feed url. + if (urlPath.endsWith(".htm", Qt::CaseInsensitive) || urlPath.endsWith(".html", Qt::CaseInsensitive)) { + return false; + } + if (urlPath.contains("rss", Qt::CaseInsensitive)) { + return true; + } + if (urlPath.contains("rdf", Qt::CaseInsensitive)) { + return true; + } + return false; +} + +bool AkregatorMenu::isFeedUrl(const KFileItem &item) const +{ + if (m_feedMimeTypes.contains(item.mimetype())) { + return true; + } else { + return ::isFeedUrl(item.url().path()); + } + return false; +} + +void AkregatorMenu::slotAddFeed() +{ + QAction *action = qobject_cast(sender()); + Q_ASSERT(action!=nullptr); + + QString url = action->data().toUrl().url(); + qCDebug(AKREGATORPLUGIN_LOG) << "for feed url" << url; + PluginUtil::addFeeds(QStringList(url)); +} + +#include "akregatorplugin.moc" diff --git a/plugins/akregator/akregatorplugin.h b/plugins/akregator/akregatorplugin.h new file mode 100644 index 0000000..2bd5694 --- /dev/null +++ b/plugins/akregator/akregatorplugin.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + + Copyright (C) 2004 Gary Cramblitt + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _AKREGATORPLUGIN_H_ +#define _AKREGATORPLUGIN_H_ + +#include + +class KFileItem; +class KFileItemListProperties; + +namespace Akregator +{ + +class AkregatorMenu : public KAbstractFileItemActionPlugin +{ + Q_OBJECT + +public: + AkregatorMenu(QObject *parent, const QVariantList &args); + ~AkregatorMenu() override = default; + + QList actions(const KFileItemListProperties &fileItemInfos, QWidget *parent) override; + +public slots: + void slotAddFeed(); + +private: + bool isFeedUrl(const KFileItem &item) const; + +private: + QStringList m_feedMimeTypes; +}; + +} + +#endif diff --git a/plugins/akregator/feed.png b/plugins/akregator/feed.png new file mode 100644 index 0000000000000000000000000000000000000000..b5ba4cd3fe36d4a38cf75d2a5f17934fe1a89644 GIT binary patch literal 930 zcmV;T16}-yP)6q zlN6XJHd2TUpt08w`%oMn0t8>;ecZFZg`c0PTMZ8WJVUR26>fVRNmAVMCA9N9l4jW2 z1hQv1%A}ADE)AeJrTxO9&mCvc(8DSUn_cvJhsu$6%QM_2`qvEZhqsZ=63KWIiAf{n zkKIlPWhx(KF{wiptSYc|4bgx*`w|))vhOgac^7i%LDGp+xF6r4clk7F^HxL*$l$Gr z>0+V~WiA&+oXf?EVijO>17id?`)M56AE)ugU?yAGBPXyAzl9Se%zZ^NUW+1;^4bPK zLzMbZjx(3t#G!z6Ur#g}A7;x#`r<579U(0LN|>F-U;GToMoEvIgFUz4rXR&-n@FV! zGLTLSnQ9dHKB0HeU1wwApJJqL4SE2IcIGh$rgCI*3irjcxHHdVpZ z6Bae>fZvWH#Yk;}5zp3#2SGp%Jb-=d1j+43(YdejzkQ6(pF<`eLB&GV0ev#vMI?Qg z1SMb;g}pUQ3TEP7lKWpqS7&kGz6OA~;{`Af7H1HfA@##(0#y5`6r_ONfrQ+ls>Mi$ zYPj_!(x*O0Mh=01|M>%S^&)29-MLU#E&w2ndkF1cNU8w4B^pR?qC;6K5)Rcd7Q&^I zXlD++dOmKdjG#Bx^ImKU5c{-DR;DO0h0qj8K~_frSvziYwDlyqa2~(DKnP&>lGm^m zKQberTc81?3bq-g+tRtdI@nkCLt~2ecPFuAwM8dm4Li}oHZ~wBB(WCH14x1Hazp(< zHN!X^LxyUL(mrmVlWgog?XEUZ1wi?qmq;$t>uaz63lF-smblt~hyVZp07*qoM6N<$ Eg23sTwEzGB literal 0 HcmV?d00001 diff --git a/plugins/akregator/feed.svg b/plugins/akregator/feed.svg new file mode 100644 index 0000000..aebba7b --- /dev/null +++ b/plugins/akregator/feed.svg @@ -0,0 +1,645 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/akregator/feeddetector.cpp b/plugins/akregator/feeddetector.cpp new file mode 100644 index 0000000..b4f1bce --- /dev/null +++ b/plugins/akregator/feeddetector.cpp @@ -0,0 +1,148 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "feeddetector.h" +#include +#include +#include + +#include + +#include "akregatorplugindebug.h" + +using namespace Akregator; + +FeedDetectorEntryList FeedDetector::extractFromLinkTags(const QString &s) +{ + //reduce all sequences of spaces, newlines etc. to one space: + QString str = s.simplified(); + + // extracts tags + QRegExp reLinkTag("<[\\s]?LINK[^>]*REL[\\s]?=[\\s]?\\\"[^\\\"]*(ALTERNATE|FEED|SERVICE\\.FEED)[^\\\"]*\\\"[^>]*>", Qt::CaseInsensitive); + + // extracts the URL (href="url") + QRegExp reHref("HREF[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", Qt::CaseInsensitive); + // extracts type attribute + QRegExp reType("TYPE[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", Qt::CaseInsensitive); + // extracts the title (title="title") + QRegExp reTitle("TITLE[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", Qt::CaseInsensitive); + + int pos = 0; + int matchpos = 0; + + // get all tags + QStringList linkTags; + //int strlength = str.length(); + while (matchpos != -1) { + matchpos = reLinkTag.indexIn(str, pos); + if (matchpos != -1) { + linkTags.append(str.mid(matchpos, reLinkTag.matchedLength())); + pos = matchpos + reLinkTag.matchedLength(); + } + } + + FeedDetectorEntryList list; + + for (QStringList::Iterator it = linkTags.begin(); it != linkTags.end(); ++it) { + QString type; + int pos = reType.indexIn(*it, 0); + if (pos != -1) { + type = reType.cap(1).toLower(); + } + + // we accept only type attributes indicating a feed + if (type != QLatin1String("application/rss+xml") && type != QLatin1String("application/rdf+xml") + && type != QLatin1String("application/atom+xml") && type != QLatin1String("application/xml")) { + continue; + } + + QString title; + pos = reTitle.indexIn(*it, 0); + if (pos != -1) { + title = reTitle.cap(1); + } + + title = KCharsets::resolveEntities(title); + + QString url; + pos = reHref.indexIn(*it, 0); + if (pos != -1) { + url = reHref.cap(1); + } + + url = KCharsets::resolveEntities(url); + + // if feed has no title, use the url as preliminary title (until feed is parsed) + if (title.isEmpty()) { + title = url; + } + + if (!url.isEmpty()) { + qCDebug(AKREGATORPLUGIN_LOG) << "found feed:" << url << title; + list.append(FeedDetectorEntry(url, title)); + } + } + + return list; +} + +QStringList FeedDetector::extractBruteForce(const QString &s) +{ + QString str = s.simplified(); + + QRegExp reAhrefTag("<[\\s]?A[^>]?HREF=[\\s]?\\\"[^\\\"]*\\\"[^>]*>", Qt::CaseInsensitive); + + // extracts the URL (href="url") + QRegExp reHref("HREF[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", Qt::CaseInsensitive); + + QRegExp rssrdfxml(".*(RSS|RDF|XML)", Qt::CaseInsensitive); + + int pos = 0; + int matchpos = 0; + + // get all tags and capture url + QStringList list; + //int strlength = str.length(); + while (matchpos != -1) { + matchpos = reAhrefTag.indexIn(str, pos); + if (matchpos != -1) { + QString ahref = str.mid(matchpos, reAhrefTag.matchedLength()); + int hrefpos = reHref.indexIn(ahref, 0); + if (hrefpos != -1) { + QString url = reHref.cap(1); + + url = KCharsets::resolveEntities(url); + + if (rssrdfxml.exactMatch(url)) { + list.append(url); + } + } + + pos = matchpos + reAhrefTag.matchedLength(); + } + } + + return list; + +} diff --git a/plugins/akregator/feeddetector.h b/plugins/akregator/feeddetector.h new file mode 100644 index 0000000..45d090c --- /dev/null +++ b/plugins/akregator/feeddetector.h @@ -0,0 +1,83 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef AKREGATORFEEDDETECTOR_H +#define AKREGATORFEEDDETECTOR_H + +#include +#include + +class QStringList; + +namespace Akregator +{ + +class FeedDetectorEntry +{ +public: + FeedDetectorEntry() {} + FeedDetectorEntry(const QString &url, const QString &title) + : m_url(url), m_title(title) {} + + const QString &url() const + { + return m_url; + } + const QString &title() const + { + return m_title; + } + +private: + QString m_url; + QString m_title; +}; + +typedef QList FeedDetectorEntryList; + +/** a class providing functions to detect linked feeds in HTML sources */ +class FeedDetector +{ +public: + /** \brief searches an HTML page for feeds listed in @c tags + @c tags with @c rel attribute values @c alternate or + @c service.feed are considered as feeds + @param s the html source to scan (the actual source, no URI) + @return a list containing the detected feeds + */ + static FeedDetectorEntryList extractFromLinkTags(const QString &s); + + /** \brief searches an HTML page for slightly feed-like looking links and catches everything not running away quickly enough. + Extracts links from @c tags which end with @c xml, @c rss or @c rdf + @param s the html source to scan (the actual source, no URI) + @return a list containing the detected feeds + */ + static QStringList extractBruteForce(const QString &s); + +private: + FeedDetector() {} +}; +} + +#endif //AKREGATORFEEDDETECTOR_H diff --git a/plugins/akregator/konqfeedicon.cpp b/plugins/akregator/konqfeedicon.cpp new file mode 100644 index 0000000..dc0c0d6 --- /dev/null +++ b/plugins/akregator/konqfeedicon.cpp @@ -0,0 +1,220 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "konqfeedicon.h" + +#include "feeddetector.h" +#include "pluginutil.h" +#include "akregatorplugindebug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace Akregator; + +K_PLUGIN_FACTORY(KonqFeedIconFactory, registerPlugin();) + +static QUrl baseUrl(KParts::ReadOnlyPart *part) +{ + QUrl url; + KParts::HtmlExtension *ext = KParts::HtmlExtension::childObject(part); + if (ext) { + url = ext->baseUrl(); + } + return url; +} + +KonqFeedIcon::KonqFeedIcon(QObject *parent, const QVariantList &args) + : KParts::Plugin(parent), + m_part(nullptr), + m_feedIcon(nullptr), + m_statusBarEx(nullptr), + m_menu(nullptr) +{ + Q_UNUSED(args); + + // make our icon foundable by the KIconLoader + KIconLoader::global()->addAppDir(QStringLiteral("akregator")); + + KParts::ReadOnlyPart *part = qobject_cast(parent); + if (part) { + KParts::HtmlExtension *ext = KParts::HtmlExtension::childObject(part); + KParts::SelectorInterface *selectorInterface = qobject_cast(ext); + if (selectorInterface) { + m_part = part; + connect(m_part, QOverload<>::of(&KParts::ReadOnlyPart::completed), this, &KonqFeedIcon::addFeedIcon); + connect(m_part, QOverload::of(&KParts::ReadOnlyPart::completed), this, &KonqFeedIcon::addFeedIcon); + connect(m_part, &KParts::ReadOnlyPart::started, this, &KonqFeedIcon::removeFeedIcon); + } + } +} + +KonqFeedIcon::~KonqFeedIcon() +{ + m_statusBarEx = KParts::StatusBarExtension::childObject(m_part); + if (m_statusBarEx) { + m_statusBarEx->removeStatusBarItem(m_feedIcon); + // if the statusbar extension is deleted, the icon is deleted as well (being the child of the status bar) + delete m_feedIcon; + } + // the icon is deleted in every case + m_feedIcon = nullptr; + delete m_menu; + m_menu = nullptr; +} + +bool KonqFeedIcon::feedFound() +{ + // Ensure that it is safe to use the URL, before doing anything else with it + const QUrl partUrl(m_part->url()); + if (!partUrl.isValid()) { + return false; + } + // Since attempting to determine feed info for about:blank crashes khtml, + // lets prevent such look up for local urls (about, file, man, etc...) + if (KProtocolInfo::protocolClass(partUrl.scheme()).compare(QLatin1String(":local"), Qt::CaseInsensitive) == 0) { + return false; + } + + KParts::HtmlExtension *ext = KParts::HtmlExtension::childObject(m_part); + KParts::SelectorInterface *selectorInterface = qobject_cast(ext); + QString doc; + if (selectorInterface) { + QList linkNodes = selectorInterface->querySelectorAll(QStringLiteral("head > link[rel=\"alternate\"]"), KParts::SelectorInterface::EntireContent); + for (int i = 0; i < linkNodes.count(); i++) { + const KParts::SelectorInterface::Element element = linkNodes.at(i); + + // TODO parse the attributes directly here, rather than re-assembling + // and then re-parsing in extractFromLinkTags! + doc += QLatin1String(""); + } + qCDebug(AKREGATORPLUGIN_LOG) << doc; + } + + m_feedList = FeedDetector::extractFromLinkTags(doc); + return m_feedList.count() != 0; +} + +void KonqFeedIcon::contextMenu() +{ + delete m_menu; + m_menu = new QMenu(m_part->widget()); + if (m_feedList.count() == 1) { + m_menu->setTitle(m_feedList.first().title()); + m_menu->addAction(QIcon::fromTheme("bookmark-new"), i18n("Add Feed to Akregator"), this, SLOT(addAllFeeds())); + } else { + m_menu->setTitle(i18n("Add Feeds to Akregator")); + int id = 0; + for (FeedDetectorEntryList::Iterator it = m_feedList.begin(); it != m_feedList.end(); ++it) { + QAction *action = m_menu->addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), (*it).title(), this, SLOT(addFeed())); + action->setData(QVariant::fromValue(id)); + id++; + } + //disconnect(m_menu, SIGNAL(activated(int)), this, SLOT(addFeed(int))); + m_menu->addSeparator(); + m_menu->addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), i18n("Add All Found Feeds to Akregator"), this, SLOT(addAllFeeds())); + } + m_menu->popup(QCursor::pos()); +} + +void KonqFeedIcon::addFeedIcon() +{ + if (!feedFound() || m_feedIcon) { + return; + } + + m_statusBarEx = KParts::StatusBarExtension::childObject(m_part); + if (!m_statusBarEx) { + return; + } + + m_feedIcon = new KUrlLabel(m_statusBarEx->statusBar()); + + // from khtmlpart's ualabel + m_feedIcon->setFixedHeight(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize)); + m_feedIcon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + m_feedIcon->setUseCursor(false); + + m_feedIcon->setPixmap(KIconLoader::global()->loadIcon(QStringLiteral("feed"), KIconLoader::User)); + m_feedIcon->setToolTip(i18n("Subscribe to site updates (using news feed)")); + + m_statusBarEx->addStatusBarItem(m_feedIcon, 0, true); + + connect(m_feedIcon, QOverload<>::of(&KUrlLabel::leftClickedUrl), this, &KonqFeedIcon::contextMenu); +} + +void KonqFeedIcon::removeFeedIcon() +{ + m_feedList.clear(); + if (m_feedIcon && m_statusBarEx) { + m_statusBarEx->removeStatusBarItem(m_feedIcon); + delete m_feedIcon; + m_feedIcon = nullptr; + } + + // Close the popup if it's open, otherwise we crash + delete m_menu; + m_menu = nullptr; +} + +void KonqFeedIcon::addFeed() +{ + bool ok = false; + const int id = sender() ? qobject_cast(sender())->data().toInt(&ok) : -1; + if (!ok || id == -1) { + return; + } + PluginUtil::addFeeds(QStringList(PluginUtil::fixRelativeURL(m_feedList[id].url(), baseUrl(m_part)))); +} + +// from akregatorplugin.cpp +void KonqFeedIcon::addAllFeeds() +{ + QStringList list; + foreach (const FeedDetectorEntry &it, m_feedList) { + list.append(PluginUtil::fixRelativeURL(it.url(), baseUrl(m_part))); + } + PluginUtil::addFeeds(list); +} + +#include "konqfeedicon.moc" diff --git a/plugins/akregator/konqfeedicon.h b/plugins/akregator/konqfeedicon.h new file mode 100644 index 0000000..1306a4b --- /dev/null +++ b/plugins/akregator/konqfeedicon.h @@ -0,0 +1,77 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KONQFEEDICON_H +#define KONQFEEDICON_H + +#include +#include +#include +#include "feeddetector.h" + +/** +@author Teemu Rytilahti +*/ +class KUrlLabel; + +namespace KParts +{ +class StatusBarExtension; +class ReadOnlyPart; +} + +namespace Akregator +{ +class KonqFeedIcon : public KParts::Plugin +{ + Q_OBJECT + +public: + KonqFeedIcon(QObject *parent, const QVariantList &args); + ~KonqFeedIcon() override; + +private: + /** + * Tells you if there is feed(s) on the page. + * @return true when there is feed(s) available + */ + bool feedFound(); + + QPointer m_part; + KUrlLabel *m_feedIcon; + KParts::StatusBarExtension *m_statusBarEx; + FeedDetectorEntryList m_feedList; + QPointer m_menu; + +private slots: + void contextMenu(); + void addFeedIcon(); + void removeFeedIcon(); + + void addAllFeeds(); + void addFeed(); +}; + +} +#endif diff --git a/plugins/akregator/pluginutil.cpp b/plugins/akregator/pluginutil.cpp new file mode 100644 index 0000000..e063ded --- /dev/null +++ b/plugins/akregator/pluginutil.cpp @@ -0,0 +1,103 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "pluginutil.h" + +#include +#include +#include + +#include "feeddetector.h" +#include "akregatorplugindebug.h" + +#include +#include +#include +#include +#include +#include + +using namespace Akregator; + +static bool isAkregatorRunning() +{ + //Laurent if akregator is registered into dbus so akregator is running + return QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.akregator")); +} + +static void addFeedsViaDBUS(const QStringList &urls) +{ + QDBusInterface akregator(QStringLiteral("org.kde.akregator"), QStringLiteral("/Akregator"), QStringLiteral("org.kde.akregator.part")); + QDBusReply reply = akregator.call(QStringLiteral("addFeedsToGroup"), urls, i18n("Imported Feeds")); + if (!reply.isValid()) { + KMessageBox::error(nullptr, i18n("Unable to contact Akregator via D-Bus"), + i18nc("@title:window", "D-Bus call failed")); + } +} + +static void addFeedsViaCmdLine(const QStringList &urls) +{ + KProcess proc; + proc << QStringLiteral("akregator") << QStringLiteral("-g") << i18n("Imported Feeds"); + foreach (const QString &url, urls) { + proc << QStringLiteral("-a") << url; + } + proc.startDetached(); +} + +void PluginUtil::addFeeds(const QStringList &urls) +{ + if (isAkregatorRunning()) { + qCDebug(AKREGATORPLUGIN_LOG) << "adding" << urls.count() << "feeds via DBus"; + addFeedsViaDBUS(urls); + } else { + qCDebug(AKREGATORPLUGIN_LOG) << "adding" << urls.count() << "feeds via command line"; + addFeedsViaCmdLine(urls); + } +} + +// handle all the wild stuff that QUrl doesn't handle +QString PluginUtil::fixRelativeURL(const QString &s, const QUrl &baseurl) +{ + QString s2 = s; + QUrl u; + if (QUrl(s2).isRelative()) { + if (s2.startsWith(QLatin1String("//"))) { + s2.prepend(baseurl.scheme() + ':'); + u.setUrl(s2); + } else if (s2.startsWith(QLatin1String("/"))) { + // delete path/query/fragment, so that only protocol://host remains + QUrl b2(baseurl.adjusted(QUrl::RemovePath|QUrl::RemoveQuery|QUrl::RemoveFragment)); + u = b2.resolved(QUrl(s2.mid(1))); // remove leading "/" + } else { + u = baseurl.resolved(QUrl(s2)); + } + } else { + u.setUrl(s2); + } + + u = u.adjusted(QUrl::NormalizePathSegments); + //qCDebug(AKREGATORPLUGIN_LOG) << "url=" << s << " baseurl=" << baseurl << "fixed=" << u; + return u.url(); +} diff --git a/plugins/akregator/pluginutil.h b/plugins/akregator/pluginutil.h new file mode 100644 index 0000000..06a5e94 --- /dev/null +++ b/plugins/akregator/pluginutil.h @@ -0,0 +1,56 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef PLUGINUTIL_H +#define PLUGINUTIL_H + +class QString; +class QStringList; +class QUrl; + +namespace Akregator +{ +namespace PluginUtil +{ + /** + * Add a list of feeds to aKregator. + * + * This will be done via a DBus call if the application is running, + * or by running it with a command line option if it is not. + * + * @param urls List of feed URLs to add + */ + void addFeeds(const QStringList &urls); + + /** + * Fix up a URL relative to a base URL. + * + * @param s The URL in string form + * @param baseurl The base URL + * @return The absolute resolved URL + */ + QString fixRelativeURL(const QString &s, const QUrl &baseurl); +} +} +#endif diff --git a/plugins/autorefresh/CMakeLists.txt b/plugins/autorefresh/CMakeLists.txt new file mode 100644 index 0000000..1540052 --- /dev/null +++ b/plugins/autorefresh/CMakeLists.txt @@ -0,0 +1,23 @@ + + + + +########### next target ############### +add_definitions(-DTRANSLATION_DOMAIN=\"autorefresh\") + +set(autorefresh_PART_SRCS autorefresh.cpp ) + +add_library(autorefresh MODULE ${autorefresh_PART_SRCS}) + + + +target_link_libraries(autorefresh KF5::Parts KF5::IconThemes ) + +install(TARGETS autorefresh DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### + +install( FILES autorefresh.rc autorefresh.desktop DESTINATION ${KDE_INSTALL_DATADIR}/khtml/kpartplugins ) +install( FILES autorefresh.rc autorefresh.desktop DESTINATION ${KDE_INSTALL_DATADIR}/kwebkitpart/kpartplugins ) +install( FILES autorefresh.rc autorefresh.desktop DESTINATION ${KDE_INSTALL_DATADIR}/webenginepart/kpartplugins ) diff --git a/plugins/autorefresh/Messages.sh b/plugins/autorefresh/Messages.sh new file mode 100644 index 0000000..0ea30e3 --- /dev/null +++ b/plugins/autorefresh/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/autorefresh.pot diff --git a/plugins/autorefresh/autorefresh.cpp b/plugins/autorefresh/autorefresh.cpp new file mode 100644 index 0000000..94a97c0 --- /dev/null +++ b/plugins/autorefresh/autorefresh.cpp @@ -0,0 +1,127 @@ +// -*- c++ -*- + +/* + Copyright 2003 by Richard J. Moore, rich@kde.org + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + */ + +#include "autorefresh.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +AutoRefresh::AutoRefresh(QObject *parent, const QVariantList & /*args*/) + : Plugin(parent) +{ + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &AutoRefresh::slotRefresh); + + refresher = actionCollection()->add(QStringLiteral("autorefresh")); + refresher->setText(i18n("&Auto Refresh")); + refresher->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); + connect(refresher, SIGNAL(triggered(QAction*)), this, SLOT(slotIntervalChanged())); + QStringList sl; + sl << i18n("None"); + sl << i18n("Every 15 Seconds"); + sl << i18n("Every 30 Seconds"); + sl << i18n("Every Minute"); + sl << i18n("Every 5 Minutes"); + sl << i18n("Every 10 Minutes"); + sl << i18n("Every 15 Minutes"); + sl << i18n("Every 30 Minutes"); + sl << i18n("Every 60 Minutes"); + sl << i18n("Every 2 Hours"); + sl << i18n("Every 6 Hours"); + + refresher->setItems(sl); + refresher->setCurrentItem(0); +} + +AutoRefresh::~AutoRefresh() +{ +} + +void AutoRefresh::slotIntervalChanged() +{ + int idx = refresher->currentItem(); + int timeout = 0; + switch (idx) { + case 1: + timeout = (15 * 1000); + break; + case 2: + timeout = (30 * 1000); + break; + case 3: + timeout = (60 * 1000); + break; + case 4: + timeout = (5 * 60 * 1000); + break; + case 5: + timeout = (10 * 60 * 1000); + break; + case 6: + timeout = (15 * 60 * 1000); + break; + case 7: + timeout = (30 * 60 * 1000); + break; + case 8: + timeout = (60 * 60 * 1000); + break; + case 9: + timeout = (2 * 60 * 60 * 1000); + break; + case 10: + timeout = (6 * 60 * 60 * 1000); + break; + default: + break; + } + timer->stop(); + if (timeout) { + timer->start(timeout); + } +} + +void AutoRefresh::slotRefresh() +{ + KParts::ReadOnlyPart *part = qobject_cast< KParts::ReadOnlyPart * >(parent()); + if (!part) { + QString title = i18nc("@title:window", "Cannot Refresh Source"); + QString text = i18n("This plugin cannot auto-refresh the current part."); + + KMessageBox::error(nullptr, text, title); + } else { + // Get URL + QUrl url = part->url(); + part->openUrl(url); + } +} + +K_PLUGIN_FACTORY(AutoRefreshFactory, registerPlugin< AutoRefresh >();) + +#include "autorefresh.moc" + diff --git a/plugins/autorefresh/autorefresh.desktop b/plugins/autorefresh/autorefresh.desktop new file mode 100644 index 0000000..e0c15f0 --- /dev/null +++ b/plugins/autorefresh/autorefresh.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +X-KDE-Library=autorefresh +X-KDE-PluginInfo-Author=Richard J. Moore +X-KDE-PluginInfo-Email=rich@kde.org +X-KDE-PluginInfo-Name=autorefresh +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=Auto Refresh +Name[ar]=محلق التحديث التلقائي +Name[ast]=Autorefrescu +Name[bg]=Автоматично обновяване +Name[bs]=Autoosvežavanje +Name[ca]=Refresc automàtic +Name[ca@valencia]=Refresc automàtic +Name[cs]=Automaticky obnovit +Name[da]=Genopfrisk automatisk +Name[de]=Automatische Aktualisierung +Name[el]=Αυτόματη ανανέωση +Name[en_GB]=Auto Refresh +Name[es]=Refresco automático +Name[et]=Automaatne uuendamine +Name[eu]=Freskatu automatikoki +Name[fi]=Automaattinen päivitys +Name[fr]=Rafraîchir automatiquement +Name[ga]=Athnuachan Uathoibríoch +Name[gl]=Refrescar automaticamente +Name[he]=רענון אוטומטי +Name[hr]=Automatsko osvježavanje +Name[hu]=Automatikus frissítés +Name[ia]=Refrescamento automatic +Name[id]=Auto Segar +Name[is]=Uppfæra sjálfkrafa +Name[it]=Aggiornamento automatico +Name[ja]=自動更新 +Name[kk]=Автожаңарту +Name[km]=ធ្វើ​ឲ្យ​ស្រស់​ដោយ​ស្វ័យប្រវត្តិ +Name[ko]=자동 새로 고침 +Name[lt]=Automatiškai atnaujinti +Name[lv]=Autoatjaunošana +Name[mr]=स्वयंचलित ताजे करा +Name[nb]=Automatisk oppfriskning +Name[nds]=Automaatsch Opfrischen +Name[nl]=Autoverversen +Name[nn]=Automatisk oppdatering +Name[pa]=ਆਟੋ ਤਾਜ਼ਾ +Name[pl]=Auto-odświeżanie +Name[pt]=Actualização Automática +Name[pt_BR]=Atualizar automaticamente +Name[ro]=Reîmprospătare automată +Name[ru]=Автообновление +Name[sk]=&Automatická obnova +Name[sl]=Samodejno osveževanje +Name[sr]=Аутоматско освежавање +Name[sr@ijekavian]=Аутоматско освјежавање +Name[sr@ijekavianlatin]=Automatsko osvježavanje +Name[sr@latin]=Automatsko osvežavanje +Name[sv]=Automatisk uppdatering +Name[tg]=Худнавсозӣ +Name[th]=เรียกปรับปรุงอัตโนมัติ +Name[tr]=Otomatik Tazele +Name[ug]=ئۆزلۈكىدىن يېڭىلا +Name[uk]=Автоматичне оновлення +Name[wa]=Oto-rafristaedje  +Name[x-test]=xxAuto Refreshxx +Name[zh_CN]=自动刷新 +Name[zh_TW]=自動刷新 +Comment=Auto Refresh plugin +Comment[ar]=محلق الإنعاش التلقائي +Comment[ast]=Plugin d'autorefrescu +Comment[bg]=Приставка за автоматично обновяване +Comment[bs]=Priključak autoosvežavanja +Comment[ca]=Connector de refresc automàtic +Comment[ca@valencia]=Connector de refresc automàtic +Comment[cs]=Automaticky obnovit modul +Comment[da]=Automatisk genindlæsning af sider +Comment[de]=Modul für automatische Aktualisierung +Comment[el]=Πρόσθετο αυτόματης ανανέωσης +Comment[en_GB]=Auto Refresh plugin +Comment[es]=Complemento de refresco automático +Comment[et]=Automaatse uuendamise plugin +Comment[eu]=Automatikoki freskatzeko plugina +Comment[fi]=Automaattinen päivitys +Comment[fr]=Module externe de rafraîchissement automatique +Comment[ga]=Breiseán Athnuachana Uathoibríche +Comment[gl]=Complemento de actualización automática +Comment[he]=תוסף רענון אוטומטי +Comment[hne]=अपने अपन ताजा करे के प्लगइन +Comment[hr]=Priključak za automatsko osvježavanje +Comment[hu]=Automatikusfrissítés-bővítmény +Comment[ia]=Plug-in de refrescamento automatic +Comment[id]=Plugin Aoto Segar +Comment[is]=Íforrit fyrir sjálfvirka endurhleðslu +Comment[it]=Estensione di aggiornamento automatico +Comment[ja]=自動更新プラグイン +Comment[kk]=Автожаңарту плагині +Comment[km]=កម្មវិធី​ជំនួយ​ធ្វើ​ឲ្យ​ស្រស់​ស្វ័យ​ប្រវត្តិ​ +Comment[ko]=자동 새로 고침 플러그인 +Comment[ku]=Pêveka Nûkirina Bixweber +Comment[lt]=Automatinio atnaujinimo priedas +Comment[lv]=Automātiskās atjaunošanas spraudnis +Comment[mr]=स्वयंचलित ताजे करणारे प्लगइन +Comment[nb]=Programtillegg for automatisk oppfriskning +Comment[nds]=Moduul för't automaatsche Opfrischen +Comment[nl]=Autoverversplugin +Comment[nn]=Tillegg for automatisk oppdatering +Comment[oc]=Ajuston d'actualizacion automatica +Comment[pa]=ਆਟੋ ਤਾਜ਼ਾ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka auto-odświeżenia +Comment[pt]='Plugin' de Actualização Automática +Comment[pt_BR]=Plugin de atualização automática +Comment[ro]=Modul de actualizare automată +Comment[ru]=Модуль автообновления +Comment[sk]=Samočinne obnoviť modul +Comment[sl]=Vstavek za samodejno osveževanje +Comment[sr]=Прикључак аутоматског освежавања +Comment[sr@ijekavian]=Прикључак аутоматског освјежавања +Comment[sr@ijekavianlatin]=Priključak automatskog osvježavanja +Comment[sr@latin]=Priključak automatskog osvežavanja +Comment[sv]=Insticksprogram för automatisk uppdatering +Comment[tg]=Плагини худнавсозӣ +Comment[th]=ส่วนเสริมเรียกปรับปรุงอัตโนมัติ +Comment[tr]=Otomatik Yenileme eklentisi +Comment[ug]=ئۆزلۈكىدىن يېڭىلاش قىستۇرمىسى +Comment[uk]=Додаток автоматичного оновлення +Comment[wa]=Tchôke-divins d' oto-rafristaedje +Comment[x-test]=xxAuto Refresh pluginxx +Comment[zh_CN]=自动刷新插件 +Comment[zh_TW]=自動刷新外掛程式 +Icon=view-refresh +X-KDE-ParentApp=konqueror + diff --git a/plugins/autorefresh/autorefresh.h b/plugins/autorefresh/autorefresh.h new file mode 100644 index 0000000..c21a035 --- /dev/null +++ b/plugins/autorefresh/autorefresh.h @@ -0,0 +1,69 @@ +// -*- c++ -*- + +/* + Copyright 2003 by Richard J. Moore, rich@kde.org + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + */ + +#ifndef __plugin_autorefresh_h +#define __plugin_autorefresh_h + +#include +#include + +class QTimer; +class KSelectAction; + +/** + * A plugin is the way to add actions to an existing @ref KParts application, + * or to a @ref Part. + * + * The XML of those plugins looks exactly like of the shell or parts, + * with one small difference: The document tag should have an additional + * attribute, named "library", and contain the name of the library implementing + * the plugin. + * + * If you want this plugin to be used by a part, you need to + * install the rc file under the directory + * "data" (KDEDIR/share/apps usually)+"/instancename/kpartplugins/" + * where instancename is the name of the part's instance. + **/ +class AutoRefresh : public KParts::Plugin +{ + Q_OBJECT +public: + + /** + * Construct a new KParts plugin. + */ + explicit AutoRefresh(QObject *parent = nullptr, const QVariantList &args = QVariantList()); + + /** + * Destructor. + */ + ~AutoRefresh() override; + +public slots: + void slotRefresh(); + void slotIntervalChanged(); + +private: + KSelectAction *refresher; + QTimer *timer; +}; + +#endif diff --git a/plugins/autorefresh/autorefresh.rc b/plugins/autorefresh/autorefresh.rc new file mode 100644 index 0000000..1cd0796 --- /dev/null +++ b/plugins/autorefresh/autorefresh.rc @@ -0,0 +1,10 @@ + + + + + &Tools + + + + + diff --git a/plugins/babelfish/16-actions-babelfish.png b/plugins/babelfish/16-actions-babelfish.png new file mode 100644 index 0000000000000000000000000000000000000000..8d6cd278b7956e66569f194777739871c5663834 GIT binary patch literal 780 zcmV+n1M~ceP)K`+D$7uo3@h@6y$Vr~yWVhdB z^%_3w+qh}dDnqo+wBw+ozUgt`D`1@2Y~70b$JbO1)o1#HSC2}lqe;Z?67jT2^%sj9 z0X@@Z9C;aJI`WkBi?WJ~k}MUd31-m7AmHKkgIl=VkJ|u^cc?JUaJe%6%BO`#3gaw0 zQ6i%-J^)$}hJytApYUb*icg%K?x(#kG#5-!V9M!|IdwMso;A9pGzfM<;yf@+g06q6 zNH@ZK`{MZ3wv;UZH5tSl$s<`knNQZY74y#KZmvA=V00y!YA5q>Ia}XK{rNt z&`((WkzaplZQgDBczJPg?uCXsy+$R!K)Lw&p#^&r=T2gbeU3iL2cfqaZik2uVgq3E z5+4_&>*fuq+Eu=-`rP-m%>hH`dXLnrcii%~EyrWeEqF9%VR{G3hz|n8pco)^2$Gzj z_YiJ>h8nRb+3Sl9n!l3+r!LiaU&(D{V1(APYRX#gj|`9+fH&^9>4w)X&|QPX9*7!3 z)lHCM`4AGG6PR#o-7h2U(@*pUX)oC`UjEl5;}hbxKy(5~FPK6AFsKj+87F^harTp; z5tFl2F+?-TObb(Dt-e3M8TNNkI!njSK#_H47dj@j&9mwZ@!+eAENa_@ZB;N2fB zUPp<(5lG-aGW~qk`nyC<$WL{ao4^7fj{hmK)Sm6wUX)hLd;9|>+$4fN=I_=30000< KMNUMnLSTYZS9m%A literal 0 HcmV?d00001 diff --git a/plugins/babelfish/22-actions-babelfish.png b/plugins/babelfish/22-actions-babelfish.png new file mode 100644 index 0000000000000000000000000000000000000000..0ea68ff488ca8aaad3b3f28cdff5aaf7b9c68a8e GIT binary patch literal 1279 zcmVdh_~k+00006VoOIv0RI600RN!9r;`8x1dK^U zK~xwSt-)zf6a*N6;cs_gK|w_YZ(1cyDJ9Ke)Vwf{al9(Q9}Ny3QD}^DD5Zg+C^{00 z7m5wzD3KD1*D8mK3M_`GfZT^5kVp}Sgd)enzV)Y>rlP^>c|=}9U4Zn_ZxoHgP*H|V z5_Qx}mFCJy%?jNj^-1qHB;3YK%;jZd_=$OQh%B!TkW2ovR9h}NkM%0q>!y41?apV- zXM(!6PaAYrr4WsXD5N*8Zxv-@q)e$hAZP3Ln6=&WoASISc27fRP69kBrn4{^?Ltkm zS|OvPw~D?Nv+AR=p+;+7TM;&$)|A5-%hRDM6CQmJW$EZYU-FZkg<_iYR>?7O&I(q< zRvwZkQ_t1%WuLs1MA zo`S+?DEtN`!EcFWu%lQ?kb@{A$7Xl42Q0@#BE^ybG_J{@4 z#?K~k`{2d|uc>!hGmf?!9>x>tW`BFInP?<(t?X*M)d%t>(q8Vtlj1Ns%hy2a5=dSQ zNsA!E8yd7w;{-MHpv(zQOy{n5UkY|Rc6aARK}j4BPpoZm8l_qxA_^HZK+K}I$f348 zwSh+#P;Cu06X2!;Bus|OlR@te^~<4YJTz&bdH@_$QT@d*jQSmLe-C8uBF^*G40DB8 z$?qoHh(+99#jzJP)}1sDfkqWv7C57Xb0gr&6lgYu4uMXAN`Y`CHKFzxQ@tVEm#(}` zgsiqbA|fjJBYP|9cRExV(o#MA1%<;vr-BRSaLx*JN-zi@U=+v{x{vp#G*r`Ntl11t z1L>^yA=J|@NJJF!XQM5}Ji=3ae$o51lKUmZ+rxKC$QD2VfhK{ARq2+cQld9mq}>XUJLmmHKkXG+C?X2^ zH#ROGI5O*sQ<|aKr<>;=kr*-QjED>r5o-}q%73wH_E6jCeM=8zr>?I&6*}>bh^XZM pGSFO1?O(CbXlzW!i-> rc.cpp +$XGETTEXT *.cpp -o $podir/babelfish.pot diff --git a/plugins/babelfish/plugin_babelfish.cpp b/plugins/babelfish/plugin_babelfish.cpp new file mode 100644 index 0000000..91f35fd --- /dev/null +++ b/plugins/babelfish/plugin_babelfish.cpp @@ -0,0 +1,425 @@ +/* This file is part of the KDE Project + Copyright (C) 2001 Kurt Granroth + Original code: plugin code, connecting to Babelfish and support for selected text + Copyright (C) 2003 Rand2342 + Submenus, KConfig file and support for other translation engines + Copyright (C) 2008 Montel Laurent + Add webkitkde support + Copyright (C) 2010 David Faure + Ported to KParts::TextExtension + + 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 "plugin_babelfish.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const KAboutData aboutdata(QStringLiteral("babelfish"), i18n("Translate Web Page"), QStringLiteral("1.0")); +K_PLUGIN_FACTORY(BabelFishFactory, registerPlugin();) + +PluginBabelFish::PluginBabelFish(QObject *parent, + const QVariantList &) + : Plugin(parent), + m_actionGroup(this) +{ + m_menu = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("Translate Web &Page"), + actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage"), m_menu); + m_menu->setDelayed(false); + connect(m_menu->menu(), SIGNAL(aboutToShow()), + this, SLOT(slotAboutToShow())); + + KParts::ReadOnlyPart *part = qobject_cast(parent); + if (part) { + connect(part, SIGNAL(started(KIO::Job*)), this, + SLOT(slotEnableMenu())); + connect(part, SIGNAL(completed()), this, + SLOT(slotEnableMenu())); + connect(part, SIGNAL(completed(bool)), this, + SLOT(slotEnableMenu())); + } +} + +void PluginBabelFish::addTopLevelAction(const QString &name, const QString &text) +{ + QAction *a = actionCollection()->addAction(name); + a->setText(text); + m_menu->addAction(a); + m_actionGroup.addAction(a); +} + +void PluginBabelFish::slotAboutToShow() +{ + if (!m_menu->menu()->actions().isEmpty()) { // already populated + return; + } + + connect(&m_actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(translateURL(QAction*))); + + // Create a menu for each "source->dest" translation possibility where + // there's more than one dest for a given source. + + KActionMenu *menu_en = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&English To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_en"), menu_en); + + KActionMenu *menu_fr = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&French To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_fr"), menu_fr); + + KActionMenu *menu_de = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&German To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_de"), menu_de); + + KActionMenu *menu_el = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Greek To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_el"), menu_el); + + KActionMenu *menu_es = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Spanish To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_es"), menu_es); + + KActionMenu *menu_pt = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Portuguese To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_pt"), menu_pt); + + KActionMenu *menu_it = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Italian To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_it"), menu_it); + + KActionMenu *menu_nl = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Dutch To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_nl"), menu_nl); + + KActionMenu *menu_ru = new KActionMenu(QIcon::fromTheme(QStringLiteral("babelfish")), i18n("&Russian To"), actionCollection()); + actionCollection()->addAction(QStringLiteral("translatewebpage_ru"), menu_ru); + + // List of translation possibilities for filling the above menus + // Mostly from babelfish. + // TODO: add all translation paths from www.reverso.net + // and all translation paths from www.freetranslation.com + // and all those from translate.google.com!! Full matrix supported... we need a different system... + // [possibly in a different list, so that we can remove it more easily if + // it goes offline?] + // TODO: Maybe the entire list of possibilities could come from translaterc? + // (It would need source, dest, engine, language-code-on-that-engine) + // Here we would just have the i18n texts for each lang code, + // and we would make up the menus on the fly. + + static const char *const translations[] = { + I18N_NOOP("&Chinese (Simplified)"), "en_zh", + I18N_NOOP("Chinese (&Traditional)"), "en_zt", + I18N_NOOP("&Dutch"), "en_nl", + I18N_NOOP("&French"), "en_fr", + I18N_NOOP("&German"), "en_de", + I18N_NOOP("&Greek"), "en_el", + I18N_NOOP("&Italian"), "en_it", + I18N_NOOP("&Japanese"), "en_ja", + I18N_NOOP("&Korean"), "en_ko", + I18N_NOOP("&Norwegian"), "en_no", + I18N_NOOP("&Portuguese"), "en_pt", + I18N_NOOP("&Russian"), "en_ru", + I18N_NOOP("&Spanish"), "en_es", + I18N_NOOP("T&hai"), "en_th", // only on parsit + I18N_NOOP("&Arabic"), "fr_ar", // google + I18N_NOOP("&Dutch"), "fr_nl", + I18N_NOOP("&English"), "fr_en", + I18N_NOOP("&German"), "fr_de", + I18N_NOOP("&Greek"), "fr_el", + I18N_NOOP("&Italian"), "fr_it", + I18N_NOOP("&Portuguese"), "fr_pt", + I18N_NOOP("&Spanish"), "fr_es", + I18N_NOOP("&Russian"), "fr_ru", // only on voila + I18N_NOOP("&English"), "de_en", + I18N_NOOP("&French"), "de_fr", + I18N_NOOP("&English"), "el_en", + I18N_NOOP("&French"), "el_fr", + I18N_NOOP("&English"), "es_en", + I18N_NOOP("&French"), "es_fr", + I18N_NOOP("&English"), "pt_en", + I18N_NOOP("&French"), "pt_fr", + I18N_NOOP("&English"), "it_en", + I18N_NOOP("&French"), "it_fr", + I18N_NOOP("&English"), "nl_en", + I18N_NOOP("&French"), "nl_fr", + I18N_NOOP("&English"), "ru_en", + I18N_NOOP("&French"), "ru_fr", // only on voila + nullptr, nullptr + }; + + for (int i = 0; translations[i]; i += 2) { + const QString translation = QString::fromLatin1(translations[i + 1]); + const int underScorePos = translation.indexOf(QLatin1Char('_')); + const QString srcLang = translation.left(underScorePos); + QAction *srcAction = actionCollection()->action(QLatin1String("translatewebpage_") + srcLang); + if (KActionMenu *actionMenu = qobject_cast(srcAction)) { + QAction *a = actionCollection()->addAction(translation); + m_actionGroup.addAction(a); + a->setText(i18n(translations[i])); + actionMenu->addAction(a); + } else { + qWarning() << "No menu found for" << srcLang; + } + } + + // Fill the toplevel menu, both with single source->dest possibilities + // and with submenus. + + addTopLevelAction(QStringLiteral("zh_en"), i18n("&Chinese (Simplified) to English")); + addTopLevelAction(QStringLiteral("zt_en"), i18n("Chinese (&Traditional) to English")); + + m_menu->addAction(menu_nl); + m_menu->addAction(menu_en); + m_menu->addAction(menu_fr); + m_menu->addAction(menu_de); + m_menu->addAction(menu_el); + m_menu->addAction(menu_it); + + addTopLevelAction(QStringLiteral("ja_en"), i18n("&Japanese to English")); + addTopLevelAction(QStringLiteral("ko_en"), i18n("&Korean to English")); + + m_menu->addAction(menu_pt); + m_menu->addAction(menu_ru); + m_menu->addAction(menu_es); + + // TODO we could sort the action texts alphabetically, so that they wouldn't + // be sorted in English only... +} + +PluginBabelFish::~PluginBabelFish() +{ + delete m_menu; +} + +// Decide whether or not to enable the menu +void PluginBabelFish::slotEnableMenu() +{ + KParts::ReadOnlyPart *part = qobject_cast(parent()); + KParts::TextExtension *textExt = KParts::TextExtension::childObject(parent()); + + //if (part) + // kDebug() << part->url(); + + if (part && textExt) { + const QString scheme = part->url().scheme(); // always lower case + if ((scheme == QLatin1String("http")) || (scheme == QLatin1String("https"))) { + if (KParts::BrowserExtension::childObject(part)) { + m_menu->setEnabled(true); + return; + } + } + } + + m_menu->setEnabled(false); +} + +void PluginBabelFish::translateURL(QAction *action) +{ + // KHTMLPart and KWebKitPart provide a TextExtension, at least. + // So if we got a part without a TextExtension, give an error. + KParts::TextExtension *textExt = KParts::TextExtension::childObject(parent()); + Q_ASSERT(textExt); // already checked in slotAboutToShow + + // Select engine + const KConfig cfg(QStringLiteral("translaterc")); + const KConfigGroup grp(&cfg, QString()); + const QString language = action->objectName(); + const QString engine = grp.readEntry(language, QStringLiteral("google")); + + KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(parent()); + if (!ext) { + return; + } + KParts::ReadOnlyPart *part = qobject_cast(parent()); + + // we check if we have text selected. if so, we translate that. If + // not, we translate the url + QString textForQuery; + QUrl url = part->url(); + const bool hasSelection = textExt->hasSelection(); + + if (hasSelection) { + QString selection = textExt->selectedText(KParts::TextExtension::PlainText); + textForQuery = QString::fromLatin1(QUrl::toPercentEncoding(selection)); + } else { + // Check syntax + if (!url.isValid()) { + QString title = i18nc("@title:window", "Malformed URL"); + QString text = i18n("The URL you entered is not valid, please " + "correct it and try again."); + KMessageBox::sorry(part->widget(), text, title); + return; + } + } + const QString urlForQuery = QLatin1String(QUrl::toPercentEncoding(url.url())); + + if (url.scheme() == QLatin1String("https")) { + if (KMessageBox::warningContinueCancel(part->widget(), + xi18nc("@info", "\ +You are viewing this page over a secure connection.\ +The URL of the page will sent to the online translation service, \ +which may fetch the insecure version of the page."), + i18nc("@title:window", "Security Warning"), + KStandardGuiItem::cont(), + KStandardGuiItem::cancel(), + QStringLiteral("insecureTranslate")) != KMessageBox::Continue) { + return; + } + } + + // Create URL + QUrl result; + QString query; + + if (engine == QLatin1String("freetranslation")) { + query = QStringLiteral("sequence=core&language="); + if (language == QStringLiteral("en_es")) { + query += QLatin1String("English/Spanish"); + } else if (language == QStringLiteral("en_de")) { + query += QLatin1String("English/German"); + } else if (language == QStringLiteral("en_it")) { + query += QLatin1String("English/Italian"); + } else if (language == QStringLiteral("en_nl")) { + query += QLatin1String("English/Dutch"); + } else if (language == QStringLiteral("en_pt")) { + query += QLatin1String("English/Portuguese"); + } else if (language == QStringLiteral("en_no")) { + query += QLatin1String("English/Norwegian"); + } else if (language == QStringLiteral("en_zh")) { + query += QLatin1String("English/SimplifiedChinese"); + } else if (language == QStringLiteral("en_zhTW")) { + query += QLatin1String("English/TraditionalChinese"); + } else if (language == QStringLiteral("es_en")) { + query += QLatin1String("Spanish/English"); + } else if (language == QStringLiteral("fr_en")) { + query += QLatin1String("French/English"); + } else if (language == QStringLiteral("de_en")) { + query += QLatin1String("German/English"); + } else if (language == QStringLiteral("it_en")) { + query += QLatin1String("Italian/English"); + } else if (language == QStringLiteral("nl_en")) { + query += QLatin1String("Dutch/English"); + } else if (language == QStringLiteral("pt_en")) { + query += QLatin1String("Portuguese/English"); + } else { // Should be en_fr + query += QLatin1String("English/French"); + } + if (hasSelection) { + // ## does not work + result = QUrl(QStringLiteral("http://ets.freetranslation.com")); + query += QLatin1String("&mode=html&template=results_en-us.htm&srctext="); + query += textForQuery; + } else { + result = QUrl(QStringLiteral("http://www.freetranslation.com/web.asp")); + query += QLatin1String("&url="); + query += urlForQuery; + } + } else if (engine == QLatin1String("parsit")) { + // Does only English -> Thai + result = QUrl(QStringLiteral("http://c3po.links.nectec.or.th/cgi-bin/Parsitcgi.exe")); + query = QStringLiteral("mode=test&inputtype="); + if (hasSelection) { + query += QLatin1String("text&TxtEng="); + query += textForQuery; + } else { + query += QLatin1String("html&inputurl="); + query += urlForQuery; + } + } else if (engine == QLatin1String("reverso")) { + result = QUrl(QStringLiteral("http://www.reverso.net/url/frame.asp")); + query = QStringLiteral("autotranslate=on&templates=0&x=0&y=0&directions="); + if (language == QStringLiteral("de_fr")) { + query += QLatin1String("524292"); + } else if (language == QStringLiteral("fr_en")) { + query += QLatin1String("65544"); + } else if (language == QStringLiteral("fr_de")) { + query += QLatin1String("262152"); + } else if (language == QStringLiteral("de_en")) { + query += QLatin1String("65540"); + } else if (language == QStringLiteral("en_de")) { + query += QLatin1String("262145"); + } else if (language == QStringLiteral("en_es")) { + query += QLatin1String("2097153"); + } else if (language == QStringLiteral("es_en")) { + query += QLatin1String("65568"); + } else if (language == QStringLiteral("fr_es")) { + query += QLatin1String("2097160"); + } else { // "en_fr" + query += QLatin1String("524289"); + } + query += QLatin1String("&url="); + query += urlForQuery; + } else if (engine == QLatin1String("tsail")) { + result = QUrl(QStringLiteral("http://www.t-mail.com/cgi-bin/tsail")); + query = QStringLiteral("sail=full&lp="); + if (language == QStringLiteral("zhTW_en")) { + query += QLatin1String("tw-en"); + } else if (language == QStringLiteral("en_zhTW")) { + query += QLatin1String("en-tw"); + } else { + query += language; + query[15] = '-'; + } + query += urlForQuery; + } else if (engine == QLatin1String("voila")) { + result = QUrl(QStringLiteral("http://tr.voila.fr/traduire-une-page-web-frame.php")); + const QStringList parts = language.split('_'); + if (parts.count() == 2) { + // The translation direction is "first letter of source, first letter of dest" + query = QStringLiteral("translationDirection="); + query += parts[0][0]; + query += parts[1][0]; + if (false /*hasSelection*/) { // TODO: needs POST + query += QLatin1String("&isText=1&stext="); + query += textForQuery; + } else { + query += QLatin1String("&urlToTranslate="); + query += urlForQuery; + } + } + } else { + + const QStringList parts = language.split('_'); + + if (hasSelection) { //https://translate.google.com/#en|de|text_to_translate + query = QStringLiteral("https://translate.google.com/#"); + if (parts.count() == 2) { + query += parts[0] + "|" + parts[1]; + } + query += "|" + textForQuery; + result = QUrl(query); + } else { //https://translate.google.com/translate?hl=en&sl=en&tl=de&u=http%3A%2F%2Fkde.org%2F%2F + result = QUrl(QStringLiteral("https://translate.google.com/translate")); + query = QStringLiteral("ie=UTF-8"); + if (parts.count() == 2) { + query += "&sl=" + parts[0] + "&tl=" + parts[1]; + } + query += "&u=" + urlForQuery; + result.setQuery(query); + } + } + + // Connect to the fish + emit ext->openUrlRequest(result); +} + +#include diff --git a/plugins/babelfish/plugin_babelfish.h b/plugins/babelfish/plugin_babelfish.h new file mode 100644 index 0000000..b3cb3f7 --- /dev/null +++ b/plugins/babelfish/plugin_babelfish.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE Project + Copyright (C) 2001 Kurt Granroth + Copyright (C) 2003 Rand2342 + + 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 __plugin_babelfish_h +#define __plugin_babelfish_h + +#include +#include +#include + +class PluginBabelFish : public KParts::Plugin +{ + Q_OBJECT +public: + explicit PluginBabelFish(QObject *parent, + const QVariantList &); + ~PluginBabelFish() override; + +private slots: + void translateURL(QAction *); + void slotAboutToShow(); + void slotEnableMenu(); + +private: + void addTopLevelAction(const QString &name, const QString &text); + +private: + QActionGroup m_actionGroup; + KActionMenu *m_menu; +}; + +#endif diff --git a/plugins/babelfish/plugin_babelfish.rc b/plugins/babelfish/plugin_babelfish.rc new file mode 100644 index 0000000..0e0dccf --- /dev/null +++ b/plugins/babelfish/plugin_babelfish.rc @@ -0,0 +1,11 @@ + + + + &Tools + + + +Extra Toolbar + + + diff --git a/plugins/babelfish/plugin_translator.desktop b/plugins/babelfish/plugin_translator.desktop new file mode 100644 index 0000000..88272b4 --- /dev/null +++ b/plugins/babelfish/plugin_translator.desktop @@ -0,0 +1,128 @@ +[Desktop Entry] +X-KDE-Library=babelfish +X-KDE-PluginInfo-Author=Kurt Granroth, Rand2342 +X-KDE-PluginInfo-Email=granroth@kde.org, rand2342@yahoo.com +X-KDE-PluginInfo-Name=babelfish +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Translate +Name[ar]=ترجم +Name[ast]=Traducción +Name[be]=Перакласці +Name[bg]=Превеждане +Name[bs]=Prevedi +Name[ca]=Traducció +Name[ca@valencia]=Traducció +Name[cs]=Přeložit +Name[da]=Oversættelse +Name[de]=Übersetzen +Name[el]=Μετάφραση +Name[en_GB]=Translate +Name[eo]=Traduki +Name[es]=Traducir +Name[et]=Tõlkimine +Name[eu]=Itzuli +Name[fi]=Käännä +Name[fr]=Traduire +Name[ga]=Aistrigh +Name[gl]=Traducir +Name[he]=תרגום +Name[hne]=अनुवाद +Name[hr]=Prevedi +Name[hu]=Fordítás +Name[ia]=Traduce +Name[id]=Terjemah +Name[is]=Þýða +Name[it]=Traduci +Name[ja]=翻訳 +Name[kk]=Аудару +Name[km]=បកប្រែ​ +Name[ko]=번역 +Name[ku]=Wergerîne +Name[lt]=Išversti +Name[lv]=Tulkot +Name[mai]=अनुवाद +Name[mr]=भाषांतर +Name[ms]=Terjemah +Name[nb]=Oversett +Name[nds]=Översetten +Name[nl]=Vertalen +Name[nn]=Set om +Name[oc]=Revirar +Name[pa]=ਅਨੁਵਾਦ +Name[pl]=Przetłumacz +Name[pt]=Traduzir +Name[pt_BR]=Traduzir +Name[ro]=Tradu +Name[ru]=Перевести +Name[sk]=Preložiť +Name[sl]=Prevajanje +Name[sr]=Преведи +Name[sr@ijekavian]=Преведи +Name[sr@ijekavianlatin]=Prevedi +Name[sr@latin]=Prevedi +Name[sv]=Översätt +Name[tg]=Тарҷума кунед +Name[th]=แปลภาษา +Name[tr]=Çevir +Name[ug]=تەرجىمە +Name[uk]=Переклад +Name[wa]=Ratourner +Name[x-test]=xxTranslatexx +Name[zh_CN]=翻译 +Name[zh_TW]=翻譯 +Comment=Language translation for the current page using Google +Comment[ast]=Traducción de la páxina actual usando Google +Comment[bg]=Превеждане на текущата страница с помощта на Google +Comment[bs]=Prevod trenutne stranicu koristeći Gogle +Comment[ca]=Traducció d'idioma per a la pàgina actual usant el Google +Comment[ca@valencia]=Traducció d'idioma per a la pàgina actual usant el Google +Comment[cs]=Překlad aktuální stránky do vybraného jazyka pomocí Google +Comment[da]=Sprogoversættelse af den aktuelle side med Google +Comment[de]=Übersetzt die Sprache der aktuellen Webseite mit Hilfe von Google +Comment[el]=Μετάφραση της τρέχουσας σελίδας με χρήση Google +Comment[en_GB]=Language translation for the current page using Google +Comment[es]=Traducción de idioma para la página actual utilizando Google +Comment[et]=Aktiivse lehekülje tõlkimine Google'i abil +Comment[eu]=Uneko orriaren hizkutzaren itzulpena Google erabiliz +Comment[fi]=Nykyisen sivun kääntäminen toiselle kielelle käyttäen Googlea +Comment[fr]=Traduction de la langue de la page actuelle à l'aide de Google +Comment[gl]=Tradución da páxina actual usando Google +Comment[he]=תרגום שפת הדף הנוכחי באמצעות Google +Comment[hu]=Az aktuális oldal fordítása a Google használatával +Comment[ia]=Traduction de linguage pro le pagina currente usante Google +Comment[id]=Terjemahan bahasa untuk halaman saat ini menggunakan Google +Comment[is]=Þýða tungumál síðunnar með Google +Comment[it]=Traduzione della pagina corrente usando Google +Comment[kk]=Google-дің көмегімен ашылған бетті басқа тілге аудару +Comment[ko]=Google을 사용하여 현재 페이지의 언어를 번역하기 +Comment[lt]=Šio puslapio kalbos vertimas naudojant Google +Comment[nb]=Språkoversettelse for gjeldende side, ved bruk av Google +Comment[nds]=Översetten vun de aktuelle Nettsiet mit Google +Comment[nl]=Vertaalt de huidige webpagina met behulp van Google +Comment[nn]=Omsetjing av den gjeldande sida ved bruk av Google +Comment[pa]=ਮੌਜੂਦਾ ਪੇਜ਼ ਦਾ ਗੂਗਲ ਰਾਹੀਂ ਭਾਸ਼ਾ ਅਨੁਵਾਦ +Comment[pl]=Tłumaczenia dla bieżącej strony przy użyciu Google +Comment[pt]=Traduzir a língua da página actual com o Google +Comment[pt_BR]=Tradução da página atual usando o Google +Comment[ro]=Traducerea lingvistică pentru pagina curentă folosind Google +Comment[ru]=Перевод текущей страницы с помощью Google +Comment[sk]=Preklad aktuálnej stránky pomocou Google +Comment[sl]=Prevod trenutne strani z uporabo Googla +Comment[sr]=Преведи тренутну страницу Гуглом +Comment[sr@ijekavian]=Преведи тренутну страницу Гуглом +Comment[sr@ijekavianlatin]=Prevedi trenutnu stranicu Googleom +Comment[sr@latin]=Prevedi trenutnu stranicu Googleom +Comment[sv]=Översättning av språk för den aktuella sidan med Google +Comment[tr]=Yürürlükteki sayfayı Google ile çevir +Comment[uk]=Переклад поточної сторінки за допомогою Google +Comment[x-test]=xxLanguage translation for the current page using Googlexx +Comment[zh_CN]=使用 Google 对当前页面的翻译 +Comment[zh_TW]=使用 Google 對目前頁面做翻譯 +Icon=babelfish +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/babel/index.html diff --git a/plugins/babelfish/translaterc b/plugins/babelfish/translaterc new file mode 100644 index 0000000..a6f20b9 --- /dev/null +++ b/plugins/babelfish/translaterc @@ -0,0 +1,6 @@ +en_no=freetranslation +en_th=parsit +#fr_es=reverso +fr_ru=voila +ru_fr=voila +fr_ar=google diff --git a/plugins/dirfilter/CMakeLists.txt b/plugins/dirfilter/CMakeLists.txt new file mode 100644 index 0000000..4a91ad1 --- /dev/null +++ b/plugins/dirfilter/CMakeLists.txt @@ -0,0 +1,14 @@ +############### next target ############### +add_definitions(-DTRANSLATION_DOMAIN=\"dirfilterplugin\") +set(dirfilterplugin_PART_SRCS dirfilterplugin.cpp ) + +add_library(dirfilterplugin MODULE ${dirfilterplugin_PART_SRCS}) + +target_link_libraries(dirfilterplugin KF5::Parts) + +install(TARGETS dirfilterplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### + +install( FILES dirfilterplugin.rc dirfilterplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/dolphinpart/kpartplugins ) diff --git a/plugins/dirfilter/Messages.sh b/plugins/dirfilter/Messages.sh new file mode 100644 index 0000000..a8678c0 --- /dev/null +++ b/plugins/dirfilter/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/dirfilterplugin.pot diff --git a/plugins/dirfilter/dirfilterplugin.cpp b/plugins/dirfilter/dirfilterplugin.cpp new file mode 100644 index 0000000..9cfea94 --- /dev/null +++ b/plugins/dirfilter/dirfilterplugin.cpp @@ -0,0 +1,550 @@ +/* + Copyright (C) 2000-2011 Dawit Alemayehu + + 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 "dirfilterplugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +Q_GLOBAL_STATIC(SessionManager, globalSessionManager) + +static void generateKey(const QUrl &url, QString *key) +{ + if (url.isValid()) { + *key = url.scheme(); + *key += QLatin1Char(':'); + + if (!url.host().isEmpty()) { + *key += url.host(); + *key += QLatin1Char(':'); + } + + if (!url.path().isEmpty()) { + *key += url.path(); + } + } +} + +static void saveNameFilter(const QUrl &url, const QString &filter) +{ + SessionManager::Filters f = globalSessionManager->restore(url); + f.nameFilter = filter; + globalSessionManager->save(url, f); +} + +static void saveTypeFilters(const QUrl &url, const QStringList &filters) +{ + SessionManager::Filters f = globalSessionManager->restore(url); + f.typeFilters = filters; + globalSessionManager->save(url, f); +} + +SessionManager::SessionManager() +{ + m_bSettingsLoaded = false; + loadSettings(); +} + +SessionManager::~SessionManager() +{ + saveSettings(); +} + +SessionManager::Filters SessionManager::restore(const QUrl &url) +{ + QString key; + generateKey(url, &key); + return m_filters.value(key); +} + +void SessionManager::save(const QUrl &url, const Filters &filters) +{ + QString key; + generateKey(url, &key); + m_filters[key] = filters; +} + +void SessionManager::saveSettings() +{ + KConfig cfg(QStringLiteral("dirfilterrc"), KConfig::NoGlobals); + KConfigGroup group = cfg.group("General"); + + group.writeEntry("ShowCount", showCount); + group.writeEntry("UseMultipleFilters", useMultipleFilters); + cfg.sync(); +} + +void SessionManager::loadSettings() +{ + if (m_bSettingsLoaded) { + return; + } + + KConfig cfg(QStringLiteral("dirfilterrc"), KConfig::NoGlobals); + KConfigGroup group = cfg.group("General"); + + showCount = group.readEntry("ShowCount", false); + useMultipleFilters = group.readEntry("UseMultipleFilters", true); + m_bSettingsLoaded = true; +} + +FilterBar::FilterBar(QWidget *parent) + : QWidget(parent) +{ + // Create close button + QToolButton *closeButton = new QToolButton(this); + closeButton->setAutoRaise(true); + closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); + closeButton->setToolTip(i18nc("@info:tooltip", "Hide Filter Bar")); + connect(closeButton, SIGNAL(clicked()), this, SIGNAL(closeRequest())); + + // Create label + QLabel *filterLabel = new QLabel(i18nc("@label:textbox", "F&ilter:"), this); + + // Create filter editor + m_filterInput = new KLineEdit(this); + m_filterInput->setLayoutDirection(Qt::LeftToRight); + m_filterInput->setClearButtonEnabled(true); + connect(m_filterInput, SIGNAL(textChanged(QString)), + this, SIGNAL(filterChanged(QString))); + setFocusProxy(m_filterInput); + + m_typeFilterButton = new QPushButton(this); + m_typeFilterButton->setIcon(QIcon::fromTheme(QStringLiteral("view-filter"))); + m_typeFilterButton->setText(i18nc("@label:button", "Filter by t&ype")); + m_typeFilterButton->setToolTip(i18nc("@info:tooltip", "Filter items by file type.")); + + // Apply layout + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(closeButton); + layout->addWidget(filterLabel); + layout->addWidget(m_filterInput); + layout->addWidget(m_typeFilterButton); + layout->addItem(new QSpacerItem(20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum)); + + filterLabel->setBuddy(m_filterInput); +} + +FilterBar::~FilterBar() +{ +} + +void FilterBar::selectAll() +{ + m_filterInput->selectAll(); +} + +bool FilterBar::typeFilterMenuEnabled() const +{ + return m_typeFilterButton->isEnabled(); +} + +void FilterBar::setEnableTypeFilterMenu(bool state) +{ + m_typeFilterButton->setEnabled(state); +} + +void FilterBar::setTypeFilterMenu(QMenu *menu) +{ + m_typeFilterButton->setMenu(menu); +} + +QMenu *FilterBar::typeFilterMenu() +{ + return m_typeFilterButton->menu(); +} + +void FilterBar::setNameFilter(const QString &text) +{ + m_filterInput->setText(text); +} + +void FilterBar::clear() +{ + m_filterInput->clear(); +} + +void FilterBar::showEvent(QShowEvent *event) +{ + if (!event->spontaneous()) { + m_filterInput->setFocus(); + } +} + +void FilterBar::keyReleaseEvent(QKeyEvent *event) +{ + QWidget::keyReleaseEvent(event); + if (event->key() == Qt::Key_Escape) { + if (m_filterInput->text().isEmpty()) { + emit closeRequest(); + } else { + m_filterInput->clear(); + } + } +} + +DirFilterPlugin::DirFilterPlugin(QObject *parent, const QVariantList &) + : KParts::Plugin(parent) + , m_filterBar(nullptr) + , m_focusWidget(nullptr) +{ + m_part = qobject_cast(parent); + if (m_part) { + connect(m_part, SIGNAL(aboutToOpenURL()), this, SLOT(slotOpenURL())); + //connect(m_part, SIGNAL(completed()), this, SLOT(slotOpenURLCompleted())); + connect(m_part, SIGNAL(completed(bool)), this, SLOT(slotOpenURLCompleted())); + } + + KParts::ListingNotificationExtension *notifyExt = KParts::ListingNotificationExtension::childObject(m_part); + if (notifyExt && notifyExt->supportedNotificationEventTypes() != KParts::ListingNotificationExtension::None) { + m_listingExt = KParts::ListingFilterExtension::childObject(m_part); + connect(notifyExt, SIGNAL(listingEvent(KParts::ListingNotificationExtension::NotificationEventType,KFileItemList)), + this, SLOT(slotListingEvent(KParts::ListingNotificationExtension::NotificationEventType,KFileItemList))); + + QAction *action = actionCollection()->addAction(QStringLiteral("filterdir"), this, SLOT(slotShowFilterBar())); + action->setText(i18nc("@action:inmenu Tools", "Show Filter Bar")); + action->setIcon(QIcon::fromTheme(QStringLiteral("view-filter"))); + actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I)); + } +} + +DirFilterPlugin::~DirFilterPlugin() +{ +} + +void DirFilterPlugin::slotOpenURL() +{ + if (m_part && !m_part->arguments().reload()) { + m_pMimeInfo.clear(); + if (m_filterBar && m_filterBar->isVisible()) { + m_filterBar->clear(); + m_filterBar->setEnableTypeFilterMenu(false); // Will be enabled once loading has completed + } + } +} + +void DirFilterPlugin::slotOpenURLCompleted() +{ + if (m_listingExt && m_part && m_filterBar && m_filterBar->isVisible()) { + setFilterBar(); + } +} + +void DirFilterPlugin::slotShowPopup() +{ + QMenu *filterMenu = (m_filterBar ? m_filterBar->typeFilterMenu() : nullptr); + if (!filterMenu) { + return; + } + + filterMenu->clear(); + + QString label; + QStringList inodes; + quint64 enableReset = 0; + QMapIterator it(m_pMimeInfo); + + while (it.hasNext()) { + it.next(); + + if (it.key().startsWith(QLatin1String("inode"))) { + inodes << it.key(); + continue; + } + + if (!globalSessionManager->showCount) { + label = it.value().mimeComment; + } else { + label = it.value().mimeComment; + label += QLatin1String(" ("); + label += QString::number(it.value().filenames.size()); + label += ')'; + } + + QAction *action = filterMenu->addAction(QIcon::fromTheme(it.value().iconName), label); + action->setCheckable(true); + if (it.value().useAsFilter) { + action->setChecked(true); + enableReset++; + } + action->setData(it.key()); + m_pMimeInfo[it.key()].action = action; + } + + // Add all the items that have mime-type of "inode/*" here... + if (!inodes.isEmpty()) { + filterMenu->addSeparator(); + + Q_FOREACH (const QString &inode, inodes) { + if (!globalSessionManager->showCount) { + label = m_pMimeInfo[inode].mimeComment; + } else { + label = m_pMimeInfo[inode].mimeComment; + label += QLatin1String(" ("); + label += QString::number(m_pMimeInfo[inode].filenames.size()); + label += ')'; + } + + QAction *action = filterMenu->addAction(QIcon::fromTheme(m_pMimeInfo[inode].iconName), label); + action->setCheckable(true); + if (m_pMimeInfo[inode].useAsFilter) { + action->setChecked(true); + enableReset ++; + } + action->setData(inode); + m_pMimeInfo[inode].action = action; + } + } + filterMenu->addSeparator(); + QAction *action = filterMenu->addAction(i18n("Use Multiple Filters"), + this, SLOT(slotMultipleFilters())); + action->setEnabled(enableReset <= 1); + action->setCheckable(true); + action->setChecked(globalSessionManager->useMultipleFilters); + + action = filterMenu->addAction(i18n("Show Count"), this, + SLOT(slotShowCount())); + action->setCheckable(true); + action->setChecked(globalSessionManager->showCount); + + action = filterMenu->addAction(i18n("Reset"), this, + SLOT(slotReset())); + action->setEnabled(enableReset); +} + +void DirFilterPlugin::slotItemSelected(QAction *action) +{ + if (!m_listingExt || !action || !m_part) { + return; + } + + MimeInfoMap::iterator it = m_pMimeInfo.find(action->data().toString()); + if (it != m_pMimeInfo.end()) { + MimeInfo &mimeInfo = it.value(); + QStringList filters; + + if (mimeInfo.useAsFilter) { + mimeInfo.useAsFilter = false; + filters = m_listingExt->filter(KParts::ListingFilterExtension::MimeType).toStringList(); + if (filters.removeAll(it.key())) { + m_listingExt->setFilter(KParts::ListingFilterExtension::MimeType, filters); + } + } else { + m_pMimeInfo[it.key()].useAsFilter = true; + + if (globalSessionManager->useMultipleFilters) { + filters = m_listingExt->filter(KParts::ListingFilterExtension::MimeType).toStringList(); + filters << it.key(); + } else { + filters << it.key(); + + MimeInfoMap::iterator item = m_pMimeInfo.begin(); + MimeInfoMap::iterator itemEnd = m_pMimeInfo.end(); + while (item != itemEnd) { + if (item != it) { + item.value().useAsFilter = false; + } + item++; + } + } + m_listingExt->setFilter(KParts::ListingFilterExtension::MimeType, filters); + } + + saveTypeFilters(m_part->url(), filters); + } +} + +void DirFilterPlugin::slotNameFilterChanged(const QString &filter) +{ + if (!m_listingExt || !m_part) { + return; + } + + m_listingExt->setFilter(KParts::ListingFilterExtension::SubString, filter); + saveNameFilter(m_part->url(), filter); +} + +void DirFilterPlugin::slotCloseRequest() +{ + if (m_filterBar) { + m_filterBar->clear(); + m_filterBar->hide(); + if (m_focusWidget) { + m_focusWidget->setFocus(); + m_focusWidget = nullptr; + } + } +} + +void DirFilterPlugin::slotListingEvent(KParts::ListingNotificationExtension::NotificationEventType type, const KFileItemList &items) +{ + if (!m_listingExt) { + return; + } + + switch (type) { + case KParts::ListingNotificationExtension::ItemsAdded: { + const QStringList filters = m_listingExt->filter(KParts::ListingFilterExtension::MimeType).toStringList(); + Q_FOREACH (const KFileItem &item, items) { + const QString mimeType(item.mimetype()); + if (m_pMimeInfo.contains(mimeType)) { + m_pMimeInfo[mimeType].filenames.insert(item.name()); + } else { + MimeInfo &mimeInfo = m_pMimeInfo[mimeType]; + mimeInfo.useAsFilter = filters.contains(mimeType); + mimeInfo.mimeComment = item.mimeComment(); + mimeInfo.iconName = item.iconName(); + mimeInfo.filenames.insert(item.name()); + } + } + break; + } + case KParts::ListingNotificationExtension::ItemsDeleted: + Q_FOREACH (const KFileItem &item, items) { + const QString mimeType(item.mimetype()); + MimeInfoMap::iterator it = m_pMimeInfo.find(mimeType); + if (it != m_pMimeInfo.end()) { + MimeInfo &info = it.value(); + + if (info.filenames.size() > 1) { + info.filenames.remove(item.name()); + } else { + if (info.useAsFilter) { + QStringList filters = m_listingExt->filter(KParts::ListingFilterExtension::MimeType).toStringList(); + filters.removeAll(mimeType); + m_listingExt->setFilter(KParts::ListingFilterExtension::MimeType, filters); + saveTypeFilters(m_part->url(), filters); + } + m_pMimeInfo.erase(it); + } + } + } + break; + default: + return; + } + + // Enable/disable mime based filtering depending on whether the number + // document types in the current directory. + if (m_filterBar) { + m_filterBar->setEnableTypeFilterMenu(m_pMimeInfo.count() > 1); + } +} + +void DirFilterPlugin::slotReset() +{ + if (!m_part || !m_listingExt) { + return; + } + + MimeInfoMap::iterator itEnd = m_pMimeInfo.end(); + for (MimeInfoMap::iterator it = m_pMimeInfo.begin(); it != itEnd; ++it) { + it.value().useAsFilter = false; + } + + const QStringList filters; + m_listingExt->setFilter(KParts::ListingFilterExtension::MimeType, filters); + saveTypeFilters(m_part->url(), filters); +} + +void DirFilterPlugin::slotShowCount() +{ + globalSessionManager->showCount = !globalSessionManager->showCount; +} + +void DirFilterPlugin::slotMultipleFilters() +{ + globalSessionManager->useMultipleFilters = !globalSessionManager->useMultipleFilters; +} + +void DirFilterPlugin::slotShowFilterBar() +{ + QWidget *partWidget = (m_part ? m_part->widget() : nullptr); + + if (!m_filterBar && partWidget) { + m_filterBar = new FilterBar(partWidget); + m_filterBar->setTypeFilterMenu(new QMenu(m_filterBar)); + connect(m_filterBar->typeFilterMenu(), SIGNAL(aboutToShow()), + this, SLOT(slotShowPopup())); + connect(m_filterBar->typeFilterMenu(), SIGNAL(triggered(QAction*)), + this, SLOT(slotItemSelected(QAction*))); + connect(m_filterBar, SIGNAL(filterChanged(QString)), + this, SLOT(slotNameFilterChanged(QString))); + connect(m_filterBar, SIGNAL(closeRequest()), + this, SLOT(slotCloseRequest())); + QBoxLayout *layout = qobject_cast(partWidget->layout()); + if (layout) { + layout->addWidget(m_filterBar); + } + } + + // Get the widget that currently has the focus so we can properly + // restore it when the filter bar is closed. + QWidget *window = (partWidget ? partWidget->window() : nullptr); + m_focusWidget = (window ? window->focusWidget() : nullptr); + + if (m_filterBar) { + setFilterBar(); + m_filterBar->show(); + } +} + +void DirFilterPlugin::setFilterBar() +{ + SessionManager::Filters savedFilters = globalSessionManager->restore(m_part->url()); + + if (m_listingExt) { + m_listingExt->setFilter(KParts::ListingFilterExtension::MimeType, savedFilters.typeFilters); + } + + if (m_filterBar) { + m_filterBar->setNameFilter(savedFilters.nameFilter); + m_filterBar->setEnableTypeFilterMenu(m_pMimeInfo.count() > 1); + } + + Q_FOREACH (const QString &mimeType, savedFilters.typeFilters) { + if (m_pMimeInfo.contains(mimeType)) { + m_pMimeInfo[mimeType].useAsFilter = true; + } + } +} + +K_PLUGIN_FACTORY(DirFilterFactory, registerPlugin();) + +#include "dirfilterplugin.moc" diff --git a/plugins/dirfilter/dirfilterplugin.desktop b/plugins/dirfilter/dirfilterplugin.desktop new file mode 100644 index 0000000..bbea21f --- /dev/null +++ b/plugins/dirfilter/dirfilterplugin.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +Type=Service +X-KDE-PluginInfo-Author=Dawit Alemayehu,Martin Koller +X-KDE-PluginInfo-Email=adawit@kde.org,m.koller@surfeu.at +X-KDE-PluginInfo-Name=DirFilter +X-KDE-PluginInfo-Version=3.4 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Directory Filter +Name[ar]=مرشح الدليل +Name[ast]=Peñera de direutorios +Name[bg]=Филтър на папки +Name[bs]=Filter direktorijuma +Name[ca]=Filtre de directoris +Name[ca@valencia]=Filtre de directoris +Name[cs]=Filtr adresářů +Name[da]=Mappefilter +Name[de]=Ordnerfilter-Modul +Name[el]=Φίλτρο καταλόγων +Name[en_GB]=Directory Filter +Name[es]=Filtro de carpeta +Name[et]=Kataloogifilter +Name[eu]=Direktorioen iragazkia +Name[fi]=Kansiosuodatin +Name[fr]=Filtre de dossiers +Name[ga]=Scagaire Comhadlainne +Name[gl]=Filtraxe de directorios +Name[he]=מסנן תיקייה +Name[hne]=डिरेक्टरी फिल्टर +Name[hr]=Filtar direktorija +Name[hu]=Könyvtárszűrő +Name[ia]=Filtro de Directorio +Name[id]=Filter Direktori +Name[is]=Möppusía +Name[it]=Filtro cartella +Name[ja]=ディレクトリフィルタ +Name[kk]=Каталог сүзгісі +Name[km]=តម្រង​ថត +Name[ko]=디렉터리 필터 +Name[ku]=Parzûna Peldankan +Name[lt]=Aplankų filtras +Name[lv]=Mapju filtrs +Name[mr]=संचयीका गाळणी +Name[nb]=Katalogfilter +Name[nds]=Ornerfilter +Name[nl]=Mappenfilter +Name[nn]=Mappefilter +Name[pa]=ਡਾਇਰੈਕਟਰੀ ਫਿਲਟਰ +Name[pl]=Filtr katalogu +Name[pt]=Filtro de Pastas +Name[pt_BR]=Filtro de diretório +Name[ro]=Filtru de directoare +Name[ru]=Фильтр каталогов +Name[sk]=Filter adresárov +Name[sl]=Filter map +Name[sr]=Филтер фасцикли +Name[sr@ijekavian]=Филтер фасцикли +Name[sr@ijekavianlatin]=Filter fascikli +Name[sr@latin]=Filter fascikli +Name[sv]=Katalogfilter +Name[tg]=Филтри феҳраст +Name[th]=กรองไดเรกทอรี +Name[tr]=Dizin Süzgeci +Name[ug]=مۇندەرىجە سۈزگۈچ +Name[uk]=Фільтр каталогів +Name[wa]=Passete des ridants +Name[x-test]=xxDirectory Filterxx +Name[zh_CN]=目录过滤器 +Name[zh_TW]=目錄過濾器 +Comment=Filter directory view using an attribute filter +Comment[ar]=عرض مُرشِّح الدليل باستعمال مرشح الصفة +Comment[ast]=Peñera la vista de direutorios usando una peñera d'atributos +Comment[bg]=Филтриране изгледа на папките +Comment[bs]=Filtrira prikaz direktorijuma pomoću filtera atributa +Comment[ca]=Filtra la vista de directoris usant un filtre d'atributs +Comment[ca@valencia]=Filtra la vista de directoris usant un filtre d'atributs +Comment[cs]=Podle atributů filtruje zobrazení adresářů +Comment[da]=Filtrér mappevisning efter attributter +Comment[de]=Filtert die Ordneransicht anhand von Attributen +Comment[el]=Προβολή φίλτρου καταλόγων με χρήση φιλτραρίσματος ιδιοτήτων +Comment[en_GB]=Filter directory view using an attribute filter +Comment[es]=Vista de filtro de carpeta utilizando un atributo de filtrado +Comment[et]=Kataloogivaate filtreerimine omaduste filtri abil +Comment[eu]=Iragazi direktorioen ikuspegia atributuaren iragazki bat erabiliz +Comment[fi]=Suodata kansionäkymää käyttäen attribuuttisuodatinta +Comment[fr]=Filtre d'affichage des dossiers en utilisant un filtre d'attribut +Comment[ga]=Scag an t-amharc comhadlainne le scagaire tréithe +Comment[gl]=Filtra a vista dos directorios usando un filtro de atributos +Comment[he]=סנן תצוגת תיקייה באמצעות מסנן תכונה +Comment[hne]=गुन छनइया के परयोग करत करत डिरेक्टरी दृस्य छनइया करव +Comment[hr]=Filtriraj prikaz direktorija koristeći atribucijski filtar +Comment[hu]=A könyvtárnézet szűrése attribútumszűrő használatával +Comment[ia]=Filtra vista de directorio usante un filtro de attributo +Comment[id]=Filter tampilan direktori menggunakan filter atribusi +Comment[is]=Sía möppusýn með eigindasíu +Comment[it]=Filtra la vista a cartella usando un filtro +Comment[ja]=属性フィルタを使ってディレクトリビューを絞り込みます +Comment[kk]=Атрибуттар сүзгісінің көмегімен каталогтың көрінісін сүзгілеу +Comment[km]=តម្រង​ទិដ្ឋភាព​ថត​ដោយ​ប្រើ​តម្រង​គុណ​លក្ខណៈ +Comment[ko]=속성 필터를 사용하여 디렉터리 보기 거르기 +Comment[ku]=Parzûna dîtina peldankan bi parzûna çawanî re +Comment[lt]=Filtruoti aplanką naudojant atributų filtrą +Comment[lv]=Filtrē mapju skatu, izmantojot atribūtu filtru +Comment[nb]=Filtrer mappevisning ved å bruke et attributtfilter +Comment[nds]=Orneransicht över Attributen filtern +Comment[nl]=Filter de mapinhoud +Comment[nn]=Filtrer mappevising ved bruk av attributtfilter +Comment[pa]=ਇੱਕ ਗੁਣ ਫਿਲਟਰ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਡਾਇਰੈਕਟਰੀ ਵੇਖਣ ਫਿਲਟਰ +Comment[pl]=Filtruje widok katalogu przy użyciu filtra atrybutów +Comment[pt]=Filtra a visualização da pasta com um filtro de atributos +Comment[pt_BR]=Filtra a visualização do diretório usando um filtro de atributos +Comment[ro]=Filtrează vederea de directoare folosind un filtru de atribute +Comment[ru]=Отфильтровать каталоги по атрибуту +Comment[sk]=Podľa atribútov filtruje zobrazenie adresárov +Comment[sl]=Filtrira mape glede na izbrane lastnosti +Comment[sr]=Филтрира приказ фасцикли помоћу филтера атрибута +Comment[sr@ijekavian]=Филтрира приказ фасцикли помоћу филтера атрибута +Comment[sr@ijekavianlatin]=Filtrira prikaz fascikli pomoću filtera atributa +Comment[sr@latin]=Filtrira prikaz fascikli pomoću filtera atributa +Comment[sv]=Filtrerar katalogvyn med användning av ett egenskapsfilter +Comment[tg]=Намоиши филтри феҳраст аз рӯи хусусияти филтр +Comment[th]=กรองการแสดงไดเรกทอรี โดยใช้ตัวกรองคุณลักษณะ +Comment[tr]=Dizin görünümünü öznitelik süzgecinden geçir +Comment[ug]=خاسلىق سۈزگۈچكە ئىشلىتىلىدىغان سۈزگۈچ مۇندەرىجە كۆرۈنۈشى +Comment[uk]=Фільтрування перегляду каталогів за допомогою фільтра атрибутів +Comment[wa]=Passer al passete li vuwe e ridant e s' siervant d' en passete d' atribut +Comment[x-test]=xxFilter directory view using an attribute filterxx +Comment[zh_CN]=使用一个属性过滤器过滤目录视图 +Comment[zh_TW]=使用屬性來過濾目錄檢視 +Icon=view-filter +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/dirfilter/index.html diff --git a/plugins/dirfilter/dirfilterplugin.h b/plugins/dirfilter/dirfilterplugin.h new file mode 100644 index 0000000..f734d76 --- /dev/null +++ b/plugins/dirfilter/dirfilterplugin.h @@ -0,0 +1,145 @@ +/* + Copyright (C) 2000-2011 Dawit Alemayehu + + 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 DIR_FILTER_PLUGIN_H +#define DIR_FILTER_PLUGIN_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class QPushButton; +class KFileItemList; +class KLineEdit; +namespace KParts +{ +class ReadOnlyPart; +} + +class FilterBar : public QWidget +{ + Q_OBJECT + +public: + explicit FilterBar(QWidget *parent = nullptr); + ~FilterBar() override; + void selectAll(); + + QMenu *typeFilterMenu(); + void setTypeFilterMenu(QMenu *); + + bool typeFilterMenuEnabled() const; + void setEnableTypeFilterMenu(bool); + + void setNameFilter(const QString &); + +public Q_SLOTS: + void clear(); + +Q_SIGNALS: + void filterChanged(const QString &nameFilter); + void closeRequest(); + +protected: + void showEvent(QShowEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + +private: + KLineEdit *m_filterInput; + QPushButton *m_typeFilterButton; +}; + +class SessionManager +{ +public: + struct Filters { + QStringList typeFilters; + QString nameFilter; + }; + + SessionManager(); + ~SessionManager(); + Filters restore(const QUrl &url); + void save(const QUrl &url, const Filters &filters); + + bool showCount; + bool useMultipleFilters; + +protected: + void loadSettings(); + void saveSettings(); + +private: + bool m_bSettingsLoaded; + QMap m_filters; +}; + +class DirFilterPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + + DirFilterPlugin(QObject *parent, const QVariantList &); + ~DirFilterPlugin() override; + +private Q_SLOTS: + void slotReset(); + void slotOpenURL(); + void slotOpenURLCompleted(); + void slotShowPopup(); + void slotShowCount(); + void slotShowFilterBar(); + void slotMultipleFilters(); + void slotItemSelected(QAction *); + void slotNameFilterChanged(const QString &); + void slotCloseRequest(); + void slotListingEvent(KParts::ListingNotificationExtension::NotificationEventType, const KFileItemList &); + +private: + void setFilterBar(); + + struct MimeInfo { + MimeInfo() : action(nullptr), useAsFilter(false) {} + + QAction *action; + bool useAsFilter; + + QString iconName; + QString mimeComment; + + QSet filenames; + }; + typedef QMap MimeInfoMap; + + FilterBar *m_filterBar; + QWidget *m_focusWidget; + QPointer m_part; + QPointer m_listingExt; + MimeInfoMap m_pMimeInfo; +}; + +#endif + diff --git a/plugins/dirfilter/dirfilterplugin.rc b/plugins/dirfilter/dirfilterplugin.rc new file mode 100644 index 0000000..278ce7d --- /dev/null +++ b/plugins/dirfilter/dirfilterplugin.rc @@ -0,0 +1,11 @@ + + + + &Tools + + + +Extra Toolbar + + + diff --git a/plugins/fsview/22-apps-fsview.png b/plugins/fsview/22-apps-fsview.png new file mode 100644 index 0000000000000000000000000000000000000000..7301a32df6eb8922b1f73890800d0eb6e301bb82 GIT binary patch literal 802 zcmV+-1Ks?IP)YK&=D|MSpF-R~dLW+oApairr8e@pYHS6xoz4shvy~FJ6YOJ*IftU9%%)IxUGnaowuw(H3 z)kU3!fpQ_l8i$P~k;8aTB$z+Cf6o~~T;kC;B(7X5HbVFHFDHs2szW_WR8LidT0K$2 zv$`n>A=X3=G)y}UDi9A16c?0=L=nWXmubkPvS1TAmnv6FPO3C1bP!OY*xjM*TG{-- z+C*uH&B^3zlX)V={S4Pc;9}+a?T}(m8TR(^ldmI}P+Ldw1d!GApP=;aF81qNQqnN* zl)CBMdK?og!;g|+&COANb%)-Sd%@Jn`0$#^*TZxt!E?`V@pQ)-W*sezRN>J5Gwj@Q z3=suYibyj!?C4Co8i(=6v|!12+_jktQ?ycm{Zhg?MZ`}LswjU0O;_VY8s54J`)LN$ z{_*Q)HReS`kt{gZv8jDxI+%dow!B*C9XL3Al!N@r`tnCqvsJWqyzIyo!2L4fA}2(^ z;@u}W{CyfxMSXy;6A^aeocQ4ORm?m%Pq=9(d8*ZCe480z?SU^;9$x0n+BLK@Iyc7l z7ZYq87)3;Ywp9dOOPE>mmf6{RkfI9>L5IoOA6nJL#mPbPm@dOj)5`{t)>Y(DjS;Dm zCm=|36{nV}e4qE{rH!`UV>?&Dxqx|5m@?D+j<6W|a7}}~d!nf~1W!KGLzz5*0R5mq z_t*_iQJ|gGJqri|&@5Oa8>8>|5YC!xB+0H%;+1!l_MGK(bTaqcO9V71Qm+|Q@WJ8~ zW2`@^cO!uahWQg=BQ gC(OtAM2-KCA3DxNNuxB*mH+?%07*qoM6N<$f|KNNSpWb4 literal 0 HcmV?d00001 diff --git a/plugins/fsview/32-apps-fsview.png b/plugins/fsview/32-apps-fsview.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3d9115e08af6a603ab2a59b2aef2148b31232b GIT binary patch literal 862 zcmV-k1EKthP)1sJ7AI}88-0_#ac zK~#9!a$NYl1&&_U0@ArOD3ti=|1& zExkTc^FT6az+w%uHOY#e6 zM{sg<5J7;5TU$x`+kM|y+viJceX)U~$$-)phtP&naGIaM9zO%{UUS6-V3UUstCee# zC0WWCAWapMI+l}`g^VOz7Y>ibkvNqyAWtGmML^P$kkV9QRhJ-23t~ndJk3%h;No$k z+zdcu2c{f`-El0QIEuNWqHP%duR%P13xhHkxLn7+K@xKGFk&Ni{C3~pwQ5p;G{#uC zUqexxezX={Um6-f5scmWVZ;C#0%WlIr69d@;Bub?aK;k2+n0bg{M`(=Cjmq`GtgXV6<&Yl z#QGP#Cw~*l?p_+&L>{UemBb7zemIJrI8&3gkC+y~oOri;J%Qr@L@E++V(PakFsAV2 z$LTr%+fbme*nJ|&e@=}SE=1KE-^>!^79wx*C9?3fF#$n+X4ve3&)27shpUZin0wPi zC7uaN?SZUB#oq!+(hGJO_Nfl+@;yU_BCwUO%jua0qZk@Fig+D`G<}80HG~`k|&+yiO2Y> rc.cpp +$XGETTEXT *.cpp -o $podir/fsview.pot diff --git a/plugins/fsview/README b/plugins/fsview/README new file mode 100644 index 0000000..c781ab9 --- /dev/null +++ b/plugins/fsview/README @@ -0,0 +1,29 @@ +What's this? +============ + +Josef Weidendorfer +Josef.Weidendorfer@gmx.de + +FSView is a tool for showing disc utilization in a graphical form, much +like the UNIX command 'du'. The visualisation type choosen is a treemap. +Treemaps allow for showing metrics of objects in nested structures, like +sizes of files and directories on your hard disc, where the size of +directories is defined to be the sum of the size of its children. +Each object is represented by a rectangle which area is proportional to +its metric. The metric must have the property that the sum of the +children's metric of some object is equal or smaller than the objects +metric. This holds true for the file/directory sizes in the use case of +FSView. + +It's provided both as a Konqueror KPart plugin for the mime type +inode/directory, and a standalone executable. + +This was meant as a small test application and usage tutorial for +the TreeMap widget developed within KCachegrind. As it's quite cool +and small, it is now provided as a Konqueror addon in KDE. + +For a full featured graphical 'du', see KDirStat. It's quite similar +to FSView, but allows for lot of cleanup actions. + +Happy space hunting, +Josef diff --git a/plugins/fsview/fsview.cpp b/plugins/fsview/fsview.cpp new file mode 100644 index 0000000..9c97b94 --- /dev/null +++ b/plugins/fsview/fsview.cpp @@ -0,0 +1,591 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialization of TreeMap classes. + */ + +#include "fsview.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +// FSView + +QMap FSView::_dirMetric; + +FSView::FSView(Inode *base, QWidget *parent) + : TreeMapWidget(base, parent) +{ + setFieldType(0, i18n("Name")); + setFieldType(1, i18n("Size")); + setFieldType(2, i18n("File Count")); + setFieldType(3, i18n("Directory Count")); + setFieldType(4, i18n("Last Modified")); + setFieldType(5, i18n("Owner")); + setFieldType(6, i18n("Group")); + setFieldType(7, i18n("Mime Type")); + + // defaults + setVisibleWidth(4, true); + setSplitMode(TreeMapItem::Rows); + setFieldForced(0, true); // show directory names + setFieldForced(1, true); // show directory sizes + setSelectionMode(TreeMapWidget::Extended); + + _colorMode = Depth; + _pathDepth = 0; + _allowRefresh = true; + + _progressPhase = 0; + _chunkData1 = 0; + _chunkData2 = 0; + _chunkData3 = 0; + _chunkSize1 = 0; + _chunkSize2 = 0; + _chunkSize3 = 0; + _progressSize = 0; + _progress = 0; + _dirsFinished = 0; + _lastDir = nullptr; + + _config = new KConfig(QStringLiteral("fsviewrc")); + + // restore TreeMap visualization options of last execution + KConfigGroup tmconfig(_config, "TreeMap"); + restoreOptions(&tmconfig); + QString str = tmconfig.readEntry("ColorMode"); + if (!str.isEmpty()) { + setColorMode(str); + } + + if (_dirMetric.count() == 0) { + // restore metric cache + KConfigGroup cconfig(_config, "MetricCache"); + int ccount = cconfig.readEntry("Count", 0); + int i, f, d; + double s; + QString str; + for (i = 1; i <= ccount; i++) { + str = QStringLiteral("Dir%1").arg(i); + if (!cconfig.hasKey(str)) { + continue; + } + str = cconfig.readPathEntry(str, QString()); + s = cconfig.readEntry(QStringLiteral("Size%1").arg(i), 0.0); + f = cconfig.readEntry(QStringLiteral("Files%1").arg(i), 0); + d = cconfig.readEntry(QStringLiteral("Dirs%1").arg(i), 0); + if (s == 0.0 || f == 0 || d == 0) { + continue; + } + setDirMetric(str, s, f, d); + } + } + + _sm.setListener(this); +} + +FSView::~FSView() +{ + delete _config; +} + +void FSView::stop() +{ + _sm.stopScan(); +} + +void FSView::setPath(const QString &p) +{ + Inode *b = (Inode *)base(); + if (!b) { + return; + } + + //kDebug(90100) << "FSView::setPath " << p; + + // stop any previous updating + stop(); + + QFileInfo fi(p); + _path = fi.absoluteFilePath(); + if (!fi.isDir()) { + _path = fi.absolutePath(); + } + _path = QDir::cleanPath(_path); + _pathDepth = _path.count('/'); + + QUrl u = QUrl::fromLocalFile(_path); + if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("list"), QUrl(), u)) { + QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, u.toDisplayString()); + KMessageBox::sorry(this, msg); + } + + ScanDir *d = _sm.setTop(_path); + + b->setPeer(d); + + setWindowTitle(QStringLiteral("%1 - FSView").arg(_path)); + requestUpdate(b); +} + +QList FSView::selectedUrls() +{ + QList urls; + + foreach (TreeMapItem *i, selection()) { + QUrl u = QUrl::fromLocalFile(((Inode *)i)->path()); + urls.append(u); + } + return urls; +} + +bool FSView::getDirMetric(const QString &k, + double &s, unsigned int &f, unsigned int &d) +{ + QMap::iterator it; + + it = _dirMetric.find(k); + if (it == _dirMetric.end()) { + return false; + } + + s = (*it).size; + f = (*it).fileCount; + d = (*it).dirCount; + + if (0) { + kDebug(90100) << "getDirMetric " << k; + } + if (0) { + kDebug(90100) << " - got size " << s << ", files " << f; + } + + return true; +} + +void FSView::setDirMetric(const QString &k, + double s, unsigned int f, unsigned int d) +{ + if (0) kDebug(90100) << "setDirMetric '" << k << "': size " + << s << ", files " << f << ", dirs " << d << endl; + _dirMetric.insert(k, MetricEntry(s, f, d)); +} + +void FSView::requestUpdate(Inode *i) +{ + if (0) kDebug(90100) << "FSView::requestUpdate(" << i->path() + << ")" << endl; + + ScanDir *peer = i->dirPeer(); + if (!peer) { + return; + } + + peer->clear(); + i->clear(); + + if (!_sm.scanRunning()) { + QTimer::singleShot(0, this, SLOT(doUpdate())); + QTimer::singleShot(100, this, SLOT(doRedraw())); + + /* start new progress chunk */ + _progressPhase = 1; + _chunkData1 += 3; + _chunkData2 = _chunkData1 + 1; + _chunkData3 = _chunkData1 + 2; + _chunkSize1 = 0; + _chunkSize2 = 0; + _chunkSize3 = 0; + peer->setData(_chunkData1); + + _progressSize = 0; + _progress = 0; + _dirsFinished = 0; + _lastDir = nullptr; + emit started(); + } + + _sm.startScan(peer); +} + +void FSView::scanFinished(ScanDir *d) +{ + /* if finished directory was from last progress chunk, increment */ + int data = d->data(); + switch (_progressPhase) { + case 1: + if (data == _chunkData1) { + _chunkSize1--; + } + break; + case 2: + if (data == _chunkData1) { + _progress++; + } + if (data == _chunkData2) { + _chunkSize2--; + } + break; + case 3: + if ((data == _chunkData1) || + (data == _chunkData2)) { + _progress++; + } + if (data == _chunkData3) { + _chunkSize3--; + } + break; + case 4: + if ((data == _chunkData1) || + (data == _chunkData2) || + (data == _chunkData3)) { + _progress++; + } + break; + default: + break; + } + + _lastDir = d; + _dirsFinished++; + + if (0) kDebug(90100) << "FSFiew::scanFinished: " << d->path() + << ", Data " << data + << ", Progress " << _progress << "/" + << _progressSize << endl; +} + +void FSView::selected(TreeMapItem *i) +{ + setPath(((Inode *)i)->path()); +} + +void FSView::contextMenu(TreeMapItem *i, const QPoint &p) +{ + QMenu popup; + + QMenu *spopup = new QMenu(i18n("Go To")); + QMenu *dpopup = new QMenu(i18n("Stop at Depth")); + QMenu *apopup = new QMenu(i18n("Stop at Area")); + QMenu *fpopup = new QMenu(i18n("Stop at Name")); + + // choosing from the selection menu will give a selectionChanged() signal + addSelectionItems(spopup, 901, i); + popup.addMenu(spopup); + + QAction *actionGoUp = popup.addAction(i18n("Go Up")); + popup.addSeparator(); + QAction *actionStopRefresh = popup.addAction(i18n("Stop Refresh")); + actionStopRefresh->setEnabled(_sm.scanRunning()); + QAction *actionRefresh = popup.addAction(i18n("Refresh")); + actionRefresh->setEnabled(!_sm.scanRunning()); + + QAction *actionRefreshSelected = nullptr; + if (i) { + actionRefreshSelected = popup.addAction(i18n("Refresh '%1'", i->text(0))); + } + popup.addSeparator(); + addDepthStopItems(dpopup, 1001, i); + popup.addMenu(dpopup); + addAreaStopItems(apopup, 1101, i); + popup.addMenu(apopup); + addFieldStopItems(fpopup, 1201, i); + popup.addMenu(fpopup); + + popup.addSeparator(); + + QMenu *cpopup = new QMenu(i18n("Color Mode")); + addColorItems(cpopup, 1401); + popup.addMenu(cpopup); + QMenu *vpopup = new QMenu(i18n("Visualization")); + addVisualizationItems(vpopup, 1301); + popup.addMenu(vpopup); + + _allowRefresh = false; + QAction *action = popup.exec(mapToGlobal(p)); + _allowRefresh = true; + if (!action) { + return; + } + + if (action == actionGoUp) { + Inode *i = (Inode *) base(); + if (i) { + setPath(i->path() + QLatin1String("/..")); + } + } else if (action == actionStopRefresh) { + stop(); + } else if (action == actionRefreshSelected) { + //((Inode*)i)->refresh(); + requestUpdate((Inode *)i); + } else if (action == actionRefresh) { + Inode *i = (Inode *) base(); + if (i) { + requestUpdate(i); + } + } +} + +void FSView::saveMetric(KConfigGroup *g) +{ + QMap::iterator it; + int c = 1; + for (it = _dirMetric.begin(); it != _dirMetric.end(); ++it) { + g->writePathEntry(QStringLiteral("Dir%1").arg(c), it.key()); + g->writeEntry(QStringLiteral("Size%1").arg(c), (*it).size); + g->writeEntry(QStringLiteral("Files%1").arg(c), (*it).fileCount); + g->writeEntry(QStringLiteral("Dirs%1").arg(c), (*it).dirCount); + c++; + } + g->writeEntry("Count", c - 1); +} + +void FSView::setColorMode(FSView::ColorMode cm) +{ + if (_colorMode == cm) { + return; + } + + _colorMode = cm; + redraw(); +} + +bool FSView::setColorMode(const QString &mode) +{ + if (mode == QLatin1String("None")) { + setColorMode(None); + } else if (mode == QLatin1String("Depth")) { + setColorMode(Depth); + } else if (mode == QLatin1String("Name")) { + setColorMode(Name); + } else if (mode == QLatin1String("Owner")) { + setColorMode(Owner); + } else if (mode == QLatin1String("Group")) { + setColorMode(Group); + } else if (mode == QLatin1String("Mime")) { + setColorMode(Mime); + } else { + return false; + } + + return true; +} + +QString FSView::colorModeString() const +{ + QString mode; + switch (_colorMode) { + case None: mode = QStringLiteral("None"); break; + case Depth: mode = QStringLiteral("Depth"); break; + case Name: mode = QStringLiteral("Name"); break; + case Owner: mode = QStringLiteral("Owner"); break; + case Group: mode = QStringLiteral("Group"); break; + case Mime: mode = QStringLiteral("Mime"); break; + default: mode = QStringLiteral("Unknown"); break; + } + return mode; +} + +void FSView::addColorItems(QMenu *popup, int id) +{ + _colorID = id; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(colorActivated(QAction*))); + + addPopupItem(popup, i18n("None"), colorMode() == None, id++); + addPopupItem(popup, i18n("Depth"), colorMode() == Depth, id++); + addPopupItem(popup, i18n("Name"), colorMode() == Name, id++); + addPopupItem(popup, i18n("Owner"), colorMode() == Owner, id++); + addPopupItem(popup, i18n("Group"), colorMode() == Group, id++); + addPopupItem(popup, i18n("Mime Type"), colorMode() == Mime, id++); +} + +void FSView::colorActivated(QAction *a) +{ + const int id = a->data().toInt(); + if (id == _colorID) { + setColorMode(None); + } else if (id == _colorID + 1) { + setColorMode(Depth); + } else if (id == _colorID + 2) { + setColorMode(Name); + } else if (id == _colorID + 3) { + setColorMode(Owner); + } else if (id == _colorID + 4) { + setColorMode(Group); + } else if (id == _colorID + 5) { + setColorMode(Mime); + } +} + +void FSView::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape && !_pressed && (selection().size() > 0)) { + // For consistency with Dolphin, deselect all on Escape if we're not dragging. + TreeMapItem *changed = selection().commonParent(); + if (changed) { + clearSelection(changed); + } + } else { + TreeMapWidget::keyPressEvent(e); + } +} + +void FSView::saveFSOptions() +{ + KConfigGroup tmconfig(_config, "TreeMap"); + saveOptions(&tmconfig); + tmconfig.writeEntry("ColorMode", colorModeString()); + + KConfigGroup gconfig(_config, "General"); + gconfig.writeEntry("Path", _path); + + KConfigGroup cconfig(_config, "MetricCache"); + saveMetric(&cconfig); +} + +void FSView::quit() +{ + saveFSOptions(); + qApp->quit(); +} + +void FSView::doRedraw() +{ + // we update progress every 1/4 second, and redraw every second + static int redrawCounter = 0; + + bool redo = _sm.scanRunning(); + if (!redo) { + redrawCounter = 0; + } + + if ((_progress > 0) && (_progressSize > 0) && _lastDir) { + int percent = _progress * 100 / _progressSize; + if (0) kDebug(90100) << "FSView::progress " + << _progress << "/" << _progressSize + << "= " << percent << "%, " + << _dirsFinished << " dirs read, in " + << _lastDir->path() << endl; + emit progress(percent, _dirsFinished, _lastDir->path()); + } + + if (_allowRefresh && ((redrawCounter % 4) == 0)) { + if (0) { + kDebug(90100) << "doRedraw " << _sm.scanLength(); + } + redraw(); + } else { + redo = true; + } + + if (redo) { + QTimer::singleShot(500, this, SLOT(doRedraw())); + redrawCounter++; + } +} + +void FSView::doUpdate() +{ + for (int i = 0; i < 5; i++) { + switch (_progressPhase) { + case 1: + _chunkSize1 += _sm.scan(_chunkData1); + if (_chunkSize1 > 100) { + _progressPhase = 2; + + /* Go to maximally 33% by scaling with 3 */ + _progressSize = 3 * _chunkSize1; + + if (1) { + kDebug(90100) << "Phase 2: CSize " << _chunkSize1; + } + } + break; + + case 2: + /* progress phase 2 */ + _chunkSize2 += _sm.scan(_chunkData2); + /* switch to Phase 3 if we reach 80 % of Phase 2 */ + if (_progress * 3 > _progressSize * 8 / 10) { + _progressPhase = 3; + + /* Goal: Keep percentage equal from phase 2 to 3 */ + double percent = (double)_progress / _progressSize; + /* We scale by factor 2/3 afterwards */ + percent = percent * 3 / 2; + + int todo = _chunkSize2 + (_progressSize / 3 - _progress); + _progressSize = (int)((double)todo / (1.0 - percent)); + _progress = _progressSize - todo; + + /* Go to maximally 66% by scaling with 1.5 */ + _progressSize = _progressSize * 3 / 2; + + if (1) kDebug(90100) << "Phase 3: CSize " << _chunkSize2 + << ", Todo " << todo + << ", Progress " << _progress + << "/" << _progressSize << endl; + } + break; + + case 3: + /* progress phase 3 */ + _chunkSize3 += _sm.scan(_chunkData3); + /* switch to Phase 4 if we reach 80 % of Phase 3 */ + if (_progress * 3 / 2 > _progressSize * 8 / 10) { + _progressPhase = 4; + + /* Goal: Keep percentage equal from phase 2 to 3 */ + double percent = (double)_progress / _progressSize; + int todo = _chunkSize3 + (_progressSize * 2 / 3 - _progress); + _progressSize = (int)((double)todo / (1.0 - percent) + .5); + _progress = _progressSize - todo; + + if (1) kDebug(90100) << "Phase 4: CSize " << _chunkSize3 + << ", Todo " << todo + << ", Progress " << _progress + << "/" << _progressSize << endl; + } + + default: + _sm.scan(-1); + break; + } + } + + if (_sm.scanRunning()) { + QTimer::singleShot(0, this, SLOT(doUpdate())); + } else { + emit completed(_dirsFinished); + } +} + diff --git a/plugins/fsview/fsview.desktop b/plugins/fsview/fsview.desktop new file mode 100644 index 0000000..3688511 --- /dev/null +++ b/plugins/fsview/fsview.desktop @@ -0,0 +1,133 @@ +# KDE Config File +[Desktop Entry] +Type=Application +Exec=fsview -caption %c %u +MimeType=inode/directory; +Icon=fsview +DocPath=konq-plugins/fsview/index.html +Terminal=false +Name=File Size Viewer +Name[ar]=عارض حجم الملف +Name[ast]=Visor del tamañu de los ficheros +Name[bg]=Преглед на файлов размер +Name[bs]=Prikazivač veličine datoteka +Name[ca]=Visor de mida de fitxers +Name[ca@valencia]=Visor de mida de fitxers +Name[cs]=Prohlížeč velikosti souborů +Name[da]=Filstørrelsesvisning +Name[de]=Dateigrößenbetrachter +Name[el]=Προβολέας μεγέθους αρχείων +Name[en_GB]=File Size Viewer +Name[es]=Visor de tamaño de archivo +Name[et]=Failisuuruse näitaja +Name[eu]=Fitxategi-tamainaren ikustailea +Name[fi]=Tiedostokokonäkymä +Name[fr]=Afficheur de la taille de fichiers +Name[ga]=Amharcán Méid Chomhaid +Name[gl]=Visor do tamaño dos ficheiros +Name[he]=מציג גדלי קבצים +Name[hne]=फाइल आकार प्रदर्सक +Name[hr]=Preglednik veličine datoteka +Name[hu]=Fájlméret-megjelenítő +Name[ia]=Visor de dimension de file +Name[id]=Penampil Ukuran File +Name[is]=Skráastærðarskoðun +Name[it]=Visore della dimensione del file +Name[ja]=ファイルサイズビューア +Name[kk]=Файл өлшемін қарау +Name[km]=កម្មវិធី​មើល​ទំហំ​ឯកសារ +Name[ko]=파일 크기 뷰어 +Name[ku]=Nîşanderê Mezinahiya Pelê +Name[lt]=Failų dydžio stebėjimo priemonė +Name[lv]=Failu izmēra rādītajs +Name[mr]=फाईल आकार प्रदर्शक +Name[nb]=Filstørrelsesviser +Name[nds]=Dateigrött-Kieker +Name[nl]=Bestandsgrootteweergave +Name[nn]=Filstorleiksvisar +Name[pa]=ਫਾਇਲ ਸਾਈਜ਼ ਦਰਸ਼ਕ +Name[pl]=Przeglądarka rozmiaru plików +Name[pt]=Visualizador do Tamanho de Ficheiros +Name[pt_BR]=Visualizador do tamanho dos arquivos +Name[ro]=Vizualizor dimensiune fișier +Name[ru]=Просмотр размеров файлов +Name[sk]=Prehliadač veľkosti súborov +Name[sl]=Pregledovalnik velikosti datotek +Name[sr]=Приказивач величине фајлова +Name[sr@ijekavian]=Приказивач величине фајлова +Name[sr@ijekavianlatin]=Prikazivač veličine fajlova +Name[sr@latin]=Prikazivač veličine fajlova +Name[sv]=Filstorleksvisning +Name[tg]=Намоишгари андозаи файл +Name[th]=เครื่องมือดูขนาดแฟ้ม +Name[tr]=Dosya Boyutu Gösterici +Name[ug]=ھۆججەت چوڭلۇقى كۆرگۈچ +Name[uk]=Перегляд розміру файлів +Name[wa]=Håyneu del grandeu des fitchîs +Name[x-test]=xxFile Size Viewerxx +Name[zh_CN]=文件大小查看器 +Name[zh_TW]=檔案大小檢視器 +Comment=View your filesystem as a TreeMap +Comment[ar]=اعرض نظام ملفاتك كخريطة شجرة +Comment[ast]=Visualiza'l sistema de ficheros como un mapa con forma d'árbole +Comment[bg]=Показване на файловата система като дървовидна схема +Comment[bs]=Prikazuje datotečni sistem kao razgranatu mapu +Comment[ca]=Mostra el sistema de fitxers com un mapa en forma d'arbre +Comment[ca@valencia]=Mostra el sistema de fitxers com un mapa en forma d'arbre +Comment[cs]=Zobrazení souborového systému jako stromu +Comment[da]=Se dit filsystem som et TreeMap +Comment[de]=Dateisystem als Hierarchiestruktur anzeigen +Comment[el]=Προβολή του συστήματος αρχείων σας σαν δενδρική δομή +Comment[en_GB]=View your filesystem as a TreeMap +Comment[es]=Visualiza su sistema de archivos como un mapa de árbol +Comment[et]=Näitab failisüsteemi puukujulise kaardina +Comment[eu]=Ikusi zure fitxategi-sistema zuhaitz-mapa gisa +Comment[fi]=Näe tiedostojärjestelmä puukarttana +Comment[fr]=Affiche votre système de fichiers sous forme d'une arborescence +Comment[ga]=Amharc ar do chóras comhad mar Mhapa Crainn +Comment[gl]=Mostra o sistema de ficheiros como unha árbore-mapa +Comment[he]=הצג את מערכת הקבצים שלך כ־TreeMap +Comment[hne]=अपन फाइल-सिसटम ल एक ट्री-मैप मं देखव +Comment[hr]=Prikažite vaš datotečni sustav kao TreeMap +Comment[hu]=A fájlrendszerének megjelenítése fastruktúra-térképként +Comment[ia]=Vide tu systema de file como Mappa a Arbore +Comment[id]=Tampilkan sistem file anda sebagai TreeMap +Comment[is]=Skoða skráakerfið í greinasýn +Comment[it]=Visualizza il tuo filesystem come un albero +Comment[ja]=ツリーマップでファイルシステムを表示します +Comment[kk]=Файлдар жүйесін бұтақ түрінде көрсету +Comment[km]=មើល​ប្រព័ន្ធ​ឯកសារ​របស់​អ្នក​ជា TreeMap +Comment[ko]=현재 파일 시스템을 트리 지도로 보기 +Comment[ku]=Pergala-pelê wekî TreeMap bibîne +Comment[lt]=Peržiūrėti failų sistemą kaip medžio tipo žemėlapį +Comment[lv]=Parāda jūsu failu sistēmu koka kartes veidā +Comment[mr]=तुमची फाईल प्रणाली ट्री-नकाशा प्रमाणे बघा +Comment[nb]=Se på filsystemet som et tre-kart +Comment[nds]=Dien Dateisysteem as Boomkoort +Comment[nl]=Bekijk uw bestandssysteem als een boomstructuurkaart +Comment[nn]=Vis filsystemet som eit trekart +Comment[pa]=ਆਪਣਾ ਫਾਇਲ-ਸਿਸਟਮ ਇੱਕ ਲੜੀ ਢੰਗ ਨਾਲ ਵੇਖੋ +Comment[pl]=Zobacz swój system plików jako mapę drzewa +Comment[pt]=Ver o sistema de ficheiros como uma árvore-mapa +Comment[pt_BR]=Visualiza o seu sistema de arquivos em árvore +Comment[ro]=Visualizați sistemul dvs. de fișiere ca un TreeMap (hartă-arbore) +Comment[ru]=Просмотр файловой системы в виде иерархической карты +Comment[sk]=Zobrazenie súborového systému ako stromu +Comment[sl]=Prikaže datotečni sistem z gnezdenimi pravokotniki +Comment[sr]=Приказује фајл систем као разгранату мапу +Comment[sr@ijekavian]=Приказује фајл систем као разгранату мапу +Comment[sr@ijekavianlatin]=Prikazuje fajl sistem kao razgranatu mapu +Comment[sr@latin]=Prikazuje fajl sistem kao razgranatu mapu +Comment[sv]=Visa filsystemet som en trädkarta +Comment[tg]=Намоиши низоми файлҳо ҳамчун дарахти харита +Comment[th]=แสดงระบบแฟ้มของคุณแบบผังต้นไม้ +Comment[tr]=Dosya sisteminizi bir Ağaç Haritası olarak gösterir +Comment[ug]=ھۆججەت سىستېمىڭىزنى شاخسىمان خەرىتىدە كۆرسىتىدۇ +Comment[uk]=Перегляд вашої файлової системи як дерева +Comment[wa]=Veyoz vosse sistinme di fitchîs come on coxhlaedje d' åbe +Comment[x-test]=xxView your filesystem as a TreeMapxx +Comment[zh_CN]=按树形图查看您的文件系统 +Comment[zh_TW]=用樹狀圖來檢視您的檔案系統 +X-DBUS-StartupType=Multi +Categories=Qt;KDE;Utility; +X-KDE-ParentApp=konqueror diff --git a/plugins/fsview/fsview.h b/plugins/fsview/fsview.h new file mode 100644 index 0000000..34513fb --- /dev/null +++ b/plugins/fsview/fsview.h @@ -0,0 +1,159 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialization of TreeMap classes. + */ + +#ifndef FSVIEW_H +#define FSVIEW_H + +#include +#include +#include + +#include + +#include "treemap.h" +#include "inode.h" +#include "scan.h" + +class QMenu; +class KConfig; + +/* Cached Metric info config */ +class MetricEntry +{ +public: + MetricEntry() + { + size = 0.0; + fileCount = 0; + dirCount = 0; + } + MetricEntry(double s, unsigned int f, unsigned int d) + { + size = s; + fileCount = f; + dirCount = d; + } + + double size; + unsigned int fileCount, dirCount; +}; + +/** + * The root object for the treemap. + * + * Does context menu handling and + * asynchronous file size update + */ +class FSView : public TreeMapWidget, public ScanListener +{ + Q_OBJECT + +public: + enum ColorMode { None = 0, Depth, Name, Owner, Group, Mime }; + + explicit FSView(Inode *, QWidget *parent = nullptr); + ~FSView() override; + + KConfig *config() + { + return _config; + } + + void setPath(const QString &); + QString path() + { + return _path; + } + int pathDepth() + { + return _pathDepth; + } + + void setColorMode(FSView::ColorMode cm); + FSView::ColorMode colorMode() const + { + return _colorMode; + } + // returns true if string was recognized + bool setColorMode(const QString &); + QString colorModeString() const; + + void requestUpdate(Inode *); + + /* Implementation of listener interface of ScanManager. + * Used to calculate progress info */ + void scanFinished(ScanDir *) override; + + void stop(); + + static bool getDirMetric(const QString &, double &, unsigned int &, unsigned int &); + static void setDirMetric(const QString &, double, unsigned int, unsigned int); + void saveMetric(KConfigGroup *); + void saveFSOptions(); + + // for color mode + void addColorItems(QMenu *, int); + + QList selectedUrls(); + +public slots: + void selected(TreeMapItem *); + void contextMenu(TreeMapItem *, const QPoint &); + void quit(); + void doUpdate(); + void doRedraw(); + void colorActivated(QAction *); + +signals: + void started(); + void progress(int percent, int dirs, const QString &lastDir); + void completed(int dirs); + +protected: + void keyPressEvent(QKeyEvent *) override; + +private: + KConfig *_config; + ScanManager _sm; + + // when a contextMenu is shown, we don't allow async. refreshing + bool _allowRefresh; + // a cache for directory sizes with long lasting updates + static QMap _dirMetric; + + // current root path + int _pathDepth; + QString _path; + + // for progress info + int _progressPhase; + int _chunkData1, _chunkData2, _chunkData3; + int _chunkSize1, _chunkSize2, _chunkSize3; + int _progress, _progressSize, _dirsFinished; + ScanDir *_lastDir; + + ColorMode _colorMode; + int _colorID; +}; + +#endif // FSVIEW_H + diff --git a/plugins/fsview/fsview_part.cpp b/plugins/fsview/fsview_part.cpp new file mode 100644 index 0000000..1b70a16 --- /dev/null +++ b/plugins/fsview/fsview_part.cpp @@ -0,0 +1,549 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + Some file management code taken from the Dolphin file manager (C) 2006-2009, + by Peter Penz + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * The KPart embedding the FSView widget + */ + +#include "fsview_part.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +K_PLUGIN_FACTORY(FSViewPartFactory, registerPlugin();) + +// FSJob, for progress + +FSJob::FSJob(FSView *v) + : KIO::Job() +{ + _view = v; + QObject::connect(v, SIGNAL(progress(int,int,QString)), + this, SLOT(progressSlot(int,int,QString))); +} + +void FSJob::kill(bool /*quietly*/) +{ + _view->stop(); + + Job::kill(); +} + +void FSJob::progressSlot(int percent, int dirs, const QString &cDir) +{ + if (percent < 100) { + emitPercent(percent, 100); + slotInfoMessage(this, i18np("Read 1 folder, in %2", + "Read %1 folders, in %2", + dirs, cDir), QString()); + } else { + slotInfoMessage(this, i18np("1 folder", "%1 folders", dirs), QString()); + } +} + +// FSViewPart + +FSViewPart::FSViewPart(QWidget *parentWidget, + QObject *parent, + const QList & /* args */) + : KParts::ReadOnlyPart(parent) +{ + KAboutData aboutData(QStringLiteral("fsview"), i18n("FSView"), QStringLiteral("0.1"), + i18n("Filesystem Viewer"), + KAboutLicense::GPL, + i18n("(c) 2002, Josef Weidendorfer")); + setComponentData(aboutData); + + _view = new FSView(new Inode(), parentWidget); + _view->setWhatsThis(i18n("

This is the FSView plugin, a graphical " + "browsing mode showing filesystem utilization " + "by using a tree map visualization.

" + "

Note that in this mode, automatic updating " + "when filesystem changes are made " + "is intentionally not done.

" + "

For details on usage and options available, " + "see the online help under " + "menu 'Help/FSView Manual'.

")); + + _view->show(); + setWidget(_view); + + _ext = new FSViewBrowserExtension(this); + _job = nullptr; + + _areaMenu = new KActionMenu(i18n("Stop at Area"), + actionCollection()); + actionCollection()->addAction(QStringLiteral("treemap_areadir"), _areaMenu); + _depthMenu = new KActionMenu(i18n("Stop at Depth"), + actionCollection()); + actionCollection()->addAction(QStringLiteral("treemap_depthdir"), _depthMenu); + _visMenu = new KActionMenu(i18n("Visualization"), + actionCollection()); + actionCollection()->addAction(QStringLiteral("treemap_visdir"), _visMenu); + + _colorMenu = new KActionMenu(i18n("Color Mode"), + actionCollection()); + actionCollection()->addAction(QStringLiteral("treemap_colordir"), _colorMenu); + + QAction *action; + action = actionCollection()->addAction(QStringLiteral("help_fsview")); + action->setText(i18n("&FSView Manual")); + action->setIcon(QIcon::fromTheme(QStringLiteral("fsview"))); + action->setToolTip(i18n("Show FSView manual")); + action->setWhatsThis(i18n("Opens the help browser with the " + "FSView documentation")); + connect(action, SIGNAL(triggered()), this, SLOT(showHelp())); + + QObject::connect(_visMenu->menu(), SIGNAL(aboutToShow()), + SLOT(slotShowVisMenu())); + QObject::connect(_areaMenu->menu(), SIGNAL(aboutToShow()), + SLOT(slotShowAreaMenu())); + QObject::connect(_depthMenu->menu(), SIGNAL(aboutToShow()), + SLOT(slotShowDepthMenu())); + QObject::connect(_colorMenu->menu(), SIGNAL(aboutToShow()), + SLOT(slotShowColorMenu())); + + slotSettingsChanged(KGlobalSettings::SETTINGS_MOUSE); + connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), + SLOT(slotSettingsChanged(int))); + + QObject::connect(_view, SIGNAL(returnPressed(TreeMapItem*)), + _ext, SLOT(selected(TreeMapItem*))); + QObject::connect(_view, SIGNAL(selectionChanged()), + this, SLOT(updateActions())); + QObject::connect(_view, + SIGNAL(contextMenuRequested(TreeMapItem*,QPoint)), + this, + SLOT(contextMenu(TreeMapItem*,QPoint))); + + QObject::connect(_view, SIGNAL(started()), this, SLOT(startedSlot())); + QObject::connect(_view, SIGNAL(completed(int)), + this, SLOT(completedSlot(int))); + + // Create common file management actions - this is necessary in KDE4 + // as these common actions are no longer automatically part of KParts. + // Much of this is taken from Dolphin. + // FIXME: Renaming didn't even seem to work in KDE3! Implement (non-inline) renaming + // functionality. + //QAction* renameAction = m_actionCollection->addAction("rename"); + //rename->setText(i18nc("@action:inmenu Edit", "Rename...")); + //rename->setShortcut(Qt::Key_F2); + + QAction *moveToTrashAction = actionCollection()->addAction(QStringLiteral("move_to_trash")); + moveToTrashAction->setText(i18nc("@action:inmenu File", "Move to Trash")); + moveToTrashAction->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); + actionCollection()->setDefaultShortcut(moveToTrashAction, QKeySequence(QKeySequence::Delete)); + connect(moveToTrashAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), + _ext, SLOT(trash(Qt::MouseButtons,Qt::KeyboardModifiers))); + + QAction *deleteAction = actionCollection()->addAction(QStringLiteral("delete")); + deleteAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); + deleteAction->setText(i18nc("@action:inmenu File", "Delete")); + actionCollection()->setDefaultShortcut(deleteAction, QKeySequence(Qt::SHIFT | Qt::Key_Delete)); + connect(deleteAction, SIGNAL(triggered()), _ext, SLOT(del())); + + QAction *editMimeTypeAction = actionCollection()->addAction(QStringLiteral("editMimeType")); + editMimeTypeAction->setText(i18nc("@action:inmenu Edit", "&Edit File Type...")); + connect(editMimeTypeAction, SIGNAL(triggered()), _ext, SLOT(editMimeType())); + + QAction *propertiesAction = actionCollection()->addAction(QStringLiteral("properties")); + propertiesAction->setText(i18nc("@action:inmenu File", "Properties")); + propertiesAction->setIcon(QIcon::fromTheme(QStringLiteral("document-properties"))); + propertiesAction->setShortcut(Qt::ALT | Qt::Key_Return); + connect(propertiesAction, SIGNAL(triggered()), SLOT(slotProperties())); + + QTimer::singleShot(1, this, SLOT(showInfo())); + + updateActions(); + + setXMLFile(QStringLiteral("fsview_part.rc")); +} + +FSViewPart::~FSViewPart() +{ + kDebug(90100) << "FSViewPart Destructor"; + + delete _job; + _view->saveFSOptions(); +} + +void FSViewPart::slotSettingsChanged(int category) +{ + if (category != KGlobalSettings::SETTINGS_MOUSE) { + return; + } + + QObject::disconnect(_view, SIGNAL(clicked(TreeMapItem*)), + _ext, SLOT(selected(TreeMapItem*))); + QObject::disconnect(_view, SIGNAL(doubleClicked(TreeMapItem*)), + _ext, SLOT(selected(TreeMapItem*))); + + if (_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) + QObject::connect(_view, SIGNAL(clicked(TreeMapItem*)), + _ext, SLOT(selected(TreeMapItem*))); + else + QObject::connect(_view, SIGNAL(doubleClicked(TreeMapItem*)), + _ext, SLOT(selected(TreeMapItem*))); +} + +void FSViewPart::showInfo() +{ + QString info; + info = i18n("FSView intentionally does not support automatic updates " + "when changes are made to files or directories, " + "currently visible in FSView, from the outside.\n" + "For details, see the 'Help/FSView Manual'."); + + KMessageBox::information(_view, info, QString(), QStringLiteral("ShowFSViewInfo")); +} + +void FSViewPart::showHelp() +{ + KToolInvocation::startServiceByDesktopName(QStringLiteral("khelpcenter"), + QStringLiteral("help:/konqueror/index.html#fsview")); +} + +void FSViewPart::startedSlot() +{ + _job = new FSJob(_view); + _job->setUiDelegate(new KIO::JobUiDelegate()); + emit started(_job); +} + +void FSViewPart::completedSlot(int dirs) +{ + if (_job) { + _job->progressSlot(100, dirs, QString()); + delete _job; + _job = nullptr; + } + + KConfigGroup cconfig(_view->config(), "MetricCache"); + _view->saveMetric(&cconfig); + + emit completed(); +} + +void FSViewPart::slotShowVisMenu() +{ + _visMenu->menu()->clear(); + _view->addVisualizationItems(_visMenu->menu(), 1301); +} + +void FSViewPart::slotShowAreaMenu() +{ + _areaMenu->menu()->clear(); + _view->addAreaStopItems(_areaMenu->menu(), 1001, nullptr); +} + +void FSViewPart::slotShowDepthMenu() +{ + _depthMenu->menu()->clear(); + _view->addDepthStopItems(_depthMenu->menu(), 1501, nullptr); +} + +void FSViewPart::slotShowColorMenu() +{ + _colorMenu->menu()->clear(); + _view->addColorItems(_colorMenu->menu(), 1401); +} + +bool FSViewPart::openFile() // never called since openUrl is reimplemented +{ + kDebug(90100) << "FSViewPart::openFile " << localFilePath(); + _view->setPath(localFilePath()); + + return true; +} + +bool FSViewPart::openUrl(const QUrl &url) +{ + kDebug(90100) << "FSViewPart::openUrl " << url.path(); + + if (!url.isValid()) { + return false; + } + if (!url.isLocalFile()) { + return false; + } + + setUrl(url); + emit setWindowCaption(this->url().toDisplayString(QUrl::PreferLocalFile)); + + _view->setPath(this->url().path()); + + return true; +} + +bool FSViewPart::closeUrl() +{ + kDebug(90100) << "FSViewPart::closeUrl "; + + _view->stop(); + + return true; +} + +void FSViewPart::setNonStandardActionEnabled(const char *actionName, bool enabled) +{ + QAction *action = actionCollection()->action(actionName); + action->setEnabled(enabled); +} + +void FSViewPart::updateActions() +{ + int canDel = 0, canCopy = 0, canMove = 0; + QList urls; + + foreach (TreeMapItem *i, _view->selection()) { + QUrl u = QUrl::fromLocalFile(((Inode *)i)->path()); + urls.append(u); + canCopy++; + if (KProtocolManager::supportsDeleting(u)) { + canDel++; + } + if (KProtocolManager::supportsMoving(u)) { + canMove++; + } + } + + // Standard KBrowserExtension actions. + emit _ext->enableAction("copy", canCopy > 0); + emit _ext->enableAction("cut", canMove > 0); + // Custom actions. + //setNonStandardActionEnabled("rename", canMove > 0 ); // FIXME + setNonStandardActionEnabled("move_to_trash", (canDel > 0 && canMove > 0)); + setNonStandardActionEnabled("delete", canDel > 0); + setNonStandardActionEnabled("editMimeType", _view->selection().count() == 1); + setNonStandardActionEnabled("properties", _view->selection().count() == 1); + + emit _ext->selectionInfo(urls); + + if (canCopy > 0) { + stateChanged(QStringLiteral("has_selection")); + } else { + stateChanged(QStringLiteral("has_no_selection")); + } + + kDebug(90100) << "FSViewPart::updateActions, deletable " << canDel; +} + +void FSViewPart::contextMenu(TreeMapItem * /*item*/, const QPoint &p) +{ + int canDel = 0, canCopy = 0, canMove = 0; + KFileItemList items; + + foreach (TreeMapItem *i, _view->selection()) { + QUrl u = QUrl::fromLocalFile(((Inode *)i)->path()); + QString mimetype = ((Inode *)i)->mimeType().name(); + const QFileInfo &info = ((Inode *)i)->fileInfo(); + mode_t mode = + info.isFile() ? S_IFREG : + info.isDir() ? S_IFDIR : + info.isSymLink() ? S_IFLNK : (mode_t) - 1; + items.append(KFileItem(u, mimetype, mode)); + + canCopy++; + if (KProtocolManager::supportsDeleting(u)) { + canDel++; + } + if (KProtocolManager::supportsMoving(u)) { + canMove++; + } + } + + QList editActions; + KParts::BrowserExtension::ActionGroupMap actionGroups; + KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::ShowUrlOperations | + KParts::BrowserExtension::ShowProperties; + + bool addTrash = (canMove > 0); + bool addDel = false; + if (canDel == 0) { + flags |= KParts::BrowserExtension::NoDeletion; + } else { + if (!url().isLocalFile()) { + addDel = true; + } else if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { + addTrash = false; + addDel = true; + } else { + KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::IncludeGlobals); + KConfigGroup configGroup(globalConfig, "KDE"); + addDel = configGroup.readEntry("ShowDeleteCommand", false); + } + } + + if (addTrash) { + editActions.append(actionCollection()->action(QStringLiteral("move_to_trash"))); + } + if (addDel) { + editActions.append(actionCollection()->action(QStringLiteral("delete"))); + } + +// FIXME: rename is currently unavailable. Requires popup renaming. +// if (canMove) +// editActions.append(actionCollection()->action("rename")); + actionGroups.insert(QStringLiteral("editactions"), editActions); + + if (items.count() > 0) + emit _ext->popupMenu(_view->mapToGlobal(p), items, + KParts::OpenUrlArguments(), + KParts::BrowserArguments(), + flags, + actionGroups); +} + +void FSViewPart::slotProperties() +{ + QList urlList; + if (view()) { + urlList = view()->selectedUrls(); + } + + if (!urlList.isEmpty()) { + KPropertiesDialog::showDialog(urlList.first(), view()); + } +} + +// FSViewBrowserExtension + +FSViewBrowserExtension::FSViewBrowserExtension(FSViewPart *viewPart) + : KParts::BrowserExtension(viewPart) +{ + _view = viewPart->view(); +} + +FSViewBrowserExtension::~FSViewBrowserExtension() +{} + +void FSViewBrowserExtension::del() +{ + const QList urls = _view->selectedUrls(); + KIO::JobUiDelegate uiDelegate; + uiDelegate.setWindow(_view); + if (uiDelegate.askDeleteConfirmation(urls, + KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { + KIO::Job *job = KIO::del(urls); + KJobWidgets::setWindow(job, _view); + job->uiDelegate()->setAutoErrorHandlingEnabled(true); + connect(job, SIGNAL(result(KJob*)), + this, SLOT(refresh())); + } +} + +void FSViewBrowserExtension::trash(Qt::MouseButtons, Qt::KeyboardModifiers modifiers) +{ + bool deleteNotTrash = ((modifiers & Qt::ShiftModifier) != 0); + if (deleteNotTrash) { + del(); + } else { + KIO::JobUiDelegate uiDelegate; + uiDelegate.setWindow(_view); + const QList urls = _view->selectedUrls(); + if (uiDelegate.askDeleteConfirmation(urls, + KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) { + KIO::Job *job = KIO::trash(urls); + KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, urls, QUrl("trash:/"), job); + KJobWidgets::setWindow(job, _view); + job->uiDelegate()->setAutoErrorHandlingEnabled(true); + connect(job, SIGNAL(result(KJob*)), + this, SLOT(refresh())); + } + } +} + +void FSViewBrowserExtension::copySelection(bool move) +{ + QMimeData *data = new QMimeData; + data->setUrls(_view->selectedUrls()); + KIO::setClipboardDataCut(data, move); + QApplication::clipboard()->setMimeData(data); +} + +void FSViewBrowserExtension::editMimeType() +{ + Inode *i = (Inode *) _view->selection().first(); + if (i) { + KMimeTypeEditor::editMimeType(i->mimeType().name(), _view); + } +} + +// refresh treemap at end of KIO jobs +void FSViewBrowserExtension::refresh() +{ + // only need to refresh common ancestor for all selected items + TreeMapItem *commonParent = _view->selection().commonParent(); + if (!commonParent) { + return; + } + + /* if commonParent is a file, update parent directory */ + if (!((Inode *)commonParent)->isDir()) { + commonParent = commonParent->parent(); + if (!commonParent) { + return; + } + } + + kDebug(90100) << "FSViewPart::refreshing " + << ((Inode *)commonParent)->path() << endl; + + _view->requestUpdate((Inode *)commonParent); +} + +void FSViewBrowserExtension::selected(TreeMapItem *i) +{ + if (!i) { + return; + } + + QUrl url = QUrl::fromLocalFile(((Inode *)i)->path()); + emit openUrlRequest(url); +} + +#include "fsview_part.moc" diff --git a/plugins/fsview/fsview_part.desktop b/plugins/fsview/fsview_part.desktop new file mode 100644 index 0000000..046172b --- /dev/null +++ b/plugins/fsview/fsview_part.desktop @@ -0,0 +1,129 @@ +[Desktop Entry] +Name=File Size View +Name[ar]=عرض حجم الملف +Name[ast]=Vista del tamañu de los ficheros +Name[bg]=Преглед на файлов размер +Name[bs]=Prikaz veličine datoteke +Name[ca]=Vista de mida de fitxers +Name[ca@valencia]=Vista de mida de fitxers +Name[cs]=Prohlížení velikosti souboru +Name[da]=Filstørrelsesvisning +Name[de]=Dateigrößen-Ansicht +Name[el]=Προβολή Μεγέθους αρχείων +Name[en_GB]=File Size View +Name[es]=Vista de tamaño de archivo +Name[et]=Failisuuruse vaade +Name[eu]=Fitxategi-tamainaren ikuspegia +Name[fi]=Tiedostokokonäkymä +Name[fr]=Afficher la taille du fichier +Name[ga]=Amharc Méid Chomhaid +Name[gl]=Vista do tamaño dos ficheiros +Name[he]=תצוגת גדלי קבצים +Name[hne]=फाइल आकार दृस्य +Name[hr]=Prikaz veličine datoteke +Name[hu]=Fájlméret-nézet +Name[ia]=Vista de dimension de file +Name[id]=Tampilan Ukuran File +Name[is]=Skráastærðarsýn +Name[it]=Visualizza la dimensione del file +Name[ja]=ファイルサイズ表示 +Name[kk]=Файл өлшемінің көрінісі +Name[km]=ទិដ្ឋភាព​ទំហំ​ឯកសារ +Name[ko]=파일 크기 보기 +Name[ku]=Dîtina Mezinahiya Pelê +Name[lt]=Failų dydžio vaizdas +Name[lv]=Failu izmēra skats +Name[mr]=फाईल आकार दृष्य +Name[nb]=Filstørrelsesvisning +Name[nds]=Dateigrött-Ansicht +Name[nl]=Bestandsgrootte tonen +Name[nn]=Filstorleiksvising +Name[pa]=ਫਾਇਲ ਸਾਈਜ਼ ਝਲਕ +Name[pl]=Widok rozmiaru plików +Name[pt]=Vista do Tamanho dos Ficheiros +Name[pt_BR]=Visualizar o tamanho do arquivo +Name[ro]=Vizualizează dimensiune fișier +Name[ru]=Просмотр размеров файлов +Name[sk]=Prehliadanie veľkosti súborov +Name[sl]=Prikaz velikosti datotek +Name[sr]=Приказ величине фајла +Name[sr@ijekavian]=Приказ величине фајла +Name[sr@ijekavianlatin]=Prikaz veličine fajla +Name[sr@latin]=Prikaz veličine fajla +Name[sv]=Filstorleksvy +Name[tg]=Намоиш аднозаи файл +Name[th]=ดูขนาดแฟ้ม +Name[tr]=Dosya Boyutu Görünümü +Name[ug]=ھۆججەت چوڭلۇقى كۆرۈنۈش +Name[uk]=Перегляд розміру файлів +Name[wa]=Voeyaedje del grandeu d' on fitchî +Name[x-test]=xxFile Size Viewxx +Name[zh_CN]=文件大小视图 +Name[zh_TW]=檔案大小檢視 +Comment=Enables a proportional view of directories and files based on file size +Comment[ar]=تمكن العرض النسبي للأدلة و الملفات بالاعتماد على حجم الملف +Comment[ast]=Activa una vista proporcional de direutorios y ficheros según los sos tamaños +Comment[bg]=Включване на пропорционален изглед на папки и файлове според размера им +Comment[bs]=Uključuje proporcionalni prikaz fascikli i datoteka na osnovu njihove veličine +Comment[ca]=Habilita una vista proporcional dels directoris i fitxers basada en la mida dels fitxers +Comment[ca@valencia]=Habilita una vista proporcional dels directoris i fitxers basada en la mida dels fitxers +Comment[cs]=Umožňuje proporcionální zobrazení adresářů podle velikosti +Comment[da]=Aktiverer proportional visning af mapper og filer baseret pÃ¥ filstørrelse +Comment[de]=Zeigt Ordner und Dateien in einer Proportionalansicht basierend auf der Dateigröße an +Comment[el]=Ενεργοποιεί την μεταβλητού μεγέθους προβολή των αρχείων και καταλόγων ανάλογα με το μέγεθος αρχείου +Comment[en_GB]=Enables a proportional view of directories and files based on file size +Comment[es]=Activa una vista proporcional de directorios y archivos basada en el tamaño del archivo +Comment[et]=Lülitab sisse kataloogide ja failide proportsionaalse vaate nende failisuuruse põhjal +Comment[eu]=Fitxategi-tamainan oinarritutako direktorio eta fitxategien ikuspegi proportzionala gaitzen du +Comment[fi]=Ottaa käyttöön hakemistojen ja tiedostojen osittaisnäkymän tiedostokokoon perustuen +Comment[fr]=Active un affichage proportionnel des dossiers et des fichiers reposant sur la taille des fichiers +Comment[ga]=Cumasaigh amharc cionmhar ar chomhadlanna agus ar chomhaid, bunaithe ar a méid +Comment[gl]=Activa unha vista proporcional dos directorios e ficheiros baseada no tamaño +Comment[he]=אפשר תצוגה פרופורציונאלית של תיקיות וקבצים על פי גודל הקובץ. +Comment[hne]=फाइल आकार मं आधार से डिरेक्टरी अउ फाइल मन के आनुपातिक दृस्य सक्छम करथे +Comment[hr]=Omogućuje proporcionalni prikaz direktorija i datoteka baziran na njihovoj veličini +Comment[hu]=A könyvtárak és fájlok fájlméreten alapuló arányos nézetének engedélyezése +Comment[ia]=Habilita un vista proportional de directorios e files basate sur le grandor de file +Comment[id]=Fungsikan tampilan proporsional direktori dan file berdasarkan ukuran file +Comment[is]=Virkjar sýn á möppur og skrár í hlutfalli við skráastærð þeirra +Comment[it]=Permette una visualizzazione proporzionale delle cartelle e dei file basata sulla dimensione +Comment[ja]=ディレクトリとファイルをそのサイズに比例した大きさで表示します +Comment[kk]=Қапшықтар мен файлдарды өлшеміне сәйекесті қылып көрсету +Comment[km]=អនុញ្ញាត​ទិដ្ឋភាព​សមាមាត្រ​នៃ​ថត និង​ឯកសារ​ដែល​មាន​មូលដ្ឋាន​លើ​ទំហំ​ឯកសារ +Comment[ko]=디렉터리와 파일의 크기에 따른 보기 +Comment[ku]=Birêje dîtina peldankan û pelên gorê mezinahiyê çalak dike +Comment[lt]=Ä®jungia proporcingą dydžiu grįstą aplankų ir rinkmenų peržiÅ«rą +Comment[lv]=Ieslēdz proporcionālo mapju un failu skatu, balstoties uz failu izmēriem +Comment[mr]=संचयीका व फाईल्स आकारांच्या प्रमाणात बघा +Comment[nb]=Tilbyr en proporsjonal visning av mapper og filer basert pÃ¥ filstørrelse +Comment[nds]=Wiest Ornern un Dateien na ehr Grötten +Comment[nl]=Biedt een proportionele weergave van mappen en bestanden gebaseerd op hun grootte +Comment[nn]=Gjev ei proporsjonal vising av mapper og filer basert pÃ¥ filstorleiken +Comment[pa]=ਫਾਇਲ ਸਾਈਜ਼ ਦੇ ਅਧਾਰ ਮੁਤਾਬਕ ਡਾਇਰੈਕਟਰੀਆਂ ਅਤੇ ਫਾਇਲਾਂ ਨੂੰ ਵੇਖਾਉਣਾ ਯੋਗ +Comment[pl]=Włącza widok proporcjonalny katalogów i plików bazując na rozmiarze pliku +Comment[pt]=Activa uma vista proporcional das pastas e ficheiros com base nos seus tamanhos +Comment[pt_BR]=Ativa uma visualização proporcional dos arquivos e pastas baseada no tamanho dos arquivos +Comment[ro]=Permite o vedere proporțională a directoarelor și fișierelor bazat pe dimensiunea acestora +Comment[ru]=Включает отображение каталогов и файлов пропорционально их размеру +Comment[sk]=Umožňuje proporcionálne zobrazenie adresárov podla veľkosti +Comment[sl]=Omogoči sorazmeren prikaz datotek in map glede na velikost +Comment[sr]=Укључује пропорционални приказ фасцикли и фајлова на основу њихове величине +Comment[sr@ijekavian]=Укључује пропорционални приказ фасцикли и фајлова на основу њихове величине +Comment[sr@ijekavianlatin]=Uključuje proporcionalni prikaz fascikli i fajlova na osnovu njihove veličine +Comment[sr@latin]=Uključuje proporcionalni prikaz fascikli i fajlova na osnovu njihove veličine +Comment[sv]=Möjliggör proportionell visning av kataloger och filer baserat pÃ¥ filstorlek +Comment[tg]=Намоиши файлҳо ва феҳрастҳоро аз рӯи андозаи он фаъол мекунад +Comment[th]=เปิดใช้การแสดงขนาดของแฟ้มและไดเรกทอรีต่าง ๆ โดยอิงข้อมูลจากขนาดแฟ้ม +Comment[tr]=Dosya boyutu tabanlı olarak dizin ve dosyaların orantılı görünümünü sağlar +Comment[ug]=ھۆججەت چوڭلۇقى ئاساسىدىكى مۇندەرىجە ۋە ھۆججەت كۆرسىتىش نىسبىتىنىڭ كۆرۈنۈشىنى قوزغىتىدۇ +Comment[uk]=Пропорційний показ тек і файлів залежно від їхнього розміру +Comment[wa]=Permet ene vuwe des fitchîs et ridants ki s' fwait sorlon l' grandeu des fitchîs +Comment[x-test]=xxEnables a proportional view of directories and files based on file sizexx +Comment[zh_CN]=启用一个基于文件大小的查看目录和文件的比例视图 +Comment[zh_TW]=以檔案與目錄的大小來開啟比例檢視圖 +MimeType=inode/directory; +ServiceTypes=KParts/ReadOnlyPart +X-KDE-Library=fsviewpart +Type=Service +Icon=fsview +DocPath=konq-plugins/fsview/index.html diff --git a/plugins/fsview/fsview_part.h b/plugins/fsview/fsview_part.h new file mode 100644 index 0000000..ade612f --- /dev/null +++ b/plugins/fsview/fsview_part.h @@ -0,0 +1,132 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * The KPart embedding the FSView widget + */ + +#ifndef FSVIEW_PART_H +#define FSVIEW_PART_H + +#include +#include +#include + +#include "fsview.h" + +class KActionMenu; + +class FSViewPart; + +class FSViewBrowserExtension : public KParts::BrowserExtension +{ + Q_OBJECT + +public: + explicit FSViewBrowserExtension(FSViewPart *viewPart); + ~FSViewBrowserExtension() override; + +protected slots: + void selected(TreeMapItem *); + void refresh(); + + void copy() + { + copySelection(false); + } + void cut() + { + copySelection(true); + } + void trash(Qt::MouseButtons, Qt::KeyboardModifiers modifiers); + void del(); + void editMimeType(); + +private: + void copySelection(bool move); + + FSView *_view; +}; + +class FSJob: public KIO::Job +{ + Q_OBJECT + +public: + explicit FSJob(FSView *); + + virtual void kill(bool quietly = true); + +public slots: + void progressSlot(int percent, int dirs, const QString &lastDir); + +private: + FSView *_view; +}; + +class FSViewPart : public KParts::ReadOnlyPart +{ + Q_OBJECT + Q_PROPERTY(bool supportsUndo READ supportsUndo) +public: + FSViewPart(QWidget *parentWidget, + QObject *parent, const QList &args); + + ~FSViewPart() override; + + bool supportsUndo() const + { + return false; + } + + FSView *view() const + { + return _view; + } + +public slots: + void updateActions(); + void contextMenu(TreeMapItem *, const QPoint &); + void showInfo(); + void showHelp(); + void startedSlot(); + void completedSlot(int dirs); + void slotShowVisMenu(); + void slotShowAreaMenu(); + void slotShowDepthMenu(); + void slotShowColorMenu(); + void slotSettingsChanged(int); + void slotProperties(); + +protected: + /** + * This must be implemented by each part + */ + bool openFile() override; + bool openUrl(const QUrl &url) override; + bool closeUrl() override; + +private: + FSView *_view; + FSJob *_job; + FSViewBrowserExtension *_ext; + KActionMenu *_visMenu, *_areaMenu, *_depthMenu, *_colorMenu; + void setNonStandardActionEnabled(const char *actionName, bool enabled); +}; + +#endif // FSVIEW_PART_H diff --git a/plugins/fsview/fsview_part.rc b/plugins/fsview/fsview_part.rc new file mode 100644 index 0000000..f691397 --- /dev/null +++ b/plugins/fsview/fsview_part.rc @@ -0,0 +1,37 @@ + + + + &Edit + + + + + + + + + &View + + + + + + + &Help + + + + + + + + + + + + + + + + + diff --git a/plugins/fsview/inode.cpp b/plugins/fsview/inode.cpp new file mode 100644 index 0000000..ceaaabb --- /dev/null +++ b/plugins/fsview/inode.cpp @@ -0,0 +1,429 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialization of TreeMapItem class. + */ + +#include "inode.h" +#include +#include +#include +#include +#include +#include +#include "scan.h" +#include "fsview.h" + +// Inode + +Inode::Inode() +{ + _dirPeer = nullptr; + _filePeer = nullptr; + init(QString()); +} + +Inode::Inode(ScanDir *d, Inode *parent) + : TreeMapItem(parent) +{ + QString absPath; + if (parent) { + absPath = parent->path(); + if (!absPath.endsWith(QLatin1Char('/'))) { + absPath += QLatin1Char('/'); + } + } + absPath += d->name(); + + _dirPeer = d; + _filePeer = nullptr; + + init(absPath); +} + +Inode::Inode(ScanFile *f, Inode *parent) + : TreeMapItem(parent) +{ + QString absPath; + if (parent) { + absPath = parent->path() + QLatin1Char('/'); + } + absPath += f->name(); + + _dirPeer = nullptr; + _filePeer = f; + + init(absPath); +} + +Inode::~Inode() +{ + if (0) kDebug(90100) << "~Inode [" << path() + << "]" << endl; + + /* reset Listener of old Peer */ + if (_dirPeer) { + _dirPeer->setListener(nullptr); + } + if (_filePeer) { + _filePeer->setListener(nullptr); + } +} + +void Inode::setPeer(ScanDir *d) +{ + /* reset Listener of old Peer */ + if (_dirPeer) { + _dirPeer->setListener(nullptr); + } + if (_filePeer) { + _filePeer->setListener(nullptr); + } + + _dirPeer = d; + _filePeer = nullptr; + init(d->name()); +} + +QString Inode::path() const +{ + return _info.absoluteFilePath(); +} + +void Inode::init(const QString &path) +{ + if (0) kDebug(90100) << "Inode::init [" << path + << "]" << endl; + + _info = QFileInfo(path); + + if (!FSView::getDirMetric(path, _sizeEstimation, + _fileCountEstimation, + _dirCountEstimation)) { + _sizeEstimation = 0.0; + _fileCountEstimation = 0; + _dirCountEstimation = 0; + } + + _mimeSet = false; + _mimePixmapSet = false; + _resortNeeded = false; + + clear(); + + /* we want to get notifications about dir changes */ + if (_dirPeer) { + _dirPeer->setListener(this); + } + if (_filePeer) { + _filePeer->setListener(this); + } + + if (_dirPeer && _dirPeer->scanFinished()) { + scanFinished(_dirPeer); + } +} + +/* ScanListener interface */ +void Inode::sizeChanged(ScanDir *d) +{ + if (0) kDebug(90100) << "Inode::sizeChanged [" << path() << "] in " + << d->name() << ": size " << d->size() << endl; + + _resortNeeded = true; +} + +void Inode::scanFinished(ScanDir *d) +{ + if (0) kDebug(90100) << "Inode::scanFinished [" << path() << "] in " + << d->name() << ": size " << d->size() << endl; + + _resortNeeded = true; + + /* no estimation any longer */ + _sizeEstimation = 0.0; + _fileCountEstimation = 0; + _dirCountEstimation = 0; + + // cache metrics if "important" (for "/usr" is dd==3) + int dd = ((FSView *)widget())->pathDepth() + depth(); + int files = d->fileCount(); + int dirs = d->dirCount(); + + if ((files < 500) && (dirs < 50)) { + if (dd > 4 && (files < 50) && (dirs < 5)) { + return; + } + } + + FSView::setDirMetric(path(), d->size(), files, dirs); +} + +void Inode::destroyed(ScanDir *d) +{ + if (_dirPeer == d) { + _dirPeer = nullptr; + } + + // remove children + clear(); +} + +void Inode::destroyed(ScanFile *f) +{ + if (_filePeer == f) { + _filePeer = nullptr; + } +} + +TreeMapItemList *Inode::children() +{ + if (!_dirPeer) { + return nullptr; + } + + if (!_children) { + if (!_dirPeer->scanStarted()) { + return nullptr; + } + + _children = new TreeMapItemList; + + setSorting(-1); + + ScanFileVector &files = _dirPeer->files(); + if (files.count() > 0) { + ScanFileVector::iterator it; + for (it = files.begin(); it != files.end(); ++it) { + new Inode(&(*it), this); + } + } + + ScanDirVector &dirs = _dirPeer->dirs(); + if (dirs.count() > 0) { + ScanDirVector::iterator it; + for (it = dirs.begin(); it != dirs.end(); ++it) { + new Inode(&(*it), this); + } + } + + setSorting(-2); + _resortNeeded = false; + } + + if (_resortNeeded) { + resort(); + _resortNeeded = false; + } + + return _children; +} + +double Inode::size() const +{ + // sizes of files are always correct + if (_filePeer) { + return _filePeer->size(); + } + if (!_dirPeer) { + return 0; + } + + double size = _dirPeer->size(); + return (_sizeEstimation > size) ? _sizeEstimation : size; +} + +double Inode::value() const +{ + return size(); +} + +unsigned int Inode::fileCount() const +{ + unsigned int fileCount = 1; + + if (_dirPeer) { + fileCount = _dirPeer->fileCount(); + } + + if (_fileCountEstimation > fileCount) { + fileCount = _fileCountEstimation; + } + + return fileCount; +} + +unsigned int Inode::dirCount() const +{ + unsigned int dirCount = 0; + + if (_dirPeer) { + dirCount = _dirPeer->dirCount(); + } + + if (_dirCountEstimation > dirCount) { + dirCount = _dirCountEstimation; + } + + return dirCount; +} + +QColor Inode::backColor() const +{ + QString n; + int id = 0; + + switch (((FSView *)widget())->colorMode()) { + case FSView::Depth: { + int d = ((FSView *)widget())->pathDepth() + depth(); + return QColor::fromHsv((100 * d) % 360, 192, 128); + } + + case FSView::Name: n = text(0); break; + case FSView::Owner: id = _info.ownerId(); break; + case FSView::Group: id = _info.groupId(); break; + case FSView::Mime: n = text(7); break; + + default: + break; + } + + if (id > 0) { + n = QString::number(id); + } + + if (n.isEmpty()) { + return widget()->palette().button().color(); + } + + QByteArray tmpBuf = n.toLocal8Bit(); + const char *str = tmpBuf.data(); + int h = 0, s = 100; + while (*str) { + h = (h * 37 + s * (unsigned) * str) % 256; + s = (s * 17 + h * (unsigned) * str) % 192; + str++; + } + return QColor::fromHsv(h, 64 + s, 192); +} + +QMimeType Inode::mimeType() const +{ + if (!_mimeSet) { + QMimeDatabase db; + _mimeType = db.mimeTypeForUrl(QUrl::fromLocalFile(path())); + + _mimeSet = true; + } + return _mimeType; +} + +QString Inode::text(int i) const +{ + if (i == 0) { + QString name; + if (_dirPeer) { + name = _dirPeer->name(); + if (!name.endsWith(QLatin1Char('/'))) { + name += QLatin1Char('/'); + } + } else if (_filePeer) { + name = _filePeer->name(); + } + + return name; + } + if (i == 1) { + QString text; + double s = size(); + + if (s < 1000) { + text = QStringLiteral("%1 B").arg((int)(s + .5)); + } else if (s < 10 * 1024) { + text = QStringLiteral("%1 kB").arg(KGlobal::locale()->formatNumber(s / 1024 + .005, 2)); + } else if (s < 100 * 1024) { + text = QStringLiteral("%1 kB").arg(KGlobal::locale()->formatNumber(s / 1024 + .05, 1)); + } else if (s < 1000 * 1024) { + text = QStringLiteral("%1 kB").arg((int)(s / 1024 + .5)); + } else if (s < 10 * 1024 * 1024) { + text = QStringLiteral("%1 MB").arg(KGlobal::locale()->formatNumber(s / 1024 / 1024 + .005, 2)); + } else if (s < 100 * 1024 * 1024) { + text = QStringLiteral("%1 MB").arg(KGlobal::locale()->formatNumber(s / 1024 / 1024 + .05, 1)); + } else if (s < 1000 * 1024 * 1024) { + text = QStringLiteral("%1 MB").arg((int)(s / 1024 / 1024 + .5)); + } else { + text = QStringLiteral("%1 GB").arg(KGlobal::locale()->formatNumber(s / 1024 / 1024 / 1024 + .005, 2)); + } + + if (_sizeEstimation > 0) { + text += '+'; + } + return text; + } + + if ((i == 2) || (i == 3)) { + /* file/dir count makes no sense for files */ + if (_filePeer) { + return QString(); + } + + QString text; + unsigned int f = (i == 2) ? fileCount() : dirCount(); + + if (f > 0) { + while (f > 1000) { + text = QStringLiteral("%1 %2").arg(QString::number(f).right(3)).arg(text); + f /= 1000; + } + text = QStringLiteral("%1 %2").arg(QString::number(f)).arg(text); + if (_fileCountEstimation > 0) { + text += '+'; + } + } + return text; + } + + if (i == 4) { + return _info.lastModified().toString(); + } + if (i == 5) { + return _info.owner(); + } + if (i == 6) { + return _info.group(); + } + if (i == 7) { + return mimeType().comment(); + } + return QString(); +} + +QPixmap Inode::pixmap(int i) const +{ + if (i != 0) { + return QPixmap(); + } + + if (!_mimePixmapSet) { + QUrl u = QUrl::fromLocalFile(path()); + _mimePixmap = KIconLoader::global()->loadMimeTypeIcon(KIO::iconNameForUrl(u), KIconLoader::Small); + _mimePixmapSet = true; + } + return _mimePixmap; +} diff --git a/plugins/fsview/inode.h b/plugins/fsview/inode.h new file mode 100644 index 0000000..07ca8ca --- /dev/null +++ b/plugins/fsview/inode.h @@ -0,0 +1,108 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialization of TreeMapItem class. + */ + +#ifndef INODE_H +#define INODE_H + +#include +#include +#include +#include + +#include + +#include "treemap.h" +#include "scan.h" + +/** + * A specialized version of a TreeMapItem + * for representation of an Directory or File. + * + * These are dynamically created on drawing. + * The real breadth-first scanning of the filesystem + * uses ScanDir:scan. + */ +class Inode: public TreeMapItem, public ScanListener +{ +public: + Inode(); + Inode(ScanDir *, Inode *); + Inode(ScanFile *, Inode *); + ~Inode() override; + void init(const QString &); + + void setPeer(ScanDir *); + + TreeMapItemList *children() override; + + double value() const override; + double size() const; + unsigned int fileCount() const; + unsigned int dirCount() const; + QString path() const; + QString text(int i) const override; + QPixmap pixmap(int i) const override; + QColor backColor() const override; + QMimeType mimeType() const; + + const QFileInfo &fileInfo() const + { + return _info; + } + ScanDir *dirPeer() + { + return _dirPeer; + } + ScanFile *filePeer() + { + return _filePeer; + } + bool isDir() + { + return (_dirPeer != nullptr); + } + + void sizeChanged(ScanDir *) override; + void scanFinished(ScanDir *) override; + void destroyed(ScanDir *) override; + void destroyed(ScanFile *) override; + +private: + void setMetrics(double, unsigned int); + + QFileInfo _info; + ScanDir *_dirPeer; + ScanFile *_filePeer; + + double _sizeEstimation; + unsigned int _fileCountEstimation, _dirCountEstimation; + + bool _resortNeeded; + + // Cached values, calculated lazy. + // This means a change even in const methods, thus has to be "mutable" + mutable bool _mimeSet, _mimePixmapSet; + mutable QMimeType _mimeType; + mutable QPixmap _mimePixmap; +}; + +#endif diff --git a/plugins/fsview/main.cpp b/plugins/fsview/main.cpp new file mode 100644 index 0000000..562a943 --- /dev/null +++ b/plugins/fsview/main.cpp @@ -0,0 +1,56 @@ +/***************************************************** + * FSView, a simple TreeMap application + * + * (C) 2002, Josef Weidendorfer + */ + +#include +#include + +#include "fsview.h" +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + // KDE compliant startup + KAboutData aboutData(QStringLiteral("fsview"), i18n("FSView"), QStringLiteral("0.1"), + i18n("Filesystem Viewer"), + KAboutLicense::GPL, + i18n("(c) 2002, Josef Weidendorfer")); + QApplication app(argc, argv); + QCommandLineParser parser; + KAboutData::setApplicationData(aboutData); + aboutData.setupCommandLine(&parser); + parser.process(app); + aboutData.processCommandLine(&parser); + + parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("+[folder]"), i18n("View filesystem starting from this folder"))); + + KConfigGroup gconfig(KSharedConfig::openConfig(), "General"); + QString path = gconfig.readPathEntry("Path", QStringLiteral(".")); + + if (parser.positionalArguments().count() > 0) { + path = parser.positionalArguments().at(0); + } + + // TreeMap Widget as toplevel window + FSView w(new Inode()); + + QObject::connect(&w, SIGNAL(clicked(TreeMapItem*)), + &w, SLOT(selected(TreeMapItem*))); + QObject::connect(&w, SIGNAL(returnPressed(TreeMapItem*)), + &w, SLOT(selected(TreeMapItem*))); + QObject::connect(&w, SIGNAL(contextMenuRequested(TreeMapItem*,QPoint)), + &w, SLOT(contextMenu(TreeMapItem*,QPoint))); + + w.setPath(path); + w.show(); + + return app.exec(); +} diff --git a/plugins/fsview/scan.cpp b/plugins/fsview/scan.cpp new file mode 100644 index 0000000..e9d0e71 --- /dev/null +++ b/plugins/fsview/scan.cpp @@ -0,0 +1,437 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "scan.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "inode.h" + +// ScanManager + +ScanManager::ScanManager() +{ + _topDir = nullptr; + _listener = nullptr; +} + +ScanManager::ScanManager(const QString &path) +{ + _topDir = nullptr; + _listener = nullptr; + setTop(path); +} + +ScanManager::~ScanManager() +{ + stopScan(); + delete _topDir; +} + +void ScanManager::setListener(ScanListener *l) +{ + _listener = l; +} + +ScanDir *ScanManager::setTop(const QString &path, int data) +{ + stopScan(); + if (_topDir) { + delete _topDir; + _topDir = nullptr; + } + if (!path.isEmpty()) { + _topDir = new ScanDir(path, this, nullptr, data); + } + return _topDir; +} + +bool ScanManager::scanRunning() +{ + if (!_topDir) { + return false; + } + + return _topDir->scanRunning(); +} + +void ScanManager::startScan(ScanDir *from) +{ + if (!_topDir) { + return; + } + if (!from) { + from = _topDir; + } + + if (scanRunning()) { + stopScan(); + } + + from->clear(); + if (from->parent()) { + from->parent()->setupChildRescan(); + } + + _list.append(new ScanItem(from->path(), from)); +} + +void ScanManager::stopScan() +{ + if (!_topDir) { + return; + } + + if (0) kDebug(90100) << "ScanManager::stopScan, scanLength " + << _list.count() << endl; + + while (!_list.isEmpty()) { + ScanItem *si = _list.takeFirst(); + si->dir->finish(); + delete si; + } +} + +int ScanManager::scan(int data) +{ + if (_list.isEmpty()) { + return false; + } + ScanItem *si = _list.takeFirst(); + + int newCount = si->dir->scan(si, _list, data); + delete si; + + return newCount; +} + +// ScanFile + +ScanFile::ScanFile() +{ + _size = 0; + _listener = nullptr; +} + +ScanFile::ScanFile(const QString &n, KIO::fileoffset_t s) +{ + _name = n; + _size = s; + _listener = nullptr; +} + +ScanFile::~ScanFile() +{ + if (_listener) { + _listener->destroyed(this); + } +} + +// ScanDir + +ScanDir::ScanDir() +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _parent = nullptr; + _manager = nullptr; + _listener = nullptr; + _data = 0; +} + +ScanDir::ScanDir(const QString &n, ScanManager *m, + ScanDir *p, int data) + : _name(n) +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _parent = p; + _manager = m; + _listener = nullptr; + _data = data; +} + +ScanDir::~ScanDir() +{ + if (_listener) { + _listener->destroyed(this); + } +} + +void ScanDir::setListener(ScanListener *l) +{ + _listener = l; +} + +QString ScanDir::path() +{ + if (_parent) { + QString p = _parent->path(); + if (!p.endsWith(QLatin1Char('/'))) { + p += QLatin1Char('/'); + } + return p + _name; + } + + return _name; +} + +void ScanDir::clear() +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _files.clear(); + _dirs.clear(); +} + +void ScanDir::update() +{ + if (!_dirty) { + return; + } + _dirty = false; + + _fileCount = 0; + _dirCount = 0; + _size = 0; + + if (_dirsFinished == -1) { + return; + } + + if (_files.count() > 0) { + _fileCount += _files.count(); + _size = _fileSize; + } + if (_dirs.count() > 0) { + _dirCount += _dirs.count(); + ScanDirVector::iterator it; + for (it = _dirs.begin(); it != _dirs.end(); ++it) { + (*it).update(); + _fileCount += (*it)._fileCount; + _dirCount += (*it)._dirCount; + _size += (*it)._size; + } + } +} + +bool ScanDir::isForbiddenDir(QString &d) +{ + static QSet *s = nullptr; + + if (!s) { + s = new QSet; + // directories without real files on Linux + // TODO: should be OS specific + s->insert(QStringLiteral("/proc")); + s->insert(QStringLiteral("/dev")); + s->insert(QStringLiteral("/sys")); + } + return (s->contains(d)); +} + +int ScanDir::scan(ScanItem *si, ScanItemList &list, int data) +{ + clear(); + _dirsFinished = 0; + _fileSize = 0; + _dirty = true; + + if (isForbiddenDir(si->absPath)) { + if (_parent) { + _parent->subScanFinished(); + } + return 0; + } + + QUrl u = QUrl::fromLocalFile(si->absPath); + if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("list"), QUrl(), u)) { + if (_parent) { + _parent->subScanFinished(); + } + + return 0; + } + + QDir d(si->absPath); + const QStringList fileList = d.entryList(QDir::Files | + QDir::Hidden | QDir::NoSymLinks); + + if (fileList.count() > 0) { + QT_STATBUF buff; + + _files.reserve(fileList.count()); + + QStringList::ConstIterator it; + for (it = fileList.constBegin(); it != fileList.constEnd(); ++it) { + QString tmp(si->absPath + QLatin1Char('/') + (*it)); + if (QT_LSTAT(tmp.toStdString().c_str(), &buff) != 0) { + continue; + } + _files.append(ScanFile(*it, buff.st_size)); + _fileSize += buff.st_size; + } + } + + const QStringList dirList = d.entryList(QDir::Dirs | + QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot); + + if (dirList.count() > 0) { + _dirs.reserve(dirList.count()); + + QStringList::ConstIterator it; + for (it = dirList.constBegin(); it != dirList.constEnd(); ++it) { + _dirs.append(ScanDir(*it, _manager, this, data)); + QString newpath = si->absPath; + if (!newpath.endsWith(QChar('/'))) { + newpath.append("/"); + } + newpath.append(*it); + list.append(new ScanItem(newpath, &(_dirs.last()))); + } + _dirCount += _dirs.count(); + } + + callScanStarted(); + callSizeChanged(); + + if (_dirs.count() == 0) { + callScanFinished(); + + if (_parent) { + _parent->subScanFinished(); + } + } + + return _dirs.count(); +} + +void ScanDir::subScanFinished() +{ + _dirsFinished++; + callSizeChanged(); + + if (0) kDebug(90100) << "ScanDir::subScanFinished [" << path() + << "]: " << _dirsFinished << "/" << _dirs.count() << endl; + + if (_dirsFinished < _dirs.count()) { + return; + } + + /* all subdirs read */ + callScanFinished(); + + if (_parent) { + _parent->subScanFinished(); + } +} + +void ScanDir::finish() +{ + if (scanRunning()) { + _dirsFinished = _dirs.count(); + callScanFinished(); + } + + if (_parent) { + _parent->finish(); + } +} + +void ScanDir::setupChildRescan() +{ + if (_dirs.count() == 0) { + return; + } + + _dirsFinished = 0; + ScanDirVector::iterator it; + for (it = _dirs.begin(); it != _dirs.end(); ++it) + if ((*it).scanFinished()) { + _dirsFinished++; + } + + if (_parent && + (_dirsFinished < _dirs.count())) { + _parent->setupChildRescan(); + } + + callScanStarted(); +} + +void ScanDir::callScanStarted() +{ + if (0) kDebug(90100) << "ScanDir:Started [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + ScanListener *mListener = _manager ? _manager->listener() : nullptr; + + if (_listener) { + _listener->scanStarted(this); + } + if (mListener) { + mListener->scanStarted(this); + } +} + +void ScanDir::callSizeChanged() +{ + if (0) kDebug(90100) << ". [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + _dirty = true; + + if (_parent) { + _parent->callSizeChanged(); + } + + ScanListener *mListener = _manager ? _manager->listener() : nullptr; + + if (_listener) { + _listener->sizeChanged(this); + } + if (mListener) { + mListener->sizeChanged(this); + } +} + +void ScanDir::callScanFinished() +{ + if (0) kDebug(90100) << "ScanDir:Finished [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + ScanListener *mListener = _manager ? _manager->listener() : nullptr; + + if (_listener) { + _listener->scanFinished(this); + } + if (mListener) { + mListener->scanFinished(this); + } +} + diff --git a/plugins/fsview/scan.h b/plugins/fsview/scan.h new file mode 100644 index 0000000..5d3297b --- /dev/null +++ b/plugins/fsview/scan.h @@ -0,0 +1,294 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * Classes for breadth-first search in local filesystem + */ + +#ifndef KONQ_PLUGIN_SCAN_H +#define KONQ_PLUGIN_SCAN_H + +#include +#include +#include + +class ScanDir; +class ScanFile; + +class ScanItem +{ +public: + ScanItem(const QString &p, ScanDir *d) + { + absPath = p; + dir = d; + } + + QString absPath; + ScanDir *dir; +}; + +typedef QList ScanItemList; + +/** + * Listener for events from directory scanning. + * + * You can register a listener for the ScanManager to get + * all scan events and a listener for every ScanDir for + * directory specific scan events. + * + * sizeChanged is called when a scan of a subdirectory + * finished. + */ +class ScanListener +{ +public: + virtual ~ScanListener() {} + virtual void scanStarted(ScanDir *) {} + virtual void sizeChanged(ScanDir *) {} + virtual void scanFinished(ScanDir *) {} + // destroyed events are not delivered to listeners of ScanManager + virtual void destroyed(ScanDir *) {} + virtual void destroyed(ScanFile *) {} +}; + +/** + * ScanManager + * + * Start/Stop/Restart Scans. Example: + * + * ScanManager m("/opt"); + * m.startScan(); + * while(m.scan()); + */ +class ScanManager +{ +public: + ScanManager(); + ScanManager(const QString &path); + ~ScanManager(); + + /** Set the top path for scanning + * The ScanDir object created gets attribute data. + */ + ScanDir *setTop(const QString &path, int data = 0); + ScanDir *top() + { + return _topDir; + } + + bool scanRunning(); + int scanLength() const + { + return _list.count(); + } + + /** + * Starts the scan. Stop previous scan if running. + * For the actual scan to happen, you have to call + * scan() periodically. + * + * If from !=0, restart scan at given position; from must + * be from the previous scan of this manager. + */ + void startScan(ScanDir *from = nullptr); + + /** Stop a current running scan. + * Make all directories to finish their scan. + */ + void stopScan(); + + /** + * Scan first directory from todo list. + * Directories added to the todo list are attributed with data. + * Returns the number of new subdirectories created for scanning. + */ + int scan(int data); + + /* set listener to get a callbacks from this ScanDir */ + void setListener(ScanListener *); + ScanListener *listener() + { + return _listener; + } + +private: + ScanItemList _list; + ScanDir *_topDir; + ScanListener *_listener; +}; + +class ScanFile +{ +public: + ScanFile(); + ScanFile(const QString &n, KIO::fileoffset_t s); + ~ScanFile(); + + const QString &name() + { + return _name; + } + KIO::fileoffset_t size() + { + return _size; + } + + /* set listener to get callbacks from this ScanDir */ + void setListener(ScanListener *l) + { + _listener = l; + } + ScanListener *listener() + { + return _listener; + } + +private: + QString _name; + KIO::fileoffset_t _size; + ScanListener *_listener; +}; + +typedef QVector ScanFileVector; +typedef QVector ScanDirVector; + +/** + * A directory to scan. + * You can attribute a directory to scan with a + * integer data attribute. + */ +class ScanDir +{ +public: + ScanDir(); + ScanDir(const QString &n, ScanManager *m, + ScanDir *p = nullptr, int data = 0); + ~ScanDir(); + + /* Get items of this directory + * and append subdirectories to todo list. + * + * Directories added to the todo list are attributed with data. + * Returns the number of new subdirectories created for scanning. + */ + int scan(ScanItem *si, ScanItemList &list, int data); + + /* clear scan objects below */ + void clear(); + + /* + * Setup for child rescan + */ + void setupChildRescan(); + + /* Absolute path. Warning: Slow, loops to top parent. */ + QString path(); + + /* get integer data attribute */ + int data() + { + return _data; + } + void setData(int d) + { + _data = d; + } + + ScanFileVector &files() + { + return _files; + } + ScanDirVector &dirs() + { + return _dirs; + } + const QString &name() + { + return _name; + } + KIO::fileoffset_t size() + { + update(); + return _size; + } + unsigned int fileCount() + { + update(); + return _fileCount; + } + unsigned int dirCount() + { + update(); + return _dirCount; + } + ScanDir *parent() + { + return _parent; + } + bool scanStarted() + { + return (_dirsFinished >= 0); + } + bool scanFinished() + { + return (_dirsFinished == _dirs.count()); + } + bool scanRunning() + { + return scanStarted() && !scanFinished(); + } + + /* set listener to get a callbacks from this ScanDir */ + void setListener(ScanListener *); + ScanListener *listener() + { + return _listener; + } + ScanManager *manager() + { + return _manager; + } + + /* force current scan to be finished */ + void finish(); + +private: + void update(); + bool isForbiddenDir(QString &); + + /* this propagates file count and size to upper dirs */ + void subScanFinished(); + void callScanStarted(); + void callSizeChanged(); + void callScanFinished(); + + ScanFileVector _files; + ScanDirVector _dirs; + + QString _name; + bool _dirty; /* needs a call to update() */ + KIO::fileoffset_t _size, _fileSize; + unsigned int _fileCount, _dirCount; + int _dirsFinished, _data; + ScanDir *_parent; + ScanListener *_listener; + ScanManager *_manager; +}; + +#endif // KONQ_PLUGIN_SCAN_H diff --git a/plugins/fsview/tests/CMakeLists.txt b/plugins/fsview/tests/CMakeLists.txt new file mode 100644 index 0000000..4ee0300 --- /dev/null +++ b/plugins/fsview/tests/CMakeLists.txt @@ -0,0 +1,23 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +########### next target ############### + +set(libfsview_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/../treemap.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../fsview.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../scan.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../inode.cpp + ) + + +set(scantest_SRCS scantest.cpp ${libfsview_SRCS}) + +add_executable(scantest ${scantest_SRCS}) +ecm_mark_as_test(scantest) + +target_link_libraries(scantest KF5::KIOCore KF5::KDELibs4Support Qt5::Widgets) + + diff --git a/plugins/fsview/tests/scantest.cpp b/plugins/fsview/tests/scantest.cpp new file mode 100644 index 0000000..6234465 --- /dev/null +++ b/plugins/fsview/tests/scantest.cpp @@ -0,0 +1,57 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* Test Directory Scanning. Usually not build. */ + +#include + +#include "scan.h" + +class MyListener: public ScanListener +{ +public: + void scanStarted(ScanDir *d) override + { + printf("Started Scan on %s\n", qPrintable(d->name())); + }; + + void sizeChanged(ScanDir *d) override + { + printf("Change in %s: Dirs %d, Files %d", + qPrintable(d->name()), + d->dirCount(), d->fileCount()); + printf("Size %llu\n", (unsigned long long int)d->size()); + } + + void scanFinished(ScanDir *d) override + { + printf("Finished Scan on %s\n", qPrintable(d->name())); + } +}; + +int main(int argc, char *argv[]) +{ + ScanManager m(QStringLiteral("/opt")); + if (argc > 1) { + m.setTop(argv[1]); + } + + m.setListener(new MyListener()); + m.startScan(); + while (m.scan(1)); +} diff --git a/plugins/fsview/treemap.cpp b/plugins/fsview/treemap.cpp new file mode 100644 index 0000000..ea9221c --- /dev/null +++ b/plugins/fsview/treemap.cpp @@ -0,0 +1,3646 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002, 2003 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + */ + +#include "treemap.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// set this to 1 to enable debug output +#define DEBUG_DRAWING 0 +#define MAX_FIELD 12 + +// +// StoredDrawParams +// +StoredDrawParams::StoredDrawParams() +{ + _selected = false; + _current = false; + _shaded = true; + _rotated = false; + _drawFrame = true; + + _backColor = Qt::white; + + // field array has size 0 +} + +StoredDrawParams::StoredDrawParams(const QColor &c, + bool selected, bool current) +{ + _backColor = c; + + _selected = selected; + _current = current; + _shaded = true; + _rotated = false; + _drawFrame = true; + + // field array has size 0 +} + +QString StoredDrawParams::text(int f) const +{ + if ((f < 0) || (f >= _field.size())) { + return QString(); + } + + return _field[f].text; +} + +QPixmap StoredDrawParams::pixmap(int f) const +{ + if ((f < 0) || (f >= _field.size())) { + return QPixmap(); + } + + return _field[f].pix; +} + +DrawParams::Position StoredDrawParams::position(int f) const +{ + if ((f < 0) || (f >= _field.size())) { + return Default; + } + + return _field[f].pos; +} + +int StoredDrawParams::maxLines(int f) const +{ + if ((f < 0) || (f >= _field.size())) { + return 0; + } + + return _field[f].maxLines; +} + +const QFont &StoredDrawParams::font() const +{ + static QFont *f = nullptr; + if (!f) { + f = new QFont(QApplication::font()); + } + + return *f; +} + +void StoredDrawParams::ensureField(int f) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + + if (_field.size() < f + 1) { + int oldSize = _field.size(); + _field.resize(f + 1); + while (oldSize < f + 1) { + _field[oldSize].pos = Default; + _field[oldSize].maxLines = 0; + oldSize++; + } + } +} + +void StoredDrawParams::setField(int f, const QString &t, const QPixmap &pm, + Position p, int maxLines) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + ensureField(f); + + _field[f].text = t; + _field[f].pix = pm; + _field[f].pos = p; + _field[f].maxLines = maxLines; +} + +void StoredDrawParams::setText(int f, const QString &t) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + ensureField(f); + + _field[f].text = t; +} + +void StoredDrawParams::setPixmap(int f, const QPixmap &pm) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + ensureField(f); + + _field[f].pix = pm; +} + +void StoredDrawParams::setPosition(int f, Position p) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + ensureField(f); + + _field[f].pos = p; +} + +void StoredDrawParams::setMaxLines(int f, int m) +{ + if (f < 0 || f >= MAX_FIELD) { + return; + } + ensureField(f); + + _field[f].maxLines = m; +} + +// +// RectDrawing +// + +RectDrawing::RectDrawing(const QRect &r) +{ + _fm = nullptr; + _dp = nullptr; + setRect(r); +} + +RectDrawing::~RectDrawing() +{ + delete _fm; + delete _dp; +} + +DrawParams *RectDrawing::drawParams() +{ + if (!_dp) { + _dp = new StoredDrawParams(); + } + + return _dp; +} + +void RectDrawing::setDrawParams(DrawParams *dp) +{ + delete _dp; + _dp = dp; +} + +void RectDrawing::setRect(const QRect &r) +{ + _rect = r; + + _usedTopLeft = 0; + _usedTopCenter = 0; + _usedTopRight = 0; + _usedBottomLeft = 0; + _usedBottomCenter = 0; + _usedBottomRight = 0; + + _fontHeight = 0; +} + +QRect RectDrawing::remainingRect(DrawParams *dp) +{ + if (!dp) { + dp = drawParams(); + } + + if ((_usedTopLeft > 0) || + (_usedTopCenter > 0) || + (_usedTopRight > 0)) { + if (dp->rotated()) { + _rect.setLeft(_rect.left() + _fontHeight); + } else { + _rect.setTop(_rect.top() + _fontHeight); + } + } + + if ((_usedBottomLeft > 0) || + (_usedBottomCenter > 0) || + (_usedBottomRight > 0)) { + if (dp->rotated()) { + _rect.setRight(_rect.right() - _fontHeight); + } else { + _rect.setBottom(_rect.bottom() - _fontHeight); + } + } + return _rect; +} + +void RectDrawing::drawBack(QPainter *p, DrawParams *dp) +{ + if (!dp) { + dp = drawParams(); + } + if (_rect.width() <= 0 || _rect.height() <= 0) { + return; + } + + QRect r = _rect; + QColor normal = dp->backColor(); + if (dp->selected()) { + normal = normal.lighter(); + } + bool isCurrent = dp->current(); + + if (dp->drawFrame() || isCurrent) { + // 3D raised/sunken frame effect... + QColor high = normal.lighter(); + QColor low = normal.darker(); + p->setPen(isCurrent ? low : high); + p->drawLine(r.left(), r.top(), r.right(), r.top()); + p->drawLine(r.left(), r.top(), r.left(), r.bottom()); + p->setPen(isCurrent ? high : low); + p->drawLine(r.right(), r.top(), r.right(), r.bottom()); + p->drawLine(r.left(), r.bottom(), r.right(), r.bottom()); + r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); + } + if (r.width() <= 0 || r.height() <= 0) { + return; + } + + if (dp->shaded() && (r.width() > 0 && r.height() > 0)) { + // adjustment for drawRect semantic in Qt4: decrement height/width + r.setRect(r.x(), r.y(), r.width() - 1, r.height() - 1); + + // some shading + bool goDark = qGray(normal.rgb()) > 128; + int rBase, gBase, bBase; + normal.getRgb(&rBase, &gBase, &bBase); + p->setBrush(Qt::NoBrush); + + // shade parameters: + int d = 7; + float factor = 0.1, forth = 0.7, back1 = 0.9, toBack2 = .7, back2 = 0.97; + + // coefficient corrections because of rectangle size + int s = r.width(); + if (s > r.height()) { + s = r.height(); + } + if (s < 100) { + forth -= .3 * (100 - s) / 100; + back1 -= .2 * (100 - s) / 100; + back2 -= .02 * (100 - s) / 100; + } + + // maximal color difference + int rDiff = goDark ? -rBase / d : (255 - rBase) / d; + int gDiff = goDark ? -gBase / d : (255 - gBase) / d; + int bDiff = goDark ? -bBase / d : (255 - bBase) / d; + + QColor shadeColor; + while (factor < .95 && (r.width() >= 0 && r.height() >= 0)) { + shadeColor.setRgb((int)(rBase + factor * rDiff + .5), + (int)(gBase + factor * gDiff + .5), + (int)(bBase + factor * bDiff + .5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); + factor = 1.0 - ((1.0 - factor) * forth); + } + + // and back (1st half) + while (factor > toBack2 && (r.width() >= 0 && r.height() >= 0)) { + shadeColor.setRgb((int)(rBase + factor * rDiff + .5), + (int)(gBase + factor * gDiff + .5), + (int)(bBase + factor * bDiff + .5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); + factor = 1.0 - ((1.0 - factor) / back1); + } + + // and back (2nd half) + while (factor > .01 && (r.width() >= 0 && r.height() >= 0)) { + shadeColor.setRgb((int)(rBase + factor * rDiff + .5), + (int)(gBase + factor * gDiff + .5), + (int)(bBase + factor * bDiff + .5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); + factor = factor * back2; + } + + normal = shadeColor; + // for filling, width and height has to be incremented again + r.setRect(r.x(), r.y(), r.width() + 1, r.height() + 1); + } + + // fill inside + p->fillRect(r, normal); +} + +/* Helper for drawField + * Find a line break position in a string, given a font and maximum width + * + * Returns the actually used width, and sets + */ +static +int findBreak(int &breakPos, QString text, QFontMetrics *fm, int maxWidth) +{ + int usedWidth; + + // does full text fit? + breakPos = text.length(); + usedWidth = fm->width(text); + if (usedWidth < maxWidth) { + return usedWidth; + } + + // now lower breakPos until best position is found. + // first by binary search, resulting in a position a little bit too large + int bottomPos = 0; + while (qAbs(maxWidth - usedWidth) > 3 * fm->maxWidth()) { + int halfPos = (bottomPos + breakPos) / 2; + int halfWidth = fm->width(text, halfPos); + if (halfWidth < maxWidth) { + bottomPos = halfPos; + } else { + breakPos = halfPos; + usedWidth = halfWidth; + } + } + + // final position by taking break boundaries into account. + // possible break boundaries are changing char categories but not middle of "Aa" + QChar::Category lastCat, cat; + int pos = breakPos; + lastCat = text[pos - 1].category(); + // at minimum 2 chars before break + while (pos > 2) { + pos--; + cat = text[pos - 1].category(); + if (cat == lastCat) { + continue; + } + + // "Aa" has not a possible break inbetween + if ((cat == QChar::Letter_Uppercase) && + (lastCat == QChar::Letter_Lowercase)) { + lastCat = cat; + continue; + } + lastCat = cat; + + breakPos = pos; + usedWidth = fm->width(text, breakPos); + if (usedWidth < maxWidth) { + break; + } + } + return usedWidth; +} + +/* Helper for drawField + * Find last line break position in a string from backwards, + * given a font and maximum width + * + * Returns the actually used width, and sets + */ +static +int findBreakBackwards(int &breakPos, QString text, QFontMetrics *fm, int maxWidth) +{ + int usedWidth; + + // does full text fit? + breakPos = 0; + usedWidth = fm->width(text); + if (usedWidth < maxWidth) { + return usedWidth; + } + + // now raise breakPos until best position is found. + // first by binary search, resulting in a position a little bit too small + int topPos = text.length(); + while (qAbs(maxWidth - usedWidth) > 3 * fm->maxWidth()) { + int halfPos = (breakPos + topPos) / 2; + int halfWidth = fm->width(text.mid(halfPos)); + if (halfWidth < maxWidth) { + breakPos = halfPos; + usedWidth = halfWidth; + } else { + topPos = halfPos; + } + } + + // final position by taking break boundaries into account. + // possible break boundaries are changing char categories but not middle of "Aa" + QChar::Category lastCat, cat; + int pos = breakPos; + lastCat = text[pos].category(); + // at minimum 2 chars before break + while (pos < text.length() - 2) { + pos++; + cat = text[pos].category(); + if (cat == lastCat) { + continue; + } + + // "Aa" has not a possible break inbetween + if ((lastCat == QChar::Letter_Uppercase) && + (cat == QChar::Letter_Lowercase)) { + lastCat = cat; + continue; + } + lastCat = cat; + + breakPos = pos; + usedWidth = fm->width(text.mid(breakPos)); + if (usedWidth < maxWidth) { + break; + } + } + return usedWidth; +} + +bool RectDrawing::drawField(QPainter *p, int f, DrawParams *dp) +{ + if (!dp) { + dp = drawParams(); + } + + if (!_fm) { + _fm = new QFontMetrics(dp->font()); + _fontHeight = _fm->height(); + } + + QRect r = _rect; + + if (0) kDebug(90100) << "DrawField: Rect " << r.x() << "/" << r.y() + << " - " << r.width() << "x" << r.height() << endl; + + int h = _fontHeight; + bool rotate = dp->rotated(); + int width = (rotate ? r.height() : r.width()) - 4; + int height = (rotate ? r.width() : r.height()); + int lines = height / h; + + // stop if there is no space available + if (lines < 1) { + return false; + } + + // calculate free space in first line () + int pos = dp->position(f); + if (pos == DrawParams::Default) { + switch (f % 4) { + case 0: pos = DrawParams::TopLeft; break; + case 1: pos = DrawParams::TopRight; break; + case 2: pos = DrawParams::BottomRight; break; + case 3: pos = DrawParams::BottomLeft; break; + } + } + + int unused = 0; + bool isBottom = false; + bool isCenter = false; + bool isRight = false; + int *used = nullptr; + switch (pos) { + case DrawParams::TopLeft: + used = &_usedTopLeft; + if (_usedTopLeft == 0) { + if (_usedTopCenter) { + unused = (width - _usedTopCenter) / 2; + } else { + unused = width - _usedTopRight; + } + } + break; + + case DrawParams::TopCenter: + isCenter = true; + used = &_usedTopCenter; + if (_usedTopCenter == 0) { + if (_usedTopLeft > _usedTopRight) { + unused = width - 2 * _usedTopLeft; + } else { + unused = width - 2 * _usedTopRight; + } + } + break; + + case DrawParams::TopRight: + isRight = true; + used = &_usedTopRight; + if (_usedTopRight == 0) { + if (_usedTopCenter) { + unused = (width - _usedTopCenter) / 2; + } else { + unused = width - _usedTopLeft; + } + } + break; + + case DrawParams::BottomLeft: + isBottom = true; + used = &_usedBottomLeft; + if (_usedBottomLeft == 0) { + if (_usedBottomCenter) { + unused = (width - _usedBottomCenter) / 2; + } else { + unused = width - _usedBottomRight; + } + } + break; + + case DrawParams::BottomCenter: + isCenter = true; + isBottom = true; + used = &_usedBottomCenter; + if (_usedBottomCenter == 0) { + if (_usedBottomLeft > _usedBottomRight) { + unused = width - 2 * _usedBottomLeft; + } else { + unused = width - 2 * _usedBottomRight; + } + } + break; + + case DrawParams::BottomRight: + isRight = true; + isBottom = true; + used = &_usedBottomRight; + if (_usedBottomRight == 0) { + if (_usedBottomCenter) { + unused = (width - _usedBottomCenter) / 2; + } else { + unused = width - _usedBottomLeft; + } + } + break; + } + + if (isBottom) { + if ((_usedTopLeft > 0) || + (_usedTopCenter > 0) || + (_usedTopRight > 0)) { + lines--; + } + } else if (!isBottom) { + if ((_usedBottomLeft > 0) || + (_usedBottomCenter > 0) || + (_usedBottomRight > 0)) { + lines--; + } + } + if (lines < 1) { + return false; + } + + int y = isBottom ? height - h : 0; + + if (unused < 0) { + unused = 0; + } + if (unused == 0) { + // no space available in last line at this position + y = isBottom ? (y - h) : (y + h); + lines--; + + if (lines < 1) { + return false; + } + + // new line: reset used space + if (isBottom) { + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + } else { + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + + unused = width; + } + + // stop as soon as possible when there is no space for "..." + static int dotW = 0; + if (!dotW) { + dotW = _fm->width(QStringLiteral("...")); + } + if (width < dotW) { + return false; + } + + // get text and pixmap now, only if we need to, because it is possible + // that they are calculated on demand (and this can take some time) + QString name = dp->text(f); + if (name.isEmpty()) { + return 0; + } + QPixmap pix = dp->pixmap(f); + + // check if pixmap can be drawn + int pixW = pix.width(); + int pixH = pix.height(); + int pixY = 0; + bool pixDrawn = true; + if (pixW > 0) { + pixW += 2; // X distance from pix + if ((width < pixW + dotW) || (height < pixH)) { + // do not draw + pixW = 0; + } else { + pixDrawn = false; + } + } + + // width of text and pixmap to be drawn + int w = pixW + _fm->width(name); + + if (0) kDebug(90100) << " For '" << name << "': Unused " << unused + << ", StrW " << w << ", Width " << width << endl; + + // if we have limited space at 1st line: + // use it only if whole name does fit in last line... + if ((unused < width) && (w > unused)) { + y = isBottom ? (y - h) : (y + h); + lines--; + + if (lines < 1) { + return false; + } + + // new line: reset used space + if (isBottom) { + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + } else { + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + } + + p->save(); + p->setPen((qGray(dp->backColor().rgb()) > 100) ? Qt::black : Qt::white); + p->setFont(dp->font()); + if (rotate) { + //p->translate(r.x()+2, r.y()+r.height()); + p->translate(r.x(), r.y() + r.height() - 2); + p->rotate(270); + } else { + p->translate(r.x() + 2, r.y()); + } + + // adjust available lines according to maxLines + int max = dp->maxLines(f); + if ((max > 0) && (lines > max)) { + lines = max; + } + + /* loop over name parts to break up string depending on available width. + * every char category change is supposed a possible break, + * with the exception Uppercase=>Lowercase. + * It is good enough for numbers, Symbols... + * + * If the text is to be written at the bottom, we start with the + * end of the string (so everything is reverted) + */ + QString remaining; + int origLines = lines; + while (lines > 0) { + + // more than one line: search for line break + if (w > width && lines > 1) { + int breakPos; + + if (!isBottom) { + w = pixW + findBreak(breakPos, name, _fm, width - pixW); + + remaining = name.mid(breakPos); + // remove space on break point + if (name[breakPos - 1].category() == QChar::Separator_Space) { + name = name.left(breakPos - 1); + } else { + name = name.left(breakPos); + } + } else { // bottom + w = pixW + findBreakBackwards(breakPos, name, _fm, width - pixW); + + remaining = name.left(breakPos); + // remove space on break point + if (name[breakPos].category() == QChar::Separator_Space) { + name = name.mid(breakPos + 1); + } else { + name = name.mid(breakPos); + } + } + } else { + remaining = QString(); + } + + /* truncate and add ... if needed */ + if (w > width) { + name = _fm->elidedText(name, Qt::ElideRight, width - pixW); + w = _fm->width(name) + pixW; + } + + int x = 0; + if (isCenter) { + x = (width - w) / 2; + } else if (isRight) { + x = width - w; + } + + if (!pixDrawn) { + pixY = y + (h - pixH) / 2; // default: center vertically + if (pixH > h) { + pixY = isBottom ? y - (pixH - h) : y; + } + + p->drawPixmap(x, pixY, pix); + + // for distance to next text + pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2); + pixDrawn = true; + } + + if (0) kDebug(90100) << " Drawing '" << name << "' at " + << x + pixW << "/" << y << endl; + + p->drawText(x + pixW, y, + width - pixW, h, + Qt::AlignLeft, name); + y = isBottom ? (y - h) : (y + h); + lines--; + + if (remaining.isEmpty()) { + break; + } + name = remaining; + w = pixW + _fm->width(name); + } + + // make sure the pix stays visible + if (pixDrawn && (pixY > 0)) { + if (isBottom && (pixY < y)) { + y = pixY; + } + if (!isBottom && (pixY > y)) { + y = pixY; + } + } + + if (origLines > lines) { + // if only 1 line written, do not reset _used* vars + if (lines - origLines > 1) { + if (isBottom) { + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + } else { + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + } + + // take back one line + y = isBottom ? (y + h) : (y - h); + if (used) { + *used = w; + } + } + + // update free space + if (!isBottom) { + if (rotate) { + _rect.setRect(r.x() + y, r.y(), r.width() - y, r.height()); + } else { + _rect.setRect(r.x(), r.y() + y, r.width(), r.height() - y); + } + } else { + if (rotate) { + _rect.setRect(r.x(), r.y(), y + h, r.height()); + } else { + _rect.setRect(r.x(), r.y(), r.width(), y + h); + } + } + + p->restore(); + + return true; +} + +// +// TreeMapItemList +// + +TreeMapItem *TreeMapItemList::commonParent() +{ + if (isEmpty()) { + return nullptr; + } + + TreeMapItem *parent = first(); + for (int i = 1; parent && i < size(); i++) { + parent = parent->commonParent(at(i)); + } + + return parent; +} + +class TreeMapItemLessThan +{ +public: + bool operator()(const TreeMapItem *i1, const TreeMapItem *i2) const + { + TreeMapItem *p = i1->parent(); + // should not happen + if (!p) { + return false; + } + + bool ascending; + bool result; + int textNo = p->sorting(&ascending); + if (textNo < 0) { + result = i1->value() < i2->value(); + } else { + result = i1->text(textNo) < i2->text(textNo); + } + + return ascending ? result : !result; + } +}; + +TreeMapItemLessThan treeMapItemLessThan; + +// TreeMapItem + +TreeMapItem::TreeMapItem(TreeMapItem *parent, double value) +{ + _value = value; + _parent = parent; + + _sum = 0; + _children = nullptr; + _widget = nullptr; + _index = -1; + _depth = -1; // not set + _unused_self = 0; + + if (_parent) { + // take sorting from parent + _sortTextNo = _parent->sorting(&_sortAscending); + _parent->addItem(this); + } else { + _sortAscending = false; + _sortTextNo = -1; // default: no sorting + } +} + +TreeMapItem::TreeMapItem(TreeMapItem *parent, double value, + const QString &text1, const QString &text2, + const QString &text3, const QString &text4) +{ + _value = value; + _parent = parent; + + // this resizes the text vector only if needed + if (!text4.isEmpty()) { + setText(3, text4); + } + if (!text3.isEmpty()) { + setText(2, text3); + } + if (!text2.isEmpty()) { + setText(1, text2); + } + setText(0, text1); + + _sum = 0; + _children = nullptr; + _widget = nullptr; + _index = -1; + _depth = -1; // not set + _unused_self = 0; + + if (_parent) { + _parent->addItem(this); + } +} + +TreeMapItem::~TreeMapItem() +{ + if (_children) { + qDeleteAll(*_children); + delete _children; + _children = nullptr; + } + + // finally, notify widget about deletion + if (_widget) { + _widget->deletingItem(this); + } +} + +void TreeMapItem::setParent(TreeMapItem *p) +{ + _parent = p; + if (p) { + _widget = p->_widget; + } +} + +bool TreeMapItem::isChildOf(TreeMapItem *item) +{ + if (!item) { + return false; + } + + TreeMapItem *i = this; + while (i) { + if (item == i) { + return true; + } + i = i->_parent; + } + return false; +} + +TreeMapItem *TreeMapItem::commonParent(TreeMapItem *item) +{ + while (item && !isChildOf(item)) { + item = item->parent(); + } + return item; +} + +void TreeMapItem::redraw() +{ + if (_widget) { + _widget->redraw(this); + } +} + +void TreeMapItem::clear() +{ + if (_children) { + // delete selected items below this item from selection + if (_widget) { + _widget->clearSelection(this); + } + + qDeleteAll(*_children); + delete _children; + _children = nullptr; + } +} + +// invalidates current children and forces redraw +// this is only useful when children are created on demand in items() +void TreeMapItem::refresh() +{ + clear(); + redraw(); +} + +QStringList TreeMapItem::path(int textNo) const +{ + QStringList list(text(textNo)); + + TreeMapItem *i = _parent; + while (i) { + QString text = i->text(textNo); + if (!text.isEmpty()) { + list.prepend(i->text(textNo)); + } + i = i->_parent; + } + return list; +} + +int TreeMapItem::depth() const +{ + if (_depth > 0) { + return _depth; + } + + if (_parent) { + return _parent->depth() + 1; + } + return 1; +} + +bool TreeMapItem::initialized() +{ + if (!_children) { + _children = new TreeMapItemList; + return false; + } + return true; +} + +void TreeMapItem::addItem(TreeMapItem *i) +{ + if (!i) { + return; + } + + if (!_children) { + _children = new TreeMapItemList; + } + + i->setParent(this); + + _children->append(i); // preserve insertion order + if (sorting(nullptr) != -1) { + std::sort(_children->begin(), _children->end(), treeMapItemLessThan); + } +} + +// default implementations of virtual functions + +double TreeMapItem::value() const +{ + return _value; +} + +double TreeMapItem::sum() const +{ + return _sum; +} + +DrawParams::Position TreeMapItem::position(int f) const +{ + Position p = StoredDrawParams::position(f); + if (_widget && (p == Default)) { + p = _widget->fieldPosition(f); + } + + return p; +} + +// use widget font +const QFont &TreeMapItem::font() const +{ + return _widget->currentFont(); +} + +bool TreeMapItem::isMarked(int) const +{ + return false; +} + +int TreeMapItem::borderWidth() const +{ + if (_widget) { + return _widget->borderWidth(); + } + + return 2; +} + +int TreeMapItem::sorting(bool *ascending) const +{ + if (ascending) { + *ascending = _sortAscending; + } + return _sortTextNo; +} + +// do *not* set sorting recursively +void TreeMapItem::setSorting(int textNo, bool ascending) +{ + if (_sortTextNo == textNo) { + if (_sortAscending == ascending) { + return; + } + if (textNo == -1) { + // when no sorting is done, order change does not do anything + _sortAscending = ascending; + return; + } + } + _sortAscending = ascending; + _sortTextNo = textNo; + + if (_children && _sortTextNo != -1) { + std::sort(_children->begin(), _children->end(), treeMapItemLessThan); + } +} + +void TreeMapItem::resort(bool recursive) +{ + if (!_children) { + return; + } + + if (_sortTextNo != -1) { + std::sort(_children->begin(), _children->end(), treeMapItemLessThan); + } + + if (recursive) + foreach (TreeMapItem *i, *_children) { + i->resort(recursive); + } +} + +TreeMapItem::SplitMode TreeMapItem::splitMode() const +{ + if (_widget) { + return _widget->splitMode(); + } + + return Best; +} + +int TreeMapItem::rtti() const +{ + return 0; +} + +TreeMapItemList *TreeMapItem::children() +{ + if (!_children) { + _children = new TreeMapItemList; + } + + return _children; +} + +void TreeMapItem::clearItemRect() +{ + _rect = QRect(); + clearFreeRects(); +} + +void TreeMapItem::clearFreeRects() +{ + _freeRects.clear(); +} + +void TreeMapItem::addFreeRect(const QRect &r) +{ + // do not add invalid rects + if ((r.width() < 1) || (r.height() < 1)) { + return; + } + + if (0) kDebug(90100) << "addFree(" << path(0).join(QStringLiteral("/")) << ", " + << r.x() << "/" << r.y() << "-" + << r.width() << "x" << r.height() << ")" << endl; + + if (_freeRects.isEmpty()) { + _freeRects.append(r); + return; + } + + // join rect with last rect if possible + // this saves memory and does not make the tooltip flicker + QRect &last = _freeRects.last(); + bool replaced = false; + if ((last.left() == r.left()) && (last.width() == r.width())) { + if ((last.bottom() + 1 == r.top()) || (r.bottom() + 1 == last.top())) { + last |= r; + replaced = true; + } + } else if ((last.top() == r.top()) && (last.height() == r.height())) { + if ((last.right() + 1 == r.left()) || (r.right() + 1 == last.left())) { + last |= r; + replaced = true; + } + } + + if (!replaced) { + _freeRects.append(r); + return; + } + + if (0) kDebug(90100) << " united with last to (" + << last.x() << "/" << last.y() << "-" + << last.width() << "x" << last.height() << ")" << endl; +} + +// TreeMapWidget + +TreeMapWidget::TreeMapWidget(TreeMapItem *base, + QWidget *parent) + : QWidget(parent) +{ + _base = base; + _base->setWidget(this); + + _font = font(); + _fontHeight = fontMetrics().height(); + + // default behaviour + _selectionMode = Single; + _splitMode = TreeMapItem::AlwaysBest; + _visibleWidth = 2; + _reuseSpace = false; + _skipIncorrectBorder = false; + _drawSeparators = false; + _allowRotation = true; + _borderWidth = 2; + _shading = true; // beautiful is default! + _maxSelectDepth = -1; // unlimited + _maxDrawingDepth = -1; // unlimited + _minimalArea = -1; // unlimited + _markNo = 0; + + for (int i = 0; i < 4; i++) { + _drawFrame[i] = true; + _transparent[i] = false; + } + + // _stopAtText will be unset on resizing (per default) + // _textVisible will be true on resizing (per default) + // _forceText will be false on resizing (per default) + + // start state: _selection is an empty list + _current = nullptr; + _oldCurrent = nullptr; + _pressed = nullptr; + _lastOver = nullptr; + _needsRefresh = _base; + + setAttribute(Qt::WA_NoSystemBackground, true); + setFocusPolicy(Qt::StrongFocus); +} + +TreeMapWidget::~TreeMapWidget() +{ + delete _base; +} + +const QFont &TreeMapWidget::currentFont() const +{ + return _font; +} + +void TreeMapWidget::setSplitMode(TreeMapItem::SplitMode m) +{ + if (_splitMode == m) { + return; + } + + _splitMode = m; + redraw(); +} + +TreeMapItem::SplitMode TreeMapWidget::splitMode() const +{ + return _splitMode; +} + +bool TreeMapWidget::setSplitMode(const QString &mode) +{ + if (mode == QLatin1String("Bisection")) { + setSplitMode(TreeMapItem::Bisection); + } else if (mode == QLatin1String("Columns")) { + setSplitMode(TreeMapItem::Columns); + } else if (mode == QLatin1String("Rows")) { + setSplitMode(TreeMapItem::Rows); + } else if (mode == QLatin1String("AlwaysBest")) { + setSplitMode(TreeMapItem::AlwaysBest); + } else if (mode == QLatin1String("Best")) { + setSplitMode(TreeMapItem::Best); + } else if (mode == QLatin1String("HAlternate")) { + setSplitMode(TreeMapItem::HAlternate); + } else if (mode == QLatin1String("VAlternate")) { + setSplitMode(TreeMapItem::VAlternate); + } else if (mode == QLatin1String("Horizontal")) { + setSplitMode(TreeMapItem::Horizontal); + } else if (mode == QLatin1String("Vertical")) { + setSplitMode(TreeMapItem::Vertical); + } else { + return false; + } + + return true; +} + +QString TreeMapWidget::splitModeString() const +{ + QString mode; + switch (splitMode()) { + case TreeMapItem::Bisection: mode = QStringLiteral("Bisection"); break; + case TreeMapItem::Columns: mode = QStringLiteral("Columns"); break; + case TreeMapItem::Rows: mode = QStringLiteral("Rows"); break; + case TreeMapItem::AlwaysBest: mode = QStringLiteral("AlwaysBest"); break; + case TreeMapItem::Best: mode = QStringLiteral("Best"); break; + case TreeMapItem::HAlternate: mode = QStringLiteral("HAlternate"); break; + case TreeMapItem::VAlternate: mode = QStringLiteral("VAlternate"); break; + case TreeMapItem::Horizontal: mode = QStringLiteral("Horizontal"); break; + case TreeMapItem::Vertical: mode = QStringLiteral("Vertical"); break; + default: mode = QStringLiteral("Unknown"); break; + } + return mode; +} + +void TreeMapWidget::setShadingEnabled(bool s) +{ + if (_shading == s) { + return; + } + + _shading = s; + redraw(); +} + +void TreeMapWidget::drawFrame(int d, bool b) +{ + if ((d < 0) || (d >= 4) || (_drawFrame[d] == b)) { + return; + } + + _drawFrame[d] = b; + redraw(); +} + +void TreeMapWidget::setTransparent(int d, bool b) +{ + if ((d < 0) || (d >= 4) || (_transparent[d] == b)) { + return; + } + + _transparent[d] = b; + redraw(); +} + +void TreeMapWidget::setAllowRotation(bool enable) +{ + if (_allowRotation == enable) { + return; + } + + _allowRotation = enable; + redraw(); +} + +void TreeMapWidget::setVisibleWidth(int width, bool reuseSpace) +{ + if (_visibleWidth == width && _reuseSpace == reuseSpace) { + return; + } + + _visibleWidth = width; + _reuseSpace = reuseSpace; + redraw(); +} + +void TreeMapWidget::setSkipIncorrectBorder(bool enable) +{ + if (_skipIncorrectBorder == enable) { + return; + } + + _skipIncorrectBorder = enable; + redraw(); +} + +void TreeMapWidget::setBorderWidth(int w) +{ + if (_borderWidth == w) { + return; + } + + _borderWidth = w; + redraw(); +} + +void TreeMapWidget::setMaxDrawingDepth(int d) +{ + if (_maxDrawingDepth == d) { + return; + } + + _maxDrawingDepth = d; + redraw(); +} + +QString TreeMapWidget::defaultFieldType(int f) const +{ + return i18n("Text %1", f + 1); +} + +QString TreeMapWidget::defaultFieldStop(int) const +{ + return QString(); +} + +bool TreeMapWidget::defaultFieldVisible(int f) const +{ + return (f < 2); +} + +bool TreeMapWidget::defaultFieldForced(int) const +{ + return false; +} + +DrawParams::Position TreeMapWidget::defaultFieldPosition(int f) const +{ + switch (f % 4) { + case 0: return DrawParams::TopLeft; + case 1: return DrawParams::TopRight; + case 2: return DrawParams::BottomRight; + case 3: return DrawParams::BottomLeft; + default: break; + } + return DrawParams::TopLeft; +} + +bool TreeMapWidget::resizeAttr(int size) +{ + if (size < 0 || size >= MAX_FIELD) { + return false; + } + + if (size > _attr.size()) { + int oldSize = _attr.size(); + _attr.resize(size); + while (oldSize < size) { + _attr[oldSize].type = defaultFieldType(oldSize); + _attr[oldSize].stop = defaultFieldStop(oldSize); + _attr[oldSize].visible = defaultFieldVisible(oldSize); + _attr[oldSize].forced = defaultFieldForced(oldSize); + _attr[oldSize].pos = defaultFieldPosition(oldSize); + oldSize++; + } + } + return true; +} + +void TreeMapWidget::setFieldType(int f, const QString &type) +{ + if ((_attr.size() < f + 1) && + (type == defaultFieldType(f))) { + return; + } + if (resizeAttr(f + 1)) { + _attr[f].type = type; + } + + // no need to redraw: the type string is not visible in the TreeMap +} + +QString TreeMapWidget::fieldType(int f) const +{ + if (f < 0 || _attr.size() < f + 1) { + return defaultFieldType(f); + } + return _attr[f].type; +} + +void TreeMapWidget::setFieldStop(int f, const QString &stop) +{ + if ((_attr.size() < f + 1) && + (stop == defaultFieldStop(f))) { + return; + } + if (resizeAttr(f + 1)) { + _attr[f].stop = stop; + redraw(); + } +} + +QString TreeMapWidget::fieldStop(int f) const +{ + if (f < 0 || _attr.size() < f + 1) { + return defaultFieldStop(f); + } + return _attr[f].stop; +} + +void TreeMapWidget::setFieldVisible(int f, bool enable) +{ + if ((_attr.size() < f + 1) && + (enable == defaultFieldVisible(f))) { + return; + } + + if (resizeAttr(f + 1)) { + _attr[f].visible = enable; + redraw(); + } +} + +bool TreeMapWidget::fieldVisible(int f) const +{ + if (f < 0 || _attr.size() < f + 1) { + return defaultFieldVisible(f); + } + + return _attr[f].visible; +} + +void TreeMapWidget::setFieldForced(int f, bool enable) +{ + if ((_attr.size() < f + 1) && + (enable == defaultFieldForced(f))) { + return; + } + + if (resizeAttr(f + 1)) { + _attr[f].forced = enable; + if (_attr[f].visible) { + redraw(); + } + } +} + +bool TreeMapWidget::fieldForced(int f) const +{ + if (f < 0 || _attr.size() < f + 1) { + return defaultFieldForced(f); + } + + return _attr[f].forced; +} + +void TreeMapWidget::setFieldPosition(int f, TreeMapItem::Position pos) +{ + if ((_attr.size() < f + 1) && + (pos == defaultFieldPosition(f))) { + return; + } + + if (resizeAttr(f + 1)) { + _attr[f].pos = pos; + if (_attr[f].visible) { + redraw(); + } + } +} + +DrawParams::Position TreeMapWidget::fieldPosition(int f) const +{ + if (f < 0 || _attr.size() < f + 1) { + return defaultFieldPosition(f); + } + + return _attr[f].pos; +} + +void TreeMapWidget::setFieldPosition(int f, const QString &pos) +{ + if (pos == QLatin1String("TopLeft")) { + setFieldPosition(f, DrawParams::TopLeft); + } else if (pos == QLatin1String("TopCenter")) { + setFieldPosition(f, DrawParams::TopCenter); + } else if (pos == QLatin1String("TopRight")) { + setFieldPosition(f, DrawParams::TopRight); + } else if (pos == QLatin1String("BottomLeft")) { + setFieldPosition(f, DrawParams::BottomLeft); + } else if (pos == QLatin1String("BottomCenter")) { + setFieldPosition(f, DrawParams::BottomCenter); + } else if (pos == QLatin1String("BottomRight")) { + setFieldPosition(f, DrawParams::BottomRight); + } else if (pos == QLatin1String("Default")) { + setFieldPosition(f, DrawParams::Default); + } +} + +QString TreeMapWidget::fieldPositionString(int f) const +{ + TreeMapItem::Position pos = fieldPosition(f); + if (pos == DrawParams::TopLeft) { + return QStringLiteral("TopLeft"); + } + if (pos == DrawParams::TopCenter) { + return QStringLiteral("TopCenter"); + } + if (pos == DrawParams::TopRight) { + return QStringLiteral("TopRight"); + } + if (pos == DrawParams::BottomLeft) { + return QStringLiteral("BottomLeft"); + } + if (pos == DrawParams::BottomCenter) { + return QStringLiteral("BottomCenter"); + } + if (pos == DrawParams::BottomRight) { + return QStringLiteral("BottomRight"); + } + if (pos == DrawParams::Default) { + return QStringLiteral("Default"); + } + return QStringLiteral("unknown"); +} + +void TreeMapWidget::setMinimalArea(int area) +{ + if (_minimalArea == area) { + return; + } + + _minimalArea = area; + redraw(); +} + +void TreeMapWidget::deletingItem(TreeMapItem *i) +{ + // remove any references to the item to be deleted + _selection.removeAll(i); + _tmpSelection.removeAll(i); + + if (_current == i) { + _current = nullptr; + } + if (_oldCurrent == i) { + _oldCurrent = nullptr; + } + if (_pressed == i) { + _pressed = nullptr; + } + if (_lastOver == i) { + _lastOver = nullptr; + } + + // do not redraw a deleted item + if (_needsRefresh == i) { + // we can safely redraw the parent, as deleting order is + // from child to parent; i.e. i->parent() is existing. + _needsRefresh = i->parent(); + } +} + +QString TreeMapWidget::tipString(TreeMapItem *i) const +{ + QString tip, itemTip; + + while (i) { + if (!i->text(0).isEmpty()) { + itemTip = i->text(0); + if (!i->text(1).isEmpty()) { + itemTip += " (" + i->text(1) + ')'; + } + + if (!tip.isEmpty()) { + tip += '\n'; + } + + tip += itemTip; + } + i = i->parent(); + } + return tip; +} + +TreeMapItem *TreeMapWidget::item(int x, int y) const +{ + + if (!rect().contains(x, y)) { + return nullptr; + } + if (DEBUG_DRAWING) { + kDebug(90100) << "item(" << x << "," << y << "):"; + } + + TreeMapItem *p = _base; + TreeMapItem *i; + while (1) { + TreeMapItemList *list = p->children(); + i = nullptr; + if (list) { + int idx; + for (idx = 0; idx < list->size(); idx++) { + i = list->at(idx); + + if (DEBUG_DRAWING) + kDebug(90100) << " Checking " << i->path(0).join(QStringLiteral("/")) << " (" + << i->itemRect().x() << "/" << i->itemRect().y() + << "-" << i->itemRect().width() + << "x" << i->itemRect().height() << ")" << endl; + + if (i->itemRect().contains(x, y)) { + + if (DEBUG_DRAWING) { + kDebug(90100) << " .. Got. Index " << idx; + } + + p->setIndex(idx); + break; + } + } + if (idx == list->size()) { + i = nullptr; // not contained in child + } + } + + if (!i) { + static TreeMapItem *last = nullptr; + if (p != last) { + last = p; + + if (DEBUG_DRAWING) + kDebug(90100) << "item(" << x << "," << y << "): Got " + << p->path(0).join(QStringLiteral("/")) << " (Size " + << p->itemRect().width() << "x" << p->itemRect().height() + << ", Val " << p->value() << ")" << endl; + } + + return p; + } + p = i; + } + return nullptr; +} + +TreeMapItem *TreeMapWidget::possibleSelection(TreeMapItem *i) const +{ + if (i) { + if (_maxSelectDepth >= 0) { + int depth = i->depth(); + while (i && depth > _maxSelectDepth) { + i = i->parent(); + depth--; + } + } + } + return i; +} + +TreeMapItem *TreeMapWidget::visibleItem(TreeMapItem *i) const +{ + if (i) { + /* Must have a visible area */ + while (i && ((i->itemRect().width() < 1) || + (i->itemRect().height() < 1))) { + TreeMapItem *p = i->parent(); + if (!p) { + break; + } + int idx = p->children()->indexOf(i); + idx--; + if (idx < 0) { + i = p; + } else { + i = p->children()->at(idx); + } + } + } + return i; +} + +void TreeMapWidget::setSelected(TreeMapItem *item, bool selected) +{ + if (!item) { + return; + } + item = possibleSelection(item); + setCurrent(item); + + TreeMapItem *changed = setTmpSelected(item, selected); + if (!changed) { + return; + } + + _selection = _tmpSelection; + if (_selectionMode == Single) { + emit selectionChanged(item); + } + emit selectionChanged(); + redraw(changed); + + if (0) kDebug(90100) << (selected ? "S" : "Des") << "elected Item " + << (item ? item->path(0).join(QLatin1String("")) : QStringLiteral("(null)")) + << " (depth " << (item ? item->depth() : -1) + << ")" << endl; +} + +void TreeMapWidget::setMarked(int markNo, bool redrawWidget) +{ + // if there is no marking, return + if ((_markNo == 0) && (markNo == 0)) { + return; + } + + _markNo = markNo; + if (!clearSelection() && redrawWidget) { + redraw(); + } +} + +/* Returns all items which appear only in one of the given lists */ +TreeMapItemList TreeMapWidget::diff(TreeMapItemList &l1, + TreeMapItemList &l2) +{ + TreeMapItemList l; + + foreach (TreeMapItem *i, l1) + if (!l2.contains(i)) { + l.append(i); + } + + foreach (TreeMapItem *i, l2) + if (!l1.contains(i)) { + l.append(i); + } + + return l; +} + +/* Only modifies _tmpSelection. + * Returns 0 when no change happened, otherwise the TreeMapItem that has + * to be redrawn for all changes. + */ +TreeMapItem *TreeMapWidget::setTmpSelected(TreeMapItem *item, bool selected) +{ + if (!item) { + return nullptr; + } + if (_selectionMode == NoSelection) { + return nullptr; + } + + TreeMapItemList old = _tmpSelection; + + if (_selectionMode == Single) { + _tmpSelection.clear(); + if (selected) { + _tmpSelection.append(item); + } + } else { + if (selected) { + // first remove any selection which is parent or child of + foreach (TreeMapItem *i, _tmpSelection) + if (i->isChildOf(item) || item->isChildOf(i)) { + _tmpSelection.removeAll(i); + } + + _tmpSelection.append(item); + } else { + _tmpSelection.removeAll(item); + } + } + + return diff(old, _tmpSelection).commonParent(); +} + +bool TreeMapWidget::clearSelection(TreeMapItem *parent) +{ + TreeMapItemList old = _selection; + + // remove any selection which is child of + foreach (TreeMapItem *i, _selection) + if (i->isChildOf(parent)) { + _selection.removeAll(i); + } + + TreeMapItem *changed = diff(old, _selection).commonParent(); + if (changed) { + _tmpSelection = _selection; + changed->redraw(); + emit selectionChanged(); + } + return (changed != nullptr); +} + +bool TreeMapWidget::isSelected(TreeMapItem *i) const +{ + if (!i) { + return false; + } + return _selection.contains(i); +} + +bool TreeMapWidget::isTmpSelected(TreeMapItem *i) +{ + if (!i) { + return false; + } + return _tmpSelection.contains(i); +} + +void TreeMapWidget::setCurrent(TreeMapItem *i, bool kbd) +{ + TreeMapItem *old = _current; + _current = i; + + if (_markNo > 0) { + // remove mark + _markNo = 0; + + if (1) kDebug(90100) << "setCurrent(" << i->path(0).join(QStringLiteral("/")) + << ") - mark removed" << endl; + + // always complete redraw needed to remove mark + redraw(); + + if (old == _current) { + return; + } + } else { + if (old == _current) { + return; + } + + if (old) { + old->redraw(); + } + if (i) { + i->redraw(); + } + } + + //kDebug(90100) << "Current Item " << (i ? i->path().ascii() : "(null)"); + + emit currentChanged(i, kbd); +} + +void TreeMapWidget::setRangeSelection(TreeMapItem *i1, + TreeMapItem *i2, bool selected) +{ + i1 = possibleSelection(i1); + i2 = possibleSelection(i2); + setCurrent(i2); + + TreeMapItem *changed = setTmpRangeSelection(i1, i2, selected); + if (!changed) { + return; + } + + _selection = _tmpSelection; + if (_selectionMode == Single) { + emit selectionChanged(i2); + } + emit selectionChanged(); + redraw(changed); +} + +TreeMapItem *TreeMapWidget::setTmpRangeSelection(TreeMapItem *i1, + TreeMapItem *i2, + bool selected) +{ + if ((i1 == nullptr) && (i2 == nullptr)) { + return nullptr; + } + if ((i1 == nullptr) || i1->isChildOf(i2)) { + return setTmpSelected(i2, selected); + } + if ((i2 == nullptr) || i2->isChildOf(i1)) { + return setTmpSelected(i1, selected); + } + + TreeMapItem *changed = setTmpSelected(i1, selected); + TreeMapItem *changed2 = setTmpSelected(i2, selected); + if (changed2) { + changed = changed2->commonParent(changed); + } + + TreeMapItem *commonParent = i1; + while (commonParent && !i2->isChildOf(commonParent)) { + i1 = commonParent; + commonParent = commonParent->parent(); + } + if (!commonParent) { + return changed; + } + while (i2 && i2->parent() != commonParent) { + i2 = i2->parent(); + } + if (!i2) { + return changed; + } + + TreeMapItemList *list = commonParent->children(); + if (!list) { + return changed; + } + + bool between = false; + foreach (TreeMapItem *i, *list) { + if (between) { + if (i == i1 || i == i2) { + break; + } + changed2 = setTmpSelected(i, selected); + if (changed2) { + changed = changed2->commonParent(changed); + } + } else if (i == i1 || i == i2) { + between = true; + } + } + + return changed; +} + +void TreeMapWidget::contextMenuEvent(QContextMenuEvent *e) +{ + //kDebug(90100) << "TreeMapWidget::contextMenuEvent"; + + if (receivers(SIGNAL(contextMenuRequested(TreeMapItem*,QPoint)))) { + e->accept(); + } + + if (e->reason() == QContextMenuEvent::Keyboard) { + QRect r = (_current) ? _current->itemRect() : _base->itemRect(); + QPoint p = QPoint(r.left() + r.width() / 2, r.top() + r.height() / 2); + emit contextMenuRequested(_current, p); + } else { + TreeMapItem *i = item(e->x(), e->y()); + emit contextMenuRequested(i, e->pos()); + } +} + +void TreeMapWidget::mousePressEvent(QMouseEvent *e) +{ + //kDebug(90100) << "TreeMapWidget::mousePressEvent"; + + _oldCurrent = _current; + + TreeMapItem *i = item(e->x(), e->y()); + + _pressed = i; + + _inShiftDrag = e->modifiers().testFlag(Qt::ShiftModifier); + _inControlDrag = e->modifiers().testFlag(Qt::ControlModifier); + _lastOver = _pressed; + + TreeMapItem *changed = nullptr; + TreeMapItem *item = possibleSelection(_pressed); + + switch (_selectionMode) { + case Single: + changed = setTmpSelected(item, true); + break; + case Multi: + changed = setTmpSelected(item, !isTmpSelected(item)); + break; + case Extended: + if (_inControlDrag) { + changed = setTmpSelected(item, !isTmpSelected(item)); + } else if (_inShiftDrag) { + TreeMapItem *sCurrent = possibleSelection(_current); + changed = setTmpRangeSelection(sCurrent, item, + !isTmpSelected(item)); + } else { + _selectionMode = Single; + changed = setTmpSelected(item, true); + _selectionMode = Extended; + } + break; + default: + break; + } + + // item under mouse always selected on right button press + if (e->button() == Qt::RightButton) { + TreeMapItem *changed2 = setTmpSelected(item, true); + if (changed2) { + changed = changed2->commonParent(changed); + } + } + + setCurrent(_pressed); + + if (changed) { + redraw(changed); + } + + if (e->button() == Qt::RightButton) { + + // emit selection change + if (!(_tmpSelection == _selection)) { + _selection = _tmpSelection; + if (_selectionMode == Single) { + emit selectionChanged(_lastOver); + } + emit selectionChanged(); + } + _pressed = nullptr; + _lastOver = nullptr; + emit rightButtonPressed(i, e->pos()); + } +} + +void TreeMapWidget::mouseMoveEvent(QMouseEvent *e) +{ + //kDebug(90100) << "TreeMapWidget::mouseMoveEvent"; + + if (!_pressed) { + return; + } + TreeMapItem *over = item(e->x(), e->y()); + if (_lastOver == over) { + return; + } + + setCurrent(over); + if (over == nullptr) { + _lastOver = nullptr; + return; + } + + TreeMapItem *changed = nullptr; + TreeMapItem *item = possibleSelection(over); + + switch (_selectionMode) { + case Single: + changed = setTmpSelected(item, true); + break; + case Multi: + changed = setTmpSelected(item, !isTmpSelected(item)); + break; + case Extended: + if (_inControlDrag) { + changed = setTmpSelected(item, !isTmpSelected(item)); + } else { + TreeMapItem *sLast = possibleSelection(_lastOver); + changed = setTmpRangeSelection(sLast, item, true); + } + break; + + default: + break; + } + + _lastOver = over; + + if (changed) { + redraw(changed); + } +} + +void TreeMapWidget::mouseReleaseEvent(QMouseEvent *) +{ + //kDebug(90100) << "TreeMapWidget::mouseReleaseEvent"; + + if (!_pressed) { + return; + } + + if (!_lastOver) { + // take back + setCurrent(_oldCurrent); + TreeMapItem *changed = diff(_tmpSelection, _selection).commonParent(); + _tmpSelection = _selection; + if (changed) { + redraw(changed); + } + } else { + if (!(_tmpSelection == _selection)) { + _selection = _tmpSelection; + if (_selectionMode == Single) { + emit selectionChanged(_lastOver); + } + emit selectionChanged(); + } + if (!_inControlDrag && !_inShiftDrag && (_pressed == _lastOver)) { + emit clicked(_lastOver); + } + } + + _pressed = nullptr; + _lastOver = nullptr; +} + +void TreeMapWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + TreeMapItem *over = item(e->x(), e->y()); + + emit doubleClicked(over); +} + +/* returns -1 if nothing visible found */ +int nextVisible(TreeMapItem *i) +{ + TreeMapItem *p = i->parent(); + if (!p || p->itemRect().isEmpty()) { + return -1; + } + + int idx = p->children()->indexOf(i); + if (idx < 0) { + return -1; + } + + while (idx < p->children()->count() - 1) { + idx++; + QRect r = p->children()->at(idx)->itemRect(); + if (r.width() > 1 && r.height() > 1) { + return idx; + } + } + return -1; +} + +/* returns -1 if nothing visible found */ +int prevVisible(TreeMapItem *i) +{ + TreeMapItem *p = i->parent(); + if (!p || p->itemRect().isEmpty()) { + return -1; + } + + int idx = p->children()->indexOf(i); + if (idx < 0) { + return -1; + } + + while (idx > 0) { + idx--; + QRect r = p->children()->at(idx)->itemRect(); + if (r.width() > 1 && r.height() > 1) { + return idx; + } + } + return -1; +} + +void TreeMapWidget::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape && _pressed) { + + // take back + if (_oldCurrent != _lastOver) { + setCurrent(_oldCurrent); + } + if (!(_tmpSelection == _selection)) { + TreeMapItem *changed = diff(_tmpSelection, _selection).commonParent(); + _tmpSelection = _selection; + if (changed) { + redraw(changed); + } + } + _pressed = nullptr; + _lastOver = nullptr; + } + + if ((e->key() == Qt::Key_Space) || + (e->key() == Qt::Key_Return)) { + + switch (_selectionMode) { + case NoSelection: + break; + case Single: + setSelected(_current, true); + break; + case Multi: + setSelected(_current, !isSelected(_current)); + break; + case Extended: + if (e->modifiers().testFlag(Qt::ControlModifier) || + e->modifiers().testFlag(Qt::ShiftModifier)) { + setSelected(_current, !isSelected(_current)); + } else { + _selectionMode = Single; + setSelected(_current, true); + _selectionMode = Extended; + } + } + + if (_current && (e->key() == Qt::Key_Return)) { + emit returnPressed(_current); + } + + return; + } + + if (!_current) { + if (e->key() == Qt::Key_Down) { + setCurrent(_base, true); + } + return; + } + + TreeMapItem *old = _current, *newItem; + TreeMapItem *p = _current->parent(); + + bool goBack; + if (_current->sorting(&goBack) == -1) { + // noSorting + goBack = false; + } + + if ((e->key() == Qt::Key_Backspace) || + (e->key() == Qt::Key_Up)) { + newItem = visibleItem(p); + setCurrent(newItem, true); + } else if (e->key() == Qt::Key_Left) { + int newIdx = goBack ? nextVisible(_current) : prevVisible(_current); + if (p && newIdx >= 0) { + p->setIndex(newIdx); + setCurrent(p->children()->at(newIdx), true); + } + } else if (e->key() == Qt::Key_Right) { + int newIdx = goBack ? prevVisible(_current) : nextVisible(_current); + if (p && newIdx >= 0) { + p->setIndex(newIdx); + setCurrent(p->children()->at(newIdx), true); + } + } else if (e->key() == Qt::Key_Down) { + if (_current->children() && _current->children()->count() > 0) { + int newIdx = _current->index(); + if (newIdx < 0) { + newIdx = goBack ? (_current->children()->count() - 1) : 0; + } + if (newIdx >= _current->children()->count()) { + newIdx = _current->children()->count() - 1; + } + newItem = visibleItem(_current->children()->at(newIdx)); + setCurrent(newItem, true); + } + } + + if (old == _current) { + return; + } + if (!e->modifiers().testFlag(Qt::ControlModifier)) { + return; + } + if (!e->modifiers().testFlag(Qt::ShiftModifier)) { + return; + } + + switch (_selectionMode) { + case NoSelection: + break; + case Single: + setSelected(_current, true); + break; + case Multi: + setSelected(_current, !isSelected(_current)); + break; + case Extended: + if (e->modifiers().testFlag(Qt::ControlModifier)) { + setSelected(_current, !isSelected(_current)); + } else { + setSelected(_current, isSelected(old)); + } + } +} + +void TreeMapWidget::fontChange(const QFont &) +{ + redraw(); +} + +// react on tooltip events +bool TreeMapWidget::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + QHelpEvent *helpEvent = static_cast(event); + TreeMapItem *i = item(helpEvent->pos().x(), helpEvent->pos().y()); + bool hasTip = false; + if (i) { + const QList &rList = i->freeRects(); + foreach (const QRect &r, rList) { + if (r.contains(helpEvent->pos())) { + hasTip = true; + break; + } + } + } + if (hasTip) { + QToolTip::showText(helpEvent->globalPos(), tipString(i)); + } else { + QToolTip::hideText(); + } + } + return QWidget::event(event); +} + +void TreeMapWidget::paintEvent(QPaintEvent *) +{ + drawTreeMap(); +} + +// Updates screen from shadow buffer, +// but redraws before if needed +void TreeMapWidget::drawTreeMap() +{ + // no need to draw if hidden + if (!isVisible()) { + return; + } + + if (_pixmap.size() != size()) { + _needsRefresh = _base; + } + + if (_needsRefresh) { + + if (DEBUG_DRAWING) { + kDebug(90100) << "Redrawing " << _needsRefresh->path(0).join(QStringLiteral("/")); + } + + if (_needsRefresh == _base) { + // redraw whole widget + _pixmap = QPixmap(size()); + _pixmap.fill(palette().color(backgroundRole())); + } + QPainter p(&_pixmap); + if (_needsRefresh == _base) { + p.setPen(Qt::black); + p.drawRect(QRect(2, 2, QWidget::width() - 5, QWidget::height() - 5)); + _base->setItemRect(QRect(3, 3, QWidget::width() - 6, QWidget::height() - 6)); + } else { + // only subitem + if (!_needsRefresh->itemRect().isValid()) { + return; + } + } + + // reset cached font object; it could have been changed + _font = font(); + _fontHeight = fontMetrics().height(); + + drawItems(&p, _needsRefresh); + _needsRefresh = nullptr; + } + + QStylePainter p(this); + p.drawPixmap(0, 0, width(), height(), _pixmap); + + if (hasFocus()) { + QStyleOptionFocusRect opt; + opt.rect = rect(); + opt.palette = palette(); + opt.state = QStyle::State_None; + p.drawPrimitive(QStyle::PE_FrameFocusRect, opt); + } +} + +void TreeMapWidget::redraw(TreeMapItem *i) +{ + if (!i) { + return; + } + + if (!_needsRefresh) { + _needsRefresh = i; + } else { + if (!i->isChildOf(_needsRefresh)) { + _needsRefresh = _needsRefresh->commonParent(i); + } + } + + if (isVisible()) { + // delayed drawing if we have multiple redraw requests + update(); + } +} + +void TreeMapWidget::drawItem(QPainter *p, + TreeMapItem *item) +{ + bool isSelected = false; + + if (_markNo > 0) { + for (TreeMapItem *i = item; i; i = i->parent()) { + if (i->isMarked(_markNo)) { + isSelected = true; + break; + } + } + } else { + foreach (TreeMapItem *i, _tmpSelection) { + if (item->isChildOf(i)) { + isSelected = true; + break; + } + } + } + + bool isCurrent = _current && item->isChildOf(_current); + int dd = item->depth(); + if (isTransparent(dd)) { + return; + } + + RectDrawing d(item->itemRect()); + item->setSelected(isSelected); + item->setCurrent(isCurrent); + item->setShaded(_shading); + item->drawFrame(drawFrame(dd)); + d.drawBack(p, item); +} + +bool TreeMapWidget::horizontal(TreeMapItem *i, const QRect &r) +{ + switch (i->splitMode()) { + case TreeMapItem::HAlternate: + return (i->depth() % 2) == 1; + case TreeMapItem::VAlternate: + return (i->depth() % 2) == 0; + case TreeMapItem::Horizontal: + return true; + case TreeMapItem::Vertical: + return false; + default: + return r.width() > r.height(); + } + return false; +} + +/** + * Draw TreeMapItems recursive, starting from item + */ +void TreeMapWidget::drawItems(QPainter *p, + TreeMapItem *item) +{ + if (DEBUG_DRAWING) + kDebug(90100) << "+drawItems(" << item->path(0).join(QStringLiteral("/")) << ", " + << item->itemRect().x() << "/" << item->itemRect().y() + << "-" << item->itemRect().width() << "x" + << item->itemRect().height() << "), Val " << item->value() + << ", Sum " << item->sum() << endl; + + drawItem(p, item); + item->clearFreeRects(); + + QRect origRect = item->itemRect(); + int bw = item->borderWidth(); + QRect r = QRect(origRect.x() + bw, origRect.y() + bw, + origRect.width() - 2 * bw, origRect.height() - 2 * bw); + + TreeMapItemList *list = item->children(); + + bool stopDrawing = false; + + // only subdivide if there are children + if (!list || list->count() == 0) { + stopDrawing = true; + } + + // only subdivide if there is enough space + if (!stopDrawing && (r.width() <= 0 || r.height() <= 0)) { + stopDrawing = true; + } + + // stop drawing if maximum depth is reached + if (!stopDrawing && + (_maxDrawingDepth >= 0 && item->depth() >= _maxDrawingDepth)) { + stopDrawing = true; + } + + // stop drawing if stopAtText is reached + if (!stopDrawing) + for (int no = 0; no < _attr.size(); no++) { + QString stopAt = fieldStop(no); + if (!stopAt.isEmpty() && (item->text(no) == stopAt)) { + stopDrawing = true; + break; + } + } + + // area size is checked later... +#if 0 + // stop drawing if minimal area size is reached + if (!stopDrawing && + (_minimalArea > 0) && + (r.width() * r.height() < _minimalArea)) { + stopDrawing = true; + } +#endif + + if (stopDrawing) { + if (list) { + // invalidate rects + foreach (TreeMapItem *i, *list) { + i->clearItemRect(); + } + } + // tooltip appears on whole item rect + item->addFreeRect(item->itemRect()); + + // if we have space for text... + if ((r.height() < _fontHeight) || (r.width() < _fontHeight)) { + return; + } + + RectDrawing d(r); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no = 0; no < _attr.size(); no++) { + if (!fieldVisible(no)) { + continue; + } + d.drawField(p, no, item); + } + r = d.remainingRect(item); + + if (DEBUG_DRAWING) { + kDebug(90100) << "-drawItems(" << item->path(0).join(QStringLiteral("/")) << ")"; + } + return; + } + + double user_sum, child_sum, self; + + // user supplied sum + user_sum = item->sum(); + + // own sum + child_sum = 0; + foreach (TreeMapItem *i, *list) { + child_sum += i->value(); + if (DEBUG_DRAWING) + kDebug(90100) << " child: " << i->text(0) << ", value " + << i->value() << endl; + } + + QRect orig = r; + + // if we have space for text... + if ((r.height() >= _fontHeight) && (r.width() >= _fontHeight)) { + + RectDrawing d(r); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no = 0; no < _attr.size(); no++) { + if (!fieldVisible(no)) { + continue; + } + if (!fieldForced(no)) { + continue; + } + d.drawField(p, no, item); + } + r = d.remainingRect(item); + } + + if (orig.x() == r.x()) { + // Strings on top + item->addFreeRect(QRect(orig.x(), orig.y(), + orig.width(), orig.height() - r.height())); + } else { + // Strings on the left + item->addFreeRect(QRect(orig.x(), orig.y(), + orig.width() - r.width(), orig.height())); + } + + if (user_sum == 0) { + // user did not supply any sum + user_sum = child_sum; + self = 0; + } else { + self = user_sum - child_sum; + + if (user_sum < child_sum) { + //kDebug(90100) << "TreeMWidget " << + // item->path() << ": User sum " << user_sum << " < Child Items sum " << child_sum << endl; + + // invalid user supplied sum: ignore and use calculate sum + user_sum = child_sum; + self = 0.0; + } else { + // Try to put the border waste in self + // percent of wasted space on border... + float borderArea = origRect.width() * origRect.height(); + borderArea = (borderArea - r.width() * r.height()) / borderArea; + unsigned borderValue = (unsigned)(borderArea * user_sum); + + if (borderValue > self) { + if (_skipIncorrectBorder) { + r = origRect; + // should add my self to nested self and set my self =0 + } else { + self = 0.0; + } + } else { + self -= borderValue; + } + + user_sum = child_sum + self; + } + } + + bool rotate = (_allowRotation && (r.height() > r.width())); + int self_length = (int)(((rotate) ? r.width() : r.height()) * + self / user_sum + .5); + if (self_length > 0) { + // take space for self cost + QRect sr = r; + if (rotate) { + sr.setWidth(self_length); + r.setRect(r.x() + sr.width(), r.y(), r.width() - sr.width(), r.height()); + } else { + sr.setHeight(self_length); + r.setRect(r.x(), r.y() + sr.height(), r.width(), r.height() - sr.height()); + } + + // set selfRect (not occupied by children) for tooltip + item->addFreeRect(sr); + + if (0) kDebug(90100) << "Item " << item->path(0).join(QStringLiteral("/")) << ": SelfR " + << sr.x() << "/" << sr.y() << "-" << sr.width() + << "/" << sr.height() << ", self " << self << "/" + << user_sum << endl; + + if ((sr.height() >= _fontHeight) && (sr.width() >= _fontHeight)) { + + RectDrawing d(sr); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no = 0; no < _attr.size(); no++) { + if (!fieldVisible(no)) { + continue; + } + if (fieldForced(no)) { + continue; + } + d.drawField(p, no, item); + } + } + + user_sum -= self; + } + + bool goBack; + if (item->sorting(&goBack) == -1) { + // noSorting + goBack = false; + } + + int idx = goBack ? (list->size() - 1) : 0; + + if (item->splitMode() == TreeMapItem::Columns) { + int len = list->count(); + bool drawDetails = true; + + while (len > 0 && user_sum > 0) { + int firstIdx = idx; + double valSum = 0; + int lenLeft = len; + int columns = (int)(sqrt((double)len * r.width() / r.height()) + .5); + if (columns == 0) { + columns = 1; //should never be needed + } + + while (lenLeft > 0 && ((double)valSum * (len - lenLeft) < + (double)len * user_sum / columns / columns)) { + valSum += list->at(idx)->value(); + if (goBack) { + --idx; + } else { + ++idx; + } + lenLeft--; + } + + // we always split horizontally + int nextPos = (int)((double)r.width() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), nextPos, r.height()); + + if (nextPos < _visibleWidth) { + if (item->sorting(nullptr) == -1) { + // fill current rect with hash pattern + drawFill(item, p, firstRect); + } else { + // fill rest with hash pattern + drawFill(item, p, r, list, firstIdx, len, goBack); + break; + } + } else { + drawDetails = drawItemArray(p, item, firstRect, + valSum, list, firstIdx, len - lenLeft, goBack); + } + r.setRect(r.x() + nextPos, r.y(), r.width() - nextPos, r.height()); + user_sum -= valSum; + len = lenLeft; + + if (!drawDetails) { + if (item->sorting(nullptr) == -1) { + drawDetails = true; + } else { + drawFill(item, p, r, list, idx, len, goBack); + break; + } + } + } + } else if (item->splitMode() == TreeMapItem::Rows) { + int len = list->count(); + bool drawDetails = true; + + while (len > 0 && user_sum > 0) { + int firstIdx = idx; + double valSum = 0; + int lenLeft = len; + int rows = (int)(sqrt((double)len * r.height() / r.width()) + .5); + if (rows == 0) { + rows = 1; //should never be needed + } + + while (lenLeft > 0 && ((double)valSum * (len - lenLeft) < + (double)len * user_sum / rows / rows)) { + valSum += list->at(idx)->value(); + if (goBack) { + --idx; + } else { + ++idx; + } + lenLeft--; + } + + // we always split horizontally + int nextPos = (int)((double)r.height() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), r.width(), nextPos); + + if (nextPos < _visibleWidth) { + if (item->sorting(nullptr) == -1) { + drawFill(item, p, firstRect); + } else { + drawFill(item, p, r, list, firstIdx, len, goBack); + break; + } + } else { + drawDetails = drawItemArray(p, item, firstRect, + valSum, list, firstIdx, len - lenLeft, goBack); + } + r.setRect(r.x(), r.y() + nextPos, r.width(), r.height() - nextPos); + user_sum -= valSum; + len = lenLeft; + + if (!drawDetails) { + if (item->sorting(nullptr) == -1) { + drawDetails = true; + } else { + drawFill(item, p, r, list, idx, len, goBack); + break; + } + } + } + } else { + drawItemArray(p, item, r, user_sum, list, idx, list->count(), goBack); + } + + if (DEBUG_DRAWING) { + kDebug(90100) << "-drawItems(" << item->path(0).join(QStringLiteral("/")) << ")"; + } +} + +// fills area with a pattern if to small to draw children +void TreeMapWidget::drawFill(TreeMapItem *i, QPainter *p, const QRect &r) +{ + p->setBrush(Qt::Dense4Pattern); + p->setPen(Qt::NoPen); + p->drawRect(QRect(r.x(), r.y(), r.width() - 1, r.height() - 1)); + i->addFreeRect(r); +} + +// fills area with a pattern if to small to draw children +void TreeMapWidget::drawFill(TreeMapItem *i, QPainter *p, const QRect &r, + TreeMapItemList *list, int idx, int len, bool goBack) +{ + if (DEBUG_DRAWING) + kDebug(90100) << " +drawFill(" << r.x() << "/" << r.y() + << "-" << r.width() << "x" << r.height() + << ", len " << len << ")" << endl; + + p->setBrush(Qt::Dense4Pattern); + p->setPen(Qt::NoPen); + p->drawRect(QRect(r.x(), r.y(), r.width() - 1, r.height() - 1)); + i->addFreeRect(r); + + // reset rects + while (len > 0 && (i = list->value(idx))) { + + if (DEBUG_DRAWING) { + kDebug(90100) << " Reset Rect " << i->path(0).join(QStringLiteral("/")); + } + + i->clearItemRect(); + if (goBack) { + --idx; + } else { + ++idx; + } + len--; + } + if (DEBUG_DRAWING) + kDebug(90100) << " -drawFill(" << r.x() << "/" << r.y() + << "-" << r.width() << "x" << r.height() + << ", len " << len << ")" << endl; +} + +// returns false if rect gets to small +bool TreeMapWidget::drawItemArray(QPainter *p, TreeMapItem *item, + const QRect &r, double user_sum, + TreeMapItemList *list, int idx, int len, + bool goBack) +{ + if (user_sum == 0) { + return false; + } + + static bool b2t = true; + + // stop recursive bisection for small rectangles + if (((r.height() < _visibleWidth) && + (r.width() < _visibleWidth)) || + ((_minimalArea > 0) && + (r.width() * r.height() < _minimalArea))) { + + drawFill(item, p, r, list, idx, len, goBack); + return false; + } + + if (DEBUG_DRAWING) + kDebug(90100) << " +drawItemArray(" << item->path(0).join(QStringLiteral("/")) + << ", " << r.x() << "/" << r.y() << "-" << r.width() + << "x" << r.height() << ")" << endl; + + if (len > 2 && (item->splitMode() == TreeMapItem::Bisection)) { + + int firstIdx = idx; + double valSum = 0; + int lenLeft = len; + //while (lenLeft>0 && valSum len / 2) { + valSum += list->at(idx)->value(); + if (goBack) { + --idx; + } else { + ++idx; + } + lenLeft--; + } + + // draw first half... + bool drawOn; + QRect secondRect; + + if (r.width() > r.height()) { + int halfPos = (int)((double)r.width() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), halfPos, r.height()); + drawOn = drawItemArray(p, item, firstRect, + valSum, list, firstIdx, len - lenLeft, goBack); + secondRect.setRect(r.x() + halfPos, r.y(), r.width() - halfPos, r.height()); + } else { + int halfPos = (int)((double)r.height() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), r.width(), halfPos); + drawOn = drawItemArray(p, item, firstRect, + valSum, list, firstIdx, len - lenLeft, goBack); + secondRect.setRect(r.x(), r.y() + halfPos, r.width(), r.height() - halfPos); + } + + // if no sorting, do not stop drawing + if (item->sorting(nullptr) == -1) { + drawOn = true; + } + + // second half + if (drawOn) + drawOn = drawItemArray(p, item, secondRect, user_sum - valSum, + list, idx, lenLeft, goBack); + else { + drawFill(item, p, secondRect, list, idx, len, goBack); + } + + if (DEBUG_DRAWING) + kDebug(90100) << " -drawItemArray(" << item->path(0).join(QStringLiteral("/")) + << ")" << endl; + + return drawOn; + } + + bool hor = horizontal(item, r); + + TreeMapItem *i; + QRect fullRect = r; + while (len > 0) { + i = list->at(idx); + if (user_sum <= 0) { + + if (DEBUG_DRAWING) { + kDebug(90100) << "drawItemArray: Reset " << i->path(0).join(QStringLiteral("/")); + } + + i->clearItemRect(); + if (goBack) { + --idx; + } else { + ++idx; + } + len--; + continue; + } + + // stop drawing for small rectangles + if (((fullRect.height() < _visibleWidth) && + (fullRect.width() < _visibleWidth)) || + ((_minimalArea > 0) && + (fullRect.width() * fullRect.height() < _minimalArea))) { + + drawFill(item, p, fullRect, list, idx, len, goBack); + if (DEBUG_DRAWING) + kDebug(90100) << " -drawItemArray(" << item->path(0).join(QStringLiteral("/")) + << "): Stop" << endl; + return false; + } + + if (i->splitMode() == TreeMapItem::AlwaysBest) { + hor = fullRect.width() > fullRect.height(); + } + + int lastPos = hor ? fullRect.width() : fullRect.height(); + double val = i->value(); + int nextPos = (user_sum <= 0.0) ? 0 : (int)(lastPos * val / user_sum + .5); + if (nextPos > lastPos) { + nextPos = lastPos; + } + + if ((item->sorting(nullptr) != -1) && (nextPos < _visibleWidth)) { + drawFill(item, p, fullRect, list, idx, len, goBack); + if (DEBUG_DRAWING) + kDebug(90100) << " -drawItemArray(" << item->path(0).join(QStringLiteral("/")) + << "): Stop" << endl; + return false; + } + + QRect currRect = fullRect; + + if (hor) { + currRect.setWidth(nextPos); + } else { + if (b2t) { + currRect.setRect(fullRect.x(), fullRect.bottom() - nextPos + 1, fullRect.width(), nextPos); + } else { + currRect.setHeight(nextPos); + } + } + + // do not draw very small rectangles: + if (nextPos >= _visibleWidth) { + i->setItemRect(currRect); + drawItems(p, i); + } else { + i->clearItemRect(); + drawFill(item, p, currRect); + } + + // draw Separator + if (_drawSeparators && (nextPos < lastPos)) { + p->setPen(Qt::black); + if (hor) { + if (fullRect.top() <= fullRect.bottom()) { + p->drawLine(fullRect.x() + nextPos, fullRect.top(), fullRect.x() + nextPos, fullRect.bottom()); + } + } else { + if (fullRect.left() <= fullRect.right()) { + p->drawLine(fullRect.left(), fullRect.y() + nextPos, fullRect.right(), fullRect.y() + nextPos); + } + } + nextPos++; + } + + if (hor) + fullRect.setRect(fullRect.x() + nextPos, fullRect.y(), + lastPos - nextPos, fullRect.height()); + else { + if (b2t) + fullRect.setRect(fullRect.x(), fullRect.y(), + fullRect.width(), lastPos - nextPos); + else + fullRect.setRect(fullRect.x(), fullRect.y() + nextPos, + fullRect.width(), lastPos - nextPos); + } + + user_sum -= val; + if (goBack) { + --idx; + } else { + ++idx; + } + len--; + } + + if (DEBUG_DRAWING) + kDebug(90100) << " -drawItemArray(" << item->path(0).join(QStringLiteral("/")) + << "): Continue" << endl; + + return true; +} + +/*---------------------------------------------------------------- + * Popup menus for option setting + */ + +void TreeMapWidget::splitActivated(QAction *a) +{ + int id = a->data().toInt(); + if (id == _splitID) { + setSplitMode(TreeMapItem::Bisection); + } else if (id == _splitID + 1) { + setSplitMode(TreeMapItem::Columns); + } else if (id == _splitID + 2) { + setSplitMode(TreeMapItem::Rows); + } else if (id == _splitID + 3) { + setSplitMode(TreeMapItem::AlwaysBest); + } else if (id == _splitID + 4) { + setSplitMode(TreeMapItem::Best); + } else if (id == _splitID + 5) { + setSplitMode(TreeMapItem::VAlternate); + } else if (id == _splitID + 6) { + setSplitMode(TreeMapItem::HAlternate); + } else if (id == _splitID + 7) { + setSplitMode(TreeMapItem::Horizontal); + } else if (id == _splitID + 8) { + setSplitMode(TreeMapItem::Vertical); + } +} + +void TreeMapWidget::addSplitDirectionItems(QMenu *popup, int id) +{ + _splitID = id; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(splitActivated(QAction*))); + + addPopupItem(popup, i18n("Recursive Bisection"), + splitMode() == TreeMapItem::Bisection, id++); + addPopupItem(popup, i18n("Columns"), + splitMode() == TreeMapItem::Columns, id++); + addPopupItem(popup, i18n("Rows"), + splitMode() == TreeMapItem::Rows, id++); + addPopupItem(popup, i18n("Always Best"), + splitMode() == TreeMapItem::AlwaysBest, id++); + addPopupItem(popup, i18n("Best"), + splitMode() == TreeMapItem::Best, id++); + addPopupItem(popup, i18n("Alternate (V)"), + splitMode() == TreeMapItem::VAlternate, id++); + addPopupItem(popup, i18n("Alternate (H)"), + splitMode() == TreeMapItem::HAlternate, id++); + addPopupItem(popup, i18n("Horizontal"), + splitMode() == TreeMapItem::Horizontal, id++); + addPopupItem(popup, i18n("Vertical"), + splitMode() == TreeMapItem::Vertical, id++); +} + +void TreeMapWidget::visualizationActivated(QAction *a) +{ + int id = a->data().toInt(); + if (id == _visID + 2) { + setSkipIncorrectBorder(!skipIncorrectBorder()); + } else if (id == _visID + 3) { + setBorderWidth(0); + } else if (id == _visID + 4) { + setBorderWidth(1); + } else if (id == _visID + 5) { + setBorderWidth(2); + } else if (id == _visID + 6) { + setBorderWidth(3); + } else if (id == _visID + 10) { + setAllowRotation(!allowRotation()); + } else if (id == _visID + 11) { + setShadingEnabled(!isShadingEnabled()); + } else if (id < _visID + 19 || id > _visID + 100) { + return; + } + + id -= 20 + _visID; + int f = id / 10; + if ((id % 10) == 1) { + setFieldVisible(f, !fieldVisible(f)); + } else if ((id % 10) == 2) { + setFieldForced(f, !fieldForced(f)); + } else if ((id % 10) == 3) { + setFieldPosition(f, DrawParams::TopLeft); + } else if ((id % 10) == 4) { + setFieldPosition(f, DrawParams::TopCenter); + } else if ((id % 10) == 5) { + setFieldPosition(f, DrawParams::TopRight); + } else if ((id % 10) == 6) { + setFieldPosition(f, DrawParams::BottomLeft); + } else if ((id % 10) == 7) { + setFieldPosition(f, DrawParams::BottomCenter); + } else if ((id % 10) == 8) { + setFieldPosition(f, DrawParams::BottomRight); + } +} + +void TreeMapWidget::addVisualizationItems(QMenu *popup, int id) +{ + _visID = id; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(visualizationActivated(QAction*))); + + QMenu *spopup = new QMenu(i18n("Nesting")); + addSplitDirectionItems(spopup, id + 100); + popup->addMenu(spopup); + + QMenu *bpopup = new QMenu(i18n("Border")); + popup->addMenu(bpopup); + + addPopupItem(bpopup, i18n("Correct Borders Only"), skipIncorrectBorder(), id + 2); + bpopup->addSeparator(); + for (int i = 0; i < 4; ++i) { + addPopupItem(bpopup, i18n("Width %1", i), borderWidth() == i, id + i + 3); + } + + addPopupItem(popup, i18n("Allow Rotation"), allowRotation(), id + 10); + addPopupItem(popup, i18n("Shading"), isShadingEnabled(), id + 11); + + if (_attr.size() == 0) { + return; + } + + popup->addSeparator(); + id += 20; + for (int f = 0; f < _attr.size(); f++, id += 10) { + QMenu *tpopup = new QMenu(_attr[f].type); + popup->addMenu(tpopup); + addPopupItem(tpopup, i18n("Visible"), _attr[f].visible, id + 1); + addPopupItem(tpopup, i18n("Take Space From Children"), + _attr[f].forced, + id + 2, _attr[f].visible); + tpopup->addSeparator(); + addPopupItem(tpopup, i18n("Top Left"), + _attr[f].pos == DrawParams::TopLeft, + id + 3, _attr[f].visible); + addPopupItem(tpopup, i18n("Top Center"), + _attr[f].pos == DrawParams::TopCenter, + id + 4, _attr[f].visible); + addPopupItem(tpopup, i18n("Top Right"), + _attr[f].pos == DrawParams::TopRight, + id + 5, _attr[f].visible); + addPopupItem(tpopup, i18n("Bottom Left"), + _attr[f].pos == DrawParams::BottomLeft, + id + 6, _attr[f].visible); + addPopupItem(tpopup, i18n("Bottom Center"), + _attr[f].pos == DrawParams::BottomCenter, + id + 7, _attr[f].visible); + addPopupItem(tpopup, i18n("Bottom Right"), + _attr[f].pos == DrawParams::BottomRight, + id + 8, _attr[f].visible); + } +} + +void TreeMapWidget::selectionActivated(QAction *a) +{ + int id = a->data().toInt(); + TreeMapItem *i = _menuItem; + id -= _selectionID; + while (id > 0 && i) { + i = i->parent(); + id--; + } + if (i) { + setSelected(i, true); + } +} + +void TreeMapWidget::addSelectionItems(QMenu *popup, + int id, TreeMapItem *i) +{ + if (!i) { + return; + } + + _selectionID = id; + _menuItem = i; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(selectionActivated(QAction*))); + + while (i) { + QString name = i->text(0); + if (name.isEmpty()) { + break; + } + addPopupItem(popup, i->text(0), false, id++); + i = i->parent(); + } +} + +void TreeMapWidget::fieldStopActivated(QAction *a) +{ + int id = a->data().toInt(); + if (id == _fieldStopID) { + setFieldStop(0, QString()); + } else { + TreeMapItem *i = _menuItem; + id -= _fieldStopID + 1; + while (id > 0 && i) { + i = i->parent(); + id--; + } + if (i) { + setFieldStop(0, i->text(0)); + } + } +} + +void TreeMapWidget::addFieldStopItems(QMenu *popup, + int id, TreeMapItem *i) +{ + _fieldStopID = id; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(fieldStopActivated(QAction*))); + + addPopupItem(popup, i18n("No %1 Limit", fieldType(0)), fieldStop(0).isEmpty(), id); + + _menuItem = i; + bool foundFieldStop = false; + if (i) { + popup->addSeparator(); + + while (i) { + id++; + QString name = i->text(0); + if (name.isEmpty()) { + break; + } + bool bChecked = fieldStop(0) == i->text(0); + addPopupItem(popup, i->text(0), bChecked, id); + if (bChecked) { + foundFieldStop = true; + } + i = i->parent(); + } + } + + if (!foundFieldStop && !fieldStop(0).isEmpty()) { + popup->addSeparator(); + addPopupItem(popup, fieldStop(0), true, id + 1); + } +} + +void TreeMapWidget::areaStopActivated(QAction *a) +{ + const int id = a->data().toInt(); + if (id == _areaStopID) { + setMinimalArea(-1); + } else if (id == _areaStopID + 1) { + int area = _menuItem ? (_menuItem->width() * _menuItem->height()) : -1; + setMinimalArea(area); + } else if (id == _areaStopID + 2) { + setMinimalArea(100); + } else if (id == _areaStopID + 3) { + setMinimalArea(400); + } else if (id == _areaStopID + 4) { + setMinimalArea(1000); + } else if (id == _areaStopID + 5) { + setMinimalArea(minimalArea() * 2); + } else if (id == _areaStopID + 6) { + setMinimalArea(minimalArea() / 2); + } +} + +void TreeMapWidget::addAreaStopItems(QMenu *popup, + int id, TreeMapItem *i) +{ + _areaStopID = id; + _menuItem = i; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(areaStopActivated(QAction*))); + + bool foundArea = false; + + addPopupItem(popup, i18n("No Area Limit"), minimalArea() == -1, id); + + if (i) { + int area = i->width() * i->height(); + popup->addSeparator(); + addPopupItem(popup, + i18n("Area of '%1' (%2)", i->text(0), area), + area == minimalArea(), + id + 1); + if (area == minimalArea()) { + foundArea = true; + } + } + + popup->addSeparator(); + int area = 100, count; + for (count = 0; count < 3; count++) { + addPopupItem(popup, + i18np("1 Pixel", "%1 Pixels", area), + area == minimalArea(), + id + 2 + count); + if (area == minimalArea()) { + foundArea = true; + } + area = (area == 100) ? 400 : (area == 400) ? 1000 : 4000; + } + + if (minimalArea() > 0) { + popup->addSeparator(); + if (!foundArea) { + addPopupItem(popup, + i18np("1 Pixel", "%1 Pixels", minimalArea()), + true, + id + 10); + } + addPopupItem(popup, i18n("Double Area Limit (to %1)", minimalArea() * 2), + false, id + 5); + addPopupItem(popup, i18n("Halve Area Limit (to %1)", minimalArea() / 2), + false, id + 6); + } +} + +void TreeMapWidget::depthStopActivated(QAction *a) +{ + const int id = a->data().toInt(); + if (id == _depthStopID) { + setMaxDrawingDepth(-1); + } else if (id == _depthStopID + 1) { + int d = _menuItem ? _menuItem->depth() : -1; + setMaxDrawingDepth(d); + } else if (id == _depthStopID + 2) { + setMaxDrawingDepth(maxDrawingDepth() - 1); + } else if (id == _depthStopID + 3) { + setMaxDrawingDepth(maxDrawingDepth() + 1); + } else if (id == _depthStopID + 4) { + setMaxDrawingDepth(2); + } else if (id == _depthStopID + 5) { + setMaxDrawingDepth(4); + } else if (id == _depthStopID + 6) { + setMaxDrawingDepth(6); + } +} + +void TreeMapWidget::addDepthStopItems(QMenu *popup, + int id, TreeMapItem *i) +{ + _depthStopID = id; + _menuItem = i; + + connect(popup, SIGNAL(triggered(QAction*)), + this, SLOT(depthStopActivated(QAction*))); + + bool foundDepth = false; + + addPopupItem(popup, i18n("No Depth Limit"), maxDrawingDepth() == -1, id); + + if (i) { + int d = i->depth(); + popup->addSeparator(); + addPopupItem(popup, + i18n("Depth of '%1' (%2)", i->text(0), d), + d == maxDrawingDepth(), + id + 1); + if (d == maxDrawingDepth()) { + foundDepth = true; + } + } + + popup->addSeparator(); + int depth = 2, count; + for (count = 0; count < 3; count++) { + addPopupItem(popup, + i18n("Depth %1", depth), + depth == maxDrawingDepth(), + id + 4 + count); + if (depth == maxDrawingDepth()) { + foundDepth = true; + } + depth = (depth == 2) ? 4 : 6; + } + + if (maxDrawingDepth() > 1) { + popup->addSeparator(); + if (!foundDepth) { + addPopupItem(popup, + i18n("Depth %1", maxDrawingDepth()), + true, + id + 10); + } + addPopupItem(popup, i18n("Decrement (to %1)", maxDrawingDepth() - 1), + false, id + 2); + addPopupItem(popup, i18n("Increment (to %1)", maxDrawingDepth() + 1), + false, id + 3); + } +} + +/*---------------------------------------------------------------- + * Option saving/restoring + */ + +void TreeMapWidget::saveOptions(KConfigGroup *config, const QString &prefix) +{ + config->writeEntry(prefix + "Nesting", splitModeString()); + config->writeEntry(prefix + "AllowRotation", allowRotation()); + config->writeEntry(prefix + "ShadingEnabled", isShadingEnabled()); + config->writeEntry(prefix + "OnlyCorrectBorder", skipIncorrectBorder()); + config->writeEntry(prefix + "BorderWidth", borderWidth()); + config->writeEntry(prefix + "MaxDepth", maxDrawingDepth()); + config->writeEntry(prefix + "MinimalArea", minimalArea()); + + int f, fCount = _attr.size(); + config->writeEntry(prefix + "FieldCount", fCount); + for (f = 0; f < fCount; f++) { + config->writeEntry(QString(prefix + "FieldVisible%1").arg(f), + _attr[f].visible); + config->writeEntry(QString(prefix + "FieldForced%1").arg(f), + _attr[f].forced); + config->writeEntry(QString(prefix + "FieldStop%1").arg(f), + _attr[f].stop); + config->writeEntry(QString(prefix + "FieldPosition%1").arg(f), + fieldPositionString(f)); + } +} + +void TreeMapWidget::restoreOptions(KConfigGroup *config, const QString &prefix) +{ + bool enabled; + int num; + QString str; + + str = config->readEntry(prefix + "Nesting", QString()); + if (!str.isEmpty()) { + setSplitMode(str); + } + + if (config->hasKey(prefix + "AllowRotation")) { + enabled = config->readEntry(prefix + "AllowRotation", true); + setAllowRotation(enabled); + } + + if (config->hasKey(prefix + "ShadingEnabled")) { + enabled = config->readEntry(prefix + "ShadingEnabled", true); + setShadingEnabled(enabled); + } + + if (config->hasKey(prefix + "OnlyCorrectBorder")) { + enabled = config->readEntry(prefix + "OnlyCorrectBorder", false); + setSkipIncorrectBorder(enabled); + } + + num = config->readEntry(prefix + "BorderWidth", -2); + if (num != -2) { + setBorderWidth(num); + } + + num = config->readEntry(prefix + "MaxDepth", -2); + if (num != -2) { + setMaxDrawingDepth(num); + } + + num = config->readEntry(prefix + "MinimalArea", -2); + if (num != -2) { + setMinimalArea(num); + } + + num = config->readEntry(prefix + "FieldCount", -2); + if (num <= 0 || num > MAX_FIELD) { + return; + } + + int f; + for (f = 0; f < num; f++) { + str = QString(prefix + "FieldVisible%1").arg(f); + if (config->hasKey(str)) { + setFieldVisible(f, config->readEntry(str, false)); + } + + str = QString(prefix + "FieldForced%1").arg(f); + if (config->hasKey(str)) { + setFieldForced(f, config->readEntry(str, false)); + } + + str = config->readEntry(QString(prefix + "FieldStop%1").arg(f), QString()); + setFieldStop(f, str); + + str = config->readEntry(QString(prefix + "FieldPosition%1").arg(f), QString()); + if (!str.isEmpty()) { + setFieldPosition(f, str); + } + } +} + +void TreeMapWidget::addPopupItem(QMenu *popup, const QString &text, + bool bChecked, int id, bool bEnabled) +{ + QAction *a; + a = popup->addAction(text); + a->setCheckable(true); + a->setChecked(bChecked); + a->setData(id); + a->setEnabled(bEnabled); +} + diff --git a/plugins/fsview/treemap.h b/plugins/fsview/treemap.h new file mode 100644 index 0000000..d283392 --- /dev/null +++ b/plugins/fsview/treemap.h @@ -0,0 +1,900 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002-2009 Josef Weidendorfer + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + * + * This file defines the following classes: + * DrawParams, RectDrawing, TreeMapItem, TreeMapWidget + * + * DrawParams/RectDrawing allows reusing of TreeMap drawing + * functions in other widgets. + */ + +#ifndef TREEMAP_H +#define TREEMAP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class TreeMapWidget; +class TreeMapItem; +class TreeMapItemList; + +/** + * Drawing parameters for an object. + * A Helper Interface for RectDrawing. + */ +class DrawParams +{ +public: + /** + * Positions for drawing into a rectangle. + * + * The specified position assumes no rotation. + * If there is more than one text for one position, it is put + * nearer to the center of the item. + * + * Drawing at top positions cuts free space from top, + * drawing at bottom positions cuts from bottom. + * Default usually gives positions clockwise according to field number. + */ + enum Position { TopLeft, TopCenter, TopRight, + BottomLeft, BottomCenter, BottomRight, + Default, Unknown + }; + + // no constructor as this is an abstract class + virtual ~DrawParams() {} + + virtual QString text(int) const = 0; + virtual QPixmap pixmap(int) const = 0; + virtual Position position(int) const = 0; + // 0: no limit, negative: leave at least -maxLines() free + virtual int maxLines(int) const + { + return 0; + } + virtual int fieldCount() const + { + return 0; + } + + virtual QColor backColor() const + { + return Qt::white; + } + virtual const QFont &font() const = 0; + + virtual bool selected() const + { + return false; + } + virtual bool current() const + { + return false; + } + virtual bool shaded() const + { + return true; + } + virtual bool rotated() const + { + return false; + } + virtual bool drawFrame() const + { + return true; + } +}; + +/* + * DrawParam with attributes stored + */ +class StoredDrawParams: public DrawParams +{ +public: + StoredDrawParams(); + explicit StoredDrawParams(const QColor &c, + bool selected = false, bool current = false); + + // getters + QString text(int) const override; + QPixmap pixmap(int) const override; + Position position(int) const override; + int maxLines(int) const override; + int fieldCount() const override + { + return _field.size(); + } + + QColor backColor() const override + { + return _backColor; + } + bool selected() const override + { + return _selected; + } + bool current() const override + { + return _current; + } + bool shaded() const override + { + return _shaded; + } + bool rotated() const override + { + return _rotated; + } + bool drawFrame() const override + { + return _drawFrame; + } + + const QFont &font() const override; + + // attribute setters + void setField(int f, const QString &t, const QPixmap &pm = QPixmap(), + Position p = Default, int maxLines = 0); + void setText(int f, const QString &); + void setPixmap(int f, const QPixmap &); + void setPosition(int f, Position); + void setMaxLines(int f, int); + void setBackColor(const QColor &c) + { + _backColor = c; + } + void setSelected(bool b) + { + _selected = b; + } + void setCurrent(bool b) + { + _current = b; + } + void setShaded(bool b) + { + _shaded = b; + } + void setRotated(bool b) + { + _rotated = b; + } + void drawFrame(bool b) + { + _drawFrame = b; + } + +protected: + QColor _backColor; + bool _selected : 1; + bool _current : 1; + bool _shaded : 1; + bool _rotated : 1; + bool _drawFrame : 1; + +private: + // resize field array if needed to allow to access field + void ensureField(int f); + + struct Field { + QString text; + QPixmap pix; + Position pos; + int maxLines; + }; + + QVector _field; +}; + +/* State for drawing on a rectangle. + * + * Following drawing functions are provided: + * - background drawing with shading and 3D frame + * - successive pixmap/text drawing at various positions with wrap-around + * optimized for minimal space usage (e.g. if a text is drawn at top right + * after text on top left, the same line is used if space allows) + * + */ +class RectDrawing +{ +public: + RectDrawing(const QRect &); + ~RectDrawing(); + + // The default DrawParams object used. + DrawParams *drawParams(); + // we take control over the given object (i.e. delete at destruction) + void setDrawParams(DrawParams *); + + // draw on a given QPainter, use this class as info provider per default + void drawBack(QPainter *, DrawParams *dp = nullptr); + /* Draw field at position() from pixmap()/text() with maxLines(). + * Returns true if something was drawn + */ + bool drawField(QPainter *, int f, DrawParams *dp = nullptr); + + // resets rectangle for free space + void setRect(const QRect &); + + // Returns the rectangle area still free of text/pixmaps after + // a number of drawText() calls. + QRect remainingRect(DrawParams *dp = nullptr); + +private: + int _usedTopLeft, _usedTopCenter, _usedTopRight; + int _usedBottomLeft, _usedBottomCenter, _usedBottomRight; + QRect _rect; + + // temporary + int _fontHeight; + QFontMetrics *_fm; + DrawParams *_dp; +}; + +class TreeMapItemList: public QList +{ +public: + TreeMapItem *commonParent(); +}; + +/** + * Base class of items in TreeMap. + * + * This class supports an arbitrary number of text() strings + * positioned counterclock-wise starting at TopLeft. Each item + * has its own static value(), sum() and sorting(). The + * splitMode() and borderWidth() is taken from a TreeMapWidget. + * + * If you want more flexibility, reimplement TreeMapItem and + * override the corresponding methods. For dynamic creation of child + * items on demand, reimplement children(). + */ +class TreeMapItem: public StoredDrawParams +{ +public: + + /** + * Split direction for nested areas: + * AlwaysBest: Choose split direction for every subitem according to + * longest side of rectangle left for drawing + * Best: Choose split direction for all subitems of an area + * depending on longest side + * HAlternate: Horizontal at top; alternate direction on depth step + * VAlternate: Vertical at top; alternate direction on depth step + * Horizontal: Always horizontal split direction + * Vertical: Always vertical split direction + */ + enum SplitMode { Bisection, Columns, Rows, + AlwaysBest, Best, + HAlternate, VAlternate, + Horizontal, Vertical + }; + + explicit TreeMapItem(TreeMapItem *parent = nullptr, double value = 1.0); + TreeMapItem(TreeMapItem *parent, double value, + const QString &text1, const QString &text2 = QString(), + const QString &text3 = QString(), const QString &text4 = QString()); + ~TreeMapItem() override; + + bool isChildOf(TreeMapItem *); + + TreeMapItem *commonParent(TreeMapItem *item); + + // force a redraw of this item + void redraw(); + + // delete all children + void clear(); + + // force new child generation & refresh + void refresh(); + + // call in a reimplemented items() method to check if already called + // after a clear(), this will return false + bool initialized(); + + /** + * Adds an item to a parent. + * When no sorting is used, the item is appended (drawn at bottom). + * This is only needed if the parent was not already specified in the + * construction of the item. + */ + void addItem(TreeMapItem *); + + /** + * Returns a list of text strings of specified text number, + * from root up to this item. + */ + QStringList path(int) const; + + /** + * Depth of this item. This is the distance to root. + */ + int depth() const; + + /** + * Parent Item + */ + TreeMapItem *parent() const + { + return _parent; + } + + /** + * Temporary rectangle used for drawing this item the last time. + * This is internally used to map from a point to an item. + */ + void setItemRect(const QRect &r) + { + _rect = r; + } + void clearItemRect(); + const QRect &itemRect() const + { + return _rect; + } + int width() const + { + return _rect.width(); + } + int height() const + { + return _rect.height(); + } + + /** + * Temporary rectangle list of free space of this item. + * Used internally to enable tooltip. + */ + void clearFreeRects(); + const QList &freeRects() const + { + return _freeRects; + } + void addFreeRect(const QRect &r); + + /** + * Temporary child item index of the child that was current() recently. + */ + int index() const + { + return _index; + } + void setIndex(int i) + { + _index = i; + } + + /** + * TreeMap widget this item is put in. + */ + TreeMapWidget *widget() const + { + return _widget; + } + + void setParent(TreeMapItem *p); + void setWidget(TreeMapWidget *w) + { + _widget = w; + } + void setSum(double s) + { + _sum = s; + } + void setValue(double s) + { + _value = s; + } + + virtual double sum() const; + virtual double value() const; + // replace "Default" position with setting from TreeMapWidget + Position position(int) const override; + const QFont &font() const override; + virtual bool isMarked(int) const; + + virtual int borderWidth() const; + + /** + * Returns the text number after that sorting is done or + * -1 for no sorting, -2 for value() sorting (default). + * If ascending != 0, a bool value is written at that location + * to indicate if sorting should be ascending. + */ + virtual int sorting(bool *ascending) const; + + /** + * Set the sorting for child drawing. + * + * Default is no sorting: = -1 + * For value() sorting, use = -2 + * + * For fast sorting, set this to -1 before child insertions and call + * again after inserting all children. + */ + void setSorting(int textNo, bool ascending = true); + + /** + * Resort according to the already set sorting. + * + * This has to be done if the sorting base changes (e.g. text or values + * change). If this is only true for the children of this item, you can + * set the recursive parameter to false. + */ + void resort(bool recursive = true); + + virtual SplitMode splitMode() const; + virtual int rtti() const; + // not const as this can create children on demand + virtual TreeMapItemList *children(); + +protected: + TreeMapItemList *_children; + double _sum, _value; + +private: + TreeMapWidget *_widget; + TreeMapItem *_parent; + + int _sortTextNo; + bool _sortAscending; + + // temporary layout + QRect _rect; + QList _freeRects; + int _depth; + + // temporary self value (when using level skipping) + double _unused_self; + + // index of last active subitem + int _index; +}; + +/** + * Class for visualization of a metric of hierarchically + * nested items as 2D areas. + */ +class TreeMapWidget: public QWidget +{ + Q_OBJECT + +public: + + /** + * Same as in QListBox/QListView + */ + enum SelectionMode { Single, Multi, Extended, NoSelection }; + + /* The widget gets owner of the base item */ + explicit TreeMapWidget(TreeMapItem *base, QWidget *parent = nullptr); + ~TreeMapWidget() override; + + /** + * Returns the TreeMapItem filling out the widget space + */ + TreeMapItem *base() const + { + return _base; + } + + /** + * Returns a reference to the current widget font. + */ + const QFont ¤tFont() const; + + /** + * Returns the area item at position x/y, independent from any + * maxSelectDepth setting. + */ + TreeMapItem *item(int x, int y) const; + + /** + * Returns the nearest item with a visible area; this + * can be the given item itself. + */ + TreeMapItem *visibleItem(TreeMapItem *) const; + + /** + * Returns the item possible for selection. this returns the + * given item itself or a parent thereof, + * depending on setting of maxSelectDepth(). + */ + TreeMapItem *possibleSelection(TreeMapItem *) const; + + /** + * Selects or unselects an item. + * In multiselection mode, the constrain that a selected item + * has no selected children or parents stays true. + */ + void setSelected(TreeMapItem *, bool selected = true); + + /** + * Switches on the marking . Marking 0 switches off marking. + * This is mutually exclusive to selection, and is automatically + * switched off when selection is changed (also by the user). + * Marking is visually the same as selection, and is based on + * TreeMapItem::isMarked(). + * This enables to programmatically show multiple selected items + * at once even in single selection mode. + */ + void setMarked(int markNo = 1, bool redraw = true); + + /** + * Clear selection of all selected items which are children of + * parent. When parent == 0, clears whole selection + * Returns true if selection changed. + */ + bool clearSelection(TreeMapItem *parent = nullptr); + + /** + * Selects or unselects items in a range. + * This is needed internally for Shift-Click in Extended mode. + * Range means for a hierarchical widget: + * - select/unselect i1 and i2 according selected + * - search common parent of i1 and i2, and select/unselect the + * range of direct children between but excluding the child + * leading to i1 and the child leading to i2. + */ + void setRangeSelection(TreeMapItem *i1, + TreeMapItem *i2, bool selected); + + /** + * Sets the current item. + * The current item is mainly used for keyboard navigation. + */ + void setCurrent(TreeMapItem *, bool kbd = false); + + /** + * Set the maximal depth a selected item can have. + * If you try to select a item with higher depth, the ancestor holding + * this condition is used. + * + * See also possibleSelection(). + */ + void setMaxSelectDepth(int d) + { + _maxSelectDepth = d; + } + + void setSelectionMode(SelectionMode m) + { + _selectionMode = m; + } + + /** + * for setting/getting global split direction + */ + void setSplitMode(TreeMapItem::SplitMode m); + TreeMapItem::SplitMode splitMode() const; + // returns true if string was recognized + bool setSplitMode(const QString &); + QString splitModeString() const; + + /* + * Shading of rectangles enabled ? + */ + void setShadingEnabled(bool s); + bool isShadingEnabled() const + { + return _shading; + } + + /* Setting for a whole depth level: draw 3D frame (default) or solid */ + void drawFrame(int d, bool b); + bool drawFrame(int d) const + { + return (d < 4) ? _drawFrame[d] : true; + } + + /* Setting for a whole depth level: draw items (default) or transparent */ + void setTransparent(int d, bool b); + bool isTransparent(int d) const + { + return (d < 4) ? _transparent[d] : false; + } + + /** + * Items usually have a size proportional to their value(). + * With , you can give the minimum width + * of the resulting rectangle to still be drawn. + * For space not used because of to small items, you can specify + * with if the background should shine through or + * the space will be used to enlarge the next item to be drawn + * at this level. + */ + void setVisibleWidth(int width, bool reuseSpace = false); + + /** + * If a children value() is almost the parents sum(), + * it can happen that the border to be drawn for visibilty of + * nesting relations takes to much space, and the + * parent/child size relation can not be mapped to a correct + * area size relation. + * + * Either + * (1) Ignore the incorrect drawing, or + * (2) Skip drawing of the parent level alltogether. + */ + void setSkipIncorrectBorder(bool enable = true); + bool skipIncorrectBorder() const + { + return _skipIncorrectBorder; + } + + /** + * Maximal nesting depth + */ + void setMaxDrawingDepth(int d); + int maxDrawingDepth() const + { + return _maxDrawingDepth; + } + + /** + * Minimal area for rectangles to draw + */ + void setMinimalArea(int area); + int minimalArea() const + { + return _minimalArea; + } + + /* defaults for text attributes */ + QString defaultFieldType(int) const; + QString defaultFieldStop(int) const; + bool defaultFieldVisible(int) const; + bool defaultFieldForced(int) const; + DrawParams::Position defaultFieldPosition(int) const; + + /** + * Set the type name of a field. + * This is important for the visualization menu generated + * with visualizationMenu() + */ + void setFieldType(int, const QString &); + QString fieldType(int) const; + + /** + * Stop drawing at item with name + */ + void setFieldStop(int, const QString &); + QString fieldStop(int) const; + + /** + * Should the text with number textNo be visible? + * This is only done if remaining space is enough to allow for + * proportional size constrains. + */ + void setFieldVisible(int, bool); + bool fieldVisible(int) const; + + /** + * Should the drawing of the name into the rectangle be forced? + * This enables drawing of the name before drawing subitems, and + * thus destroys proportional constrains. + */ + void setFieldForced(int, bool); + bool fieldForced(int) const; + + /** + * Set the field position in the area. See TreeMapItem::Position + */ + void setFieldPosition(int, DrawParams::Position); + DrawParams::Position fieldPosition(int) const; + void setFieldPosition(int, const QString &); + QString fieldPositionString(int) const; + + /** + * Do we allow the texts to be rotated by 90 degrees for better fitting? + */ + void setAllowRotation(bool); + bool allowRotation() const + { + return _allowRotation; + } + + void setBorderWidth(int w); + int borderWidth() const + { + return _borderWidth; + } + + /** + * Save/restore options. + */ + void saveOptions(KConfigGroup *, const QString &prefix = QString()); + void restoreOptions(KConfigGroup *, const QString &prefix = QString()); + + /** + * These functions populate given popup menus. + * The added items are already connected to handlers. + * + * The int is the menu id where to start for the items (100 IDs reserved). + */ + void addSplitDirectionItems(QMenu *, int); + void addSelectionItems(QMenu *, int, TreeMapItem *); + void addFieldStopItems(QMenu *, int, TreeMapItem *); + void addAreaStopItems(QMenu *, int, TreeMapItem *); + void addDepthStopItems(QMenu *, int, TreeMapItem *); + void addVisualizationItems(QMenu *, int); + + TreeMapWidget *widget() + { + return this; + } + TreeMapItem *current() const + { + return _current; + } + TreeMapItemList selection() const + { + return _selection; + } + bool isSelected(TreeMapItem *i) const; + int maxSelectDepth() const + { + return _maxSelectDepth; + } + SelectionMode selectionMode() const + { + return _selectionMode; + } + + /** + * Return tooltip string to show for a item (can be rich text) + * Default implementation gives lines with "text0 (text1)" going to root. + */ + virtual QString tipString(TreeMapItem *i) const; + + /** + * Redraws an item with all children. + * This takes changed values(), sums(), colors() and text() into account. + */ + void redraw(TreeMapItem *); + void redraw() + { + redraw(_base); + } + + /** + * Resort all TreeMapItems. See TreeMapItem::resort(). + */ + void resort() + { + _base->resort(true); + } + + // internal + void drawTreeMap(); + + // used internally when items are destroyed + void deletingItem(TreeMapItem *); + +protected slots: + void splitActivated(QAction *); + void selectionActivated(QAction *); + void fieldStopActivated(QAction *); + void areaStopActivated(QAction *); + void depthStopActivated(QAction *); + void visualizationActivated(QAction *a); + +signals: + void selectionChanged(); + void selectionChanged(TreeMapItem *); + + /** + * This signal is emitted if the current item changes. + * If the change is done because of keyboard navigation, + * the is set to true + */ + void currentChanged(TreeMapItem *, bool keyboard); + void clicked(TreeMapItem *); + void returnPressed(TreeMapItem *); + void doubleClicked(TreeMapItem *); + void rightButtonPressed(TreeMapItem *, const QPoint &); + void contextMenuRequested(TreeMapItem *, const QPoint &); + +protected: + void mousePressEvent(QMouseEvent *) override; + void contextMenuEvent(QContextMenuEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseMoveEvent(QMouseEvent *) override; + void mouseDoubleClickEvent(QMouseEvent *) override; + void keyPressEvent(QKeyEvent *) override; + void paintEvent(QPaintEvent *) override; + void fontChange(const QFont &); + bool event(QEvent *event) override; + // For "Esc deselects all" functionality implemented in FSView. + TreeMapItem *_pressed; + // add a checkable popup item + void addPopupItem(QMenu *popup, const QString &text, + bool bChecked, int id, bool bEnabled = true); +private: + TreeMapItemList diff(TreeMapItemList &, TreeMapItemList &); + // returns true if selection changed + TreeMapItem *setTmpSelected(TreeMapItem *, bool selected = true); + TreeMapItem *setTmpRangeSelection(TreeMapItem *i1, + TreeMapItem *i2, bool selected); + bool isTmpSelected(TreeMapItem *i); + + void drawItem(QPainter *p, TreeMapItem *); + void drawItems(QPainter *p, TreeMapItem *); + bool horizontal(TreeMapItem *i, const QRect &r); + void drawFill(TreeMapItem *, QPainter *p, const QRect &r); + void drawFill(TreeMapItem *, QPainter *p, const QRect &r, + TreeMapItemList *list, int idx, int len, bool goBack); + bool drawItemArray(QPainter *p, TreeMapItem *, const QRect &r, double, + TreeMapItemList *list, int idx, int len, bool); + bool resizeAttr(int); + + TreeMapItem *_base; + TreeMapItem *_current, *_lastOver, *_oldCurrent; + int _maxSelectDepth, _maxDrawingDepth; + + // attributes for field, per textNo + struct FieldAttr { + QString type, stop; + bool visible, forced; + DrawParams::Position pos; + }; + QVector _attr; + + SelectionMode _selectionMode; + TreeMapItem::SplitMode _splitMode; + int _visibleWidth, _stopArea, _minimalArea, _borderWidth; + bool _reuseSpace, _skipIncorrectBorder, _drawSeparators, _shading; + bool _allowRotation; + bool _transparent[4], _drawFrame[4]; + TreeMapItem *_needsRefresh; + TreeMapItemList _selection; + int _markNo; + + // for the context menus: start IDs + int _splitID, _selectionID, _visID; + int _fieldStopID, _areaStopID, _depthStopID; + TreeMapItem *_menuItem; + + // temporary selection while dragging, used for drawing + // most of the time, _selection == _tmpSelection + TreeMapItemList _tmpSelection; + bool _inShiftDrag, _inControlDrag; + + // temporary widget font metrics while drawing + QFont _font; + int _fontHeight; + + // back buffer pixmap + QPixmap _pixmap; +}; + +#endif diff --git a/plugins/imagerotation/CMakeLists.txt b/plugins/imagerotation/CMakeLists.txt new file mode 100644 index 0000000..daa34c7 --- /dev/null +++ b/plugins/imagerotation/CMakeLists.txt @@ -0,0 +1,9 @@ + +#if(NOT WIN32) +# install( FILES jpegorient.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/ServiceMenus ) +# install( PROGRAMS exif.py jpegorient orient.py DESTINATION ${KDE_INSTALL_BINDIR} ) +#endif(NOT WIN32) + +install( FILES imageconverter.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/ServiceMenus ) + + diff --git a/plugins/imagerotation/exif.py b/plugins/imagerotation/exif.py new file mode 100755 index 0000000..309df47 --- /dev/null +++ b/plugins/imagerotation/exif.py @@ -0,0 +1,1079 @@ +#! /usr/bin/env python +# Library to extract EXIF information in digital camera image files +# +# Contains code from "exifdump.py" originally written by Thierry Bousch +# and released into the public domain. +# +# Updated and turned into general-purpose library by Gene Cash +# +# +# NOTE: This version has been modified by Leif Jensen +# +# This copyright license is intended to be similar to the FreeBSD license. +# +# Copyright 2002 Gene Cash All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY GENE CASH ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This means you may do anything you want with this code, except claim you +# wrote it. Also, if it breaks you get to keep both pieces. +# +# 21-AUG-99 TB Last update by Thierry Bousch to his code. +# 17-JAN-02 CEC Discovered code on web. +# Commented everything. +# Made small code improvements. +# Reformatted for readability. +# 19-JAN-02 CEC Added ability to read TIFFs and JFIF-format JPEGs. +# Added ability to extract JPEG formatted thumbnail. +# Added ability to read GPS IFD (not tested). +# Converted IFD data structure to dictionaries indexed by +# tag name. +# Factored into library returning dictionary of IFDs plus +# thumbnail, if any. +# 20-JAN-02 CEC Added MakerNote processing logic. +# Added Olympus MakerNote. +# Converted data structure to single-level dictionary, avoiding +# tag name collisions by prefixing with IFD name. This makes +# it much easier to use. +# 23-JAN-02 CEC Trimmed nulls from end of string values. +# 25-JAN-02 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote. +# 26-JAN-02 CEC Added ability to extract TIFF thumbnails. +# Added Nikon, Fujifilm, Casio MakerNotes. +# +# To do: +# * Finish Canon MakerNote format +# * Better printing of ratios + +# field type descriptions as (length, abbreviation, full name) tuples +FIELD_TYPES=( + (0, 'X', 'Dummy'), # no such type + (1, 'B', 'Byte'), + (1, 'A', 'ASCII'), + (2, 'S', 'Short'), + (4, 'L', 'Long'), + (8, 'R', 'Ratio'), + (1, 'SB', 'Signed Byte'), + (1, 'U', 'Undefined'), + (2, 'SS', 'Signed Short'), + (4, 'SL', 'Signed Long'), + (8, 'SR', 'Signed Ratio') + ) + +# dictionary of main EXIF tag names +# first element of tuple is tag name, optional second element is +# another dictionary giving names to values +EXIF_TAGS={ + 0x0100: ('ImageWidth', ), + 0x0101: ('ImageLength', ), + 0x0102: ('BitsPerSample', ), + 0x0103: ('Compression', + {1: 'Uncompressed TIFF', + 6: 'JPEG Compressed'}), + 0x0106: ('PhotometricInterpretation', ), + 0x010A: ('FillOrder', ), + 0x010D: ('DocumentName', ), + 0x010E: ('ImageDescription', ), + 0x010F: ('Make', ), + 0x0110: ('Model', ), + 0x0111: ('StripOffsets', ), + 0x0112: ('Orientation', ), + 0x0115: ('SamplesPerPixel', ), + 0x0116: ('RowsPerStrip', ), + 0x0117: ('StripByteCounts', ), + 0x011A: ('XResolution', ), + 0x011B: ('YResolution', ), + 0x011C: ('PlanarConfiguration', ), + 0x0128: ('ResolutionUnit', + {1: 'Not Absolute', + 2: 'Pixels/Inch', + 3: 'Pixels/Centimeter'}), + 0x012D: ('TransferFunction', ), + 0x0131: ('Software', ), + 0x0132: ('DateTime', ), + 0x013B: ('Artist', ), + 0x013E: ('WhitePoint', ), + 0x013F: ('PrimaryChromaticities', ), + 0x0156: ('TransferRange', ), + 0x0200: ('JPEGProc', ), + 0x0201: ('JPEGInterchangeFormat', ), + 0x0202: ('JPEGInterchangeFormatLength', ), + 0x0211: ('YCbCrCoefficients', ), + 0x0212: ('YCbCrSubSampling', ), + 0x0213: ('YCbCrPositioning', ), + 0x0214: ('ReferenceBlackWhite', ), + 0x828D: ('CFARepeatPatternDim', ), + 0x828E: ('CFAPattern', ), + 0x828F: ('BatteryLevel', ), + 0x8298: ('Copyright', ), + 0x829A: ('ExposureTime', ), + 0x829D: ('FNumber', ), + 0x83BB: ('IPTC/NAA', ), + 0x8769: ('ExifOffset', ), + 0x8773: ('InterColorProfile', ), + 0x8822: ('ExposureProgram', + {0: 'Unidentified', + 1: 'Manual', + 2: 'Program Normal', + 3: 'Aperture Priority', + 4: 'Shutter Priority', + 5: 'Program Creative', + 6: 'Program Action', + 7: 'Portrait Mode', + 8: 'Landscape Mode'}), + 0x8824: ('SpectralSensitivity', ), + 0x8825: ('GPSInfo', ), + 0x8827: ('ISOSpeedRatings', ), + 0x8828: ('OECF', ), + 0x9000: ('ExifVersion', ), + 0x9003: ('DateTimeOriginal', ), + 0x9004: ('DateTimeDigitized', ), + 0x9101: ('ComponentsConfiguration', + {0: '', + 1: 'Y', + 2: 'Cb', + 3: 'Cr', + 4: 'Red', + 5: 'Green', + 6: 'Blue'}), + 0x9102: ('CompressedBitsPerPixel', ), + 0x9201: ('ShutterSpeedValue', ), + 0x9202: ('ApertureValue', ), + 0x9203: ('BrightnessValue', ), + 0x9204: ('ExposureBiasValue', ), + 0x9205: ('MaxApertureValue', ), + 0x9206: ('SubjectDistance', ), + 0x9207: ('MeteringMode', + {0: 'Unidentified', + 1: 'Average', + 2: 'CenterWeightedAverage', + 3: 'Spot', + 4: 'MultiSpot'}), + 0x9208: ('LightSource', + {0: 'Unknown', + 1: 'Daylight', + 2: 'Fluorescent', + 3: 'Tungsten', + 10: 'Flash', + 17: 'Standard Light A', + 18: 'Standard Light B', + 19: 'Standard Light C', + 20: 'D55', + 21: 'D65', + 22: 'D75', + 255: 'Other'}), + 0x9209: ('Flash', {0: 'No', + 1: 'Fired', + 5: 'Fired (?)', # no return sensed + 7: 'Fired (!)', # return sensed + 9: 'Fill Fired', + 13: 'Fill Fired (?)', + 15: 'Fill Fired (!)', + 16: 'Off', + 24: 'Auto Off', + 25: 'Auto Fired', + 29: 'Auto Fired (?)', + 31: 'Auto Fired (!)', + 32: 'Not Available'}), + 0x920A: ('FocalLength', ), + 0x927C: ('MakerNote', ), + 0x9286: ('UserComment', ), + 0x9290: ('SubSecTime', ), + 0x9291: ('SubSecTimeOriginal', ), + 0x9292: ('SubSecTimeDigitized', ), + 0xA000: ('FlashPixVersion', ), + 0xA001: ('ColorSpace', ), + 0xA002: ('ExifImageWidth', ), + 0xA003: ('ExifImageLength', ), + 0xA005: ('InteroperabilityOffset', ), + 0xA20B: ('FlashEnergy', ), # 0x920B in TIFF/EP + 0xA20C: ('SpatialFrequencyResponse', ), # 0x920C - - + 0xA20E: ('FocalPlaneXResolution', ), # 0x920E - - + 0xA20F: ('FocalPlaneYResolution', ), # 0x920F - - + 0xA210: ('FocalPlaneResolutionUnit', ), # 0x9210 - - + 0xA214: ('SubjectLocation', ), # 0x9214 - - + 0xA215: ('ExposureIndex', ), # 0x9215 - - + 0xA217: ('SensingMethod', ), # 0x9217 - - + 0xA300: ('FileSource', + {3: 'Digital Camera'}), + 0xA301: ('SceneType', + {1: 'Directly Photographed'}), + } + +# interoperability tags +INTR_TAGS={ + 0x0001: ('InteroperabilityIndex', ), + 0x0002: ('InteroperabilityVersion', ), + 0x1000: ('RelatedImageFileFormat', ), + 0x1001: ('RelatedImageWidth', ), + 0x1002: ('RelatedImageLength', ), + } + +# GPS tags (not used yet, haven't seen camera with GPS) +GPS_TAGS={ + 0x0000: ('GPSVersionID', ), + 0x0001: ('GPSLatitudeRef', ), + 0x0002: ('GPSLatitude', ), + 0x0003: ('GPSLongitudeRef', ), + 0x0004: ('GPSLongitude', ), + 0x0005: ('GPSAltitudeRef', ), + 0x0006: ('GPSAltitude', ), + 0x0007: ('GPSTimeStamp', ), + 0x0008: ('GPSSatellites', ), + 0x0009: ('GPSStatus', ), + 0x000A: ('GPSMeasureMode', ), + 0x000B: ('GPSDOP', ), + 0x000C: ('GPSSpeedRef', ), + 0x000D: ('GPSSpeed', ), + 0x000E: ('GPSTrackRef', ), + 0x000F: ('GPSTrack', ), + 0x0010: ('GPSImgDirectionRef', ), + 0x0011: ('GPSImgDirection', ), + 0x0012: ('GPSMapDatum', ), + 0x0013: ('GPSDestLatitudeRef', ), + 0x0014: ('GPSDestLatitude', ), + 0x0015: ('GPSDestLongitudeRef', ), + 0x0016: ('GPSDestLongitude', ), + 0x0017: ('GPSDestBearingRef', ), + 0x0018: ('GPSDestBearing', ), + 0x0019: ('GPSDestDistanceRef', ), + 0x001A: ('GPSDestDistance', ) + } + +# Nikon E99x MakerNote Tags +# http://members.tripod.com/~tawba/990exif.htm +MAKERNOTE_NIKON_NEWER_TAGS={ + 0x0002: ('ISOSetting', ), + 0x0003: ('ColorMode', ), + 0x0004: ('Quality', ), + 0x0005: ('Whitebalance', ), + 0x0006: ('ImageSharpening', ), + 0x0007: ('FocusMode', ), + 0x0008: ('FlashSetting', ), + 0x000F: ('ISOSelection', ), + 0x0080: ('ImageAdjustment', ), + 0x0082: ('AuxiliaryLens', ), + 0x0085: ('ManualFocusDistance', ), + 0x0086: ('DigitalZoomFactor', ), + 0x0088: ('AFFocusPosition', + {0x0000: 'Center', + 0x0100: 'Top', + 0x0200: 'Bottom', + 0x0300: 'Left', + 0x0400: 'Right'}), + 0x0094: ('Saturation', + {-3: 'B&W', + -2: '-2', + -1: '-1', + 0: '0', + 1: '1', + 2: '2'}), + 0x0095: ('NoiseReduction', ), + 0x0010: ('DataDump', ) + } + +MAKERNOTE_NIKON_OLDER_TAGS={ + 0x0003: ('Quality', + {1: 'VGA Basic', + 2: 'VGA Normal', + 3: 'VGA Fine', + 4: 'SXGA Basic', + 5: 'SXGA Normal', + 6: 'SXGA Fine'}), + 0x0004: ('ColorMode', + {1: 'Color', + 2: 'Monochrome'}), + 0x0005: ('ImageAdjustment', + {0: 'Normal', + 1: 'Bright+', + 2: 'Bright-', + 3: 'Contrast+', + 4: 'Contrast-'}), + 0x0006: ('CCDSpeed', + {0: 'ISO 80', + 2: 'ISO 160', + 4: 'ISO 320', + 5: 'ISO 100'}), + 0x0007: ('WhiteBalance', + {0: 'Auto', + 1: 'Preset', + 2: 'Daylight', + 3: 'Incandescent', + 4: 'Fluorescent', + 5: 'Cloudy', + 6: 'Speed Light'}) + } + +# decode Olympus SpecialMode tag in MakerNote +def olympus_special_mode(v): + a={ + 0: 'Normal', + 1: 'Unknown', + 2: 'Fast', + 3: 'Panorama'} + b={ + 0: 'Non-panoramic', + 1: 'Left to right', + 2: 'Right to left', + 3: 'Bottom to top', + 4: 'Top to bottom'} + return '%s - sequence %d - %s' % (a[v[0]], v[1], b[v[2]]) + +MAKERNOTE_OLYMPUS_TAGS={ + # ah HAH! those sneeeeeaky bastids! this is how they get past the fact + # that a JPEG thumbnail is not allowed in an uncompressed TIFF file + 0x0100: ('JPEGThumbnail', ), + 0x0200: ('SpecialMode', olympus_special_mode), + 0x0201: ('JPEGQual', + {1: 'SQ', + 2: 'HQ', + 3: 'SHQ'}), + 0x0202: ('Macro', + {0: 'Normal', + 1: 'Macro'}), + 0x0204: ('DigitalZoom', ), + 0x0207: ('SoftwareRelease', ), + 0x0208: ('PictureInfo', ), + # print as string + 0x0209: ('CameraID', lambda x: ''.join(map(chr, x))), + 0x0F00: ('DataDump', ) + } + +MAKERNOTE_CASIO_TAGS={ + 0x0001: ('RecordingMode', + {1: 'Single Shutter', + 2: 'Panorama', + 3: 'Night Scene', + 4: 'Portrait', + 5: 'Landscape'}), + 0x0002: ('Quality', + {1: 'Economy', + 2: 'Normal', + 3: 'Fine'}), + 0x0003: ('FocusingMode', + {2: 'Macro', + 3: 'Auto Focus', + 4: 'Manual Focus', + 5: 'Infinity'}), + 0x0004: ('FlashMode', + {1: 'Auto', + 2: 'On', + 3: 'Off', + 4: 'Red Eye Reduction'}), + 0x0005: ('FlashIntensity', + {11: 'Weak', + 13: 'Normal', + 15: 'Strong'}), + 0x0006: ('Object Distance', ), + 0x0007: ('WhiteBalance', + {1: 'Auto', + 2: 'Tungsten', + 3: 'Daylight', + 4: 'Fluorescent', + 5: 'Shade', + 129: 'Manual'}), + 0x000B: ('Sharpness', + {0: 'Normal', + 1: 'Soft', + 2: 'Hard'}), + 0x000C: ('Contrast', + {0: 'Normal', + 1: 'Low', + 2: 'High'}), + 0x000D: ('Saturation', + {0: 'Normal', + 1: 'Low', + 2: 'High'}), + 0x0014: ('CCDSpeed', + {64: 'Normal', + 80: 'Normal', + 100: 'High', + 125: '+1.0', + 244: '+3.0', + 250: '+2.0',}) + } + +MAKERNOTE_FUJIFILM_TAGS={ + 0x0000: ('NoteVersion', lambda x: ''.join(map(chr, x))), + 0x1000: ('Quality', ), + 0x1001: ('Sharpness', + {1: 'Soft', + 2: 'Soft', + 3: 'Normal', + 4: 'Hard', + 5: 'Hard'}), + 0x1002: ('WhiteBalance', + {0: 'Auto', + 256: 'Daylight', + 512: 'Cloudy', + 768: 'DaylightColor-Fluorescent', + 769: 'DaywhiteColor-Fluorescent', + 770: 'White-Fluorescent', + 1024: 'Incandescent', + 3840: 'Custom'}), + 0x1003: ('Color', + {0: 'Normal', + 256: 'High', + 512: 'Low'}), + 0x1004: ('Tone', + {0: 'Normal', + 256: 'High', + 512: 'Low'}), + 0x1010: ('FlashMode', + {0: 'Auto', + 1: 'On', + 2: 'Off', + 3: 'Red Eye Reduction'}), + 0x1011: ('FlashStrength', ), + 0x1020: ('Macro', + {0: 'Off', + 1: 'On'}), + 0x1021: ('FocusMode', + {0: 'Auto', + 1: 'Manual'}), + 0x1030: ('SlowSync', + {0: 'Off', + 1: 'On'}), + 0x1031: ('PictureMode', + {0: 'Auto', + 1: 'Portrait', + 2: 'Landscape', + 4: 'Sports', + 5: 'Night', + 6: 'Program AE', + 256: 'Aperture Priority AE', + 512: 'Shutter Priority AE', + 768: 'Manual Exposure'}), + 0x1100: ('MotorOrBracket', + {0: 'Off', + 1: 'On'}), + 0x1300: ('BlurWarning', + {0: 'Off', + 1: 'On'}), + 0x1301: ('FocusWarning', + {0: 'Off', + 1: 'On'}), + 0x1302: ('AEWarning', + {0: 'Off', + 1: 'On'}) + } + +MAKERNOTE_CANON_TAGS={ + 0x0006: ('ImageType', ), + 0x0007: ('FirmwareVersion', ), + 0x0008: ('ImageNumber', ), + 0x0009: ('OwnerName', ) + } + +# see http://www.burren.cx/david/canon.html by David Burren +# this is in element offset, name, optional value dictionary format +MAKERNOTE_CANON_TAG_0x001={ + 1: ('Macromode', + {1: 'Macro', + 2: 'Normal'}), + 2: ('SelfTimer', ), + 3: ('Quality', + {2: 'Normal', + 3: 'Fine', + 5: 'Superfine'}), + 4: ('FlashMode', + {0: 'Flash Not Fired', + 1: 'Auto', + 2: 'On', + 3: 'Red-Eye Reduction', + 4: 'Slow Synchro', + 5: 'Auto + Red-Eye Reduction', + 6: 'On + Red-Eye Reduction', + 16: 'external flash'}), + 5: ('ContinuousDriveMode', + {0: 'Single Or Timer', + 1: 'Continuous'}), + 7: ('FocusMode', + {0: 'One-Shot', + 1: 'AI Servo', + 2: 'AI Focus', + 3: 'MF', + 4: 'Single', + 5: 'Continuous', + 6: 'MF'}), + 10: ('ImageSize', + {0: 'Large', + 1: 'Medium', + 2: 'Small'}), + 11: ('EasyShootingMode', + {0: 'Full Auto', + 1: 'Manual', + 2: 'Landscape', + 3: 'Fast Shutter', + 4: 'Slow Shutter', + 5: 'Night', + 6: 'B&W', + 7: 'Sepia', + 8: 'Portrait', + 9: 'Sports', + 10: 'Macro/Close-Up', + 11: 'Pan Focus'}), + 12: ('DigitalZoom', + {0: 'None', + 1: '2x', + 2: '4x'}), + 13: ('Contrast', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 14: ('Saturation', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 15: ('Sharpness', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 16: ('ISO', + {0: 'See ISOSpeedRatings Tag', + 15: 'Auto', + 16: '50', + 17: '100', + 18: '200', + 19: '400'}), + 17: ('MeteringMode', + {3: 'Evaluative', + 4: 'Partial', + 5: 'Center-weighted'}), + 18: ('FocusType', + {0: 'Manual', + 1: 'Auto', + 3: 'Close-Up (Macro)', + 8: 'Locked (Pan Mode)'}), + 19: ('AFPointSelected', + {0x3000: 'None (MF)', + 0x3001: 'Auto-Selected', + 0x3002: 'Right', + 0x3003: 'Center', + 0x3004: 'Left'}), + 20: ('ExposureMode', + {0: 'Easy Shooting', + 1: 'Program', + 2: 'Tv-priority', + 3: 'Av-priority', + 4: 'Manual', + 5: 'A-DEP'}), + 23: ('LongFocalLengthOfLensInFocalUnits', ), + 24: ('ShortFocalLengthOfLensInFocalUnits', ), + 25: ('FocalUnitsPerMM', ), + 28: ('FlashActivity', + {0: 'Did Not Fire', + 1: 'Fired'}), + 29: ('FlashDetails', + {14: 'External E-TTL', + 13: 'Internal Flash', + 11: 'FP Sync Used', + 7: '2nd("Rear")-Curtain Sync Used', + 4: 'FP Sync Enabled'}), + 32: ('FocusMode', + {0: 'Single', + 1: 'Continuous'}) + } + +MAKERNOTE_CANON_TAG_0x004={ + 7: ('WhiteBalance', + {0: 'Auto', + 1: 'Sunny', + 2: 'Cloudy', + 3: 'Tungsten', + 4: 'Fluorescent', + 5: 'Flash', + 6: 'Custom'}), + 9: ('SequenceNumber', ), + 14: ('AFPointUsed', ), + 15: ('FlashBias', + {0XFFC0: '-2 EV', + 0XFFCC: '-1.67 EV', + 0XFFD0: '-1.50 EV', + 0XFFD4: '-1.33 EV', + 0XFFE0: '-1 EV', + 0XFFEC: '-0.67 EV', + 0XFFF0: '-0.50 EV', + 0XFFF4: '-0.33 EV', + 0X0000: '0 EV', + 0X000C: '0.33 EV', + 0X0010: '0.50 EV', + 0X0014: '0.67 EV', + 0X0020: '1 EV', + 0X002C: '1.33 EV', + 0X0030: '1.50 EV', + 0X0034: '1.67 EV', + 0X0040: '2 EV'}), + 19: ('SubjectDistance', ) + } + +# extract multibyte integer in Motorola format (little endian) +def s2n_motorola(str): + x=0 + for c in str: + x=(long(x) << 8) | ord(c) + return x + +# extract multibyte integer in Intel format (big endian) +def s2n_intel(str): + x=0 + y=0 + for c in str: + x=x | (ord(c) << y) + y=y+8 + return x + +# ratio object that eventually will be able to reduce itself to lowest +# common denominator for printing +def gcd(a, b): + if b == 0: + return a + else: + return gcd(b, a % b) + +class Ratio: + def __init__(self, num, den): + self.num=num + self.den=den + + def __repr__(self): +# self.reduce() # ugh, 259/250 worse 1036/1000 + if self.den == 1: + return str(self.num) + return '%d/%d' % (self.num, self.den) + + def reduce(self): + div=gcd(self.num, self.den) + if div > 1: + self.num=self.num/div + self.den=self.den/div + +# for ease of dealing with tags +class IFD_Tag: + def __init__(self, printable, tag, field_type, values, field_offset, + field_length): + self.printable=printable + self.tag=tag + self.field_type=field_type + self.field_offset=field_offset + self.field_length=field_length + self.values=values + + def __str__(self): + return self.printable + + def __repr__(self): + return '(0x%04X) %s=%s @ %d' % (self.tag, + FIELD_TYPES[self.field_type][2], + self.printable, + self.field_offset) + +# class that handles an EXIF header +class EXIF_header: + def __init__(self, file, endian, offset, debug=0): + self.file=file + self.endian=endian + self.offset=offset + self.debug=debug + self.tags={} + + # convert slice to integer, based on sign and endian flags + def s2n(self, offset, length, signed=0): + self.file.seek(self.offset+offset) + slice=self.file.read(length) + if self.endian == 'I': + val=s2n_intel(slice) + else: + val=s2n_motorola(slice) + # Sign extension ? + if signed: + msb=1L << (8*length-1) + if val & msb: + val=val-(msb << 1) + return val + + # convert offset to string + def n2s(self, offset, length): + s='' + for i in range(length): + if self.endian == 'I': + s=s+chr(offset & 0xFF) + else: + s=chr(offset & 0xFF)+s + offset=offset >> 8 + return s + + # return first IFD + def first_IFD(self): + return self.s2n(4, 4) + + # return pointer to next IFD + def next_IFD(self, ifd): + entries=self.s2n(ifd, 2) + return self.s2n(ifd+2+12*entries, 4) + + # return list of IFDs in header + def list_IFDs(self): + i=self.first_IFD() + a=[] + while i: + a.append(i) + i=self.next_IFD(i) + return a + + # return list of entries in this IFD + def dump_IFD(self, ifd, ifd_name, dict=EXIF_TAGS): + entries=self.s2n(ifd, 2) + for i in range(entries): + entry=ifd+2+12*i + tag=self.s2n(entry, 2) + field_type=self.s2n(entry+2, 2) + if not 0 < field_type < len(FIELD_TYPES): + # unknown field type + raise ValueError, \ + 'unknown type %d in tag 0x%04X' % (field_type, tag) + typelen=FIELD_TYPES[field_type][0] + count=self.s2n(entry+4, 4) + offset=entry+8 + if count*typelen > 4: + # not the value, it's a pointer to the value + offset=self.s2n(offset, 4) + field_offset=offset + if field_type == 2: + # special case: null-terminated ASCII string + if count != 0: + self.file.seek(self.offset+offset) + values=self.file.read(count).strip().replace('\x00','') + else: + values='' + elif tag == 0x927C or tag == 0x9286: # MakerNote or UserComment +# elif tag == 0x9286: # UserComment + values=[] + else: + values=[] + signed=(field_type in [6, 8, 9, 10]) + for j in range(count): + if field_type in (5, 10): + # a ratio + value_j=Ratio(self.s2n(offset, 4, signed), + self.s2n(offset+4, 4, signed)) + else: + value_j=self.s2n(offset, typelen, signed) + values.append(value_j) + offset=offset+typelen + # now "values" is either a string or an array + if count == 1 and field_type != 2: + printable=str(values[0]) + else: + printable=str(values) + # figure out tag name + tag_entry=dict.get(tag) + if tag_entry: + tag_name=tag_entry[0] + if len(tag_entry) != 1: + # optional 2nd tag element is present + if callable(tag_entry[1]): + # call mapping function + printable=tag_entry[1](values) + else: + printable='' + for i in values: + # use LUT for this tag + printable+=tag_entry[1].get(i, repr(i)) + else: + tag_name='Tag 0x%04X' % tag + self.tags[ifd_name+' '+tag_name]=IFD_Tag(printable, tag, + field_type, + values, field_offset, + count*typelen) + if self.debug: + print ' %s: %s' % (tag_name, + repr(self.tags[ifd_name+' '+tag_name])) + + # extract uncompressed TIFF thumbnail (like pulling teeth) + # we take advantage of the pre-existing layout in the thumbnail IFD as + # much as possible + def extract_TIFF_thumbnail(self, thumb_ifd): + entries=self.s2n(thumb_ifd, 2) + # this is header plus offset to IFD ... + if self.endian == 'M': + tiff='MM\x00*\x00\x00\x00\x08' + else: + tiff='II*\x00\x08\x00\x00\x00' + # ... plus thumbnail IFD data plus a null "next IFD" pointer + self.file.seek(self.offset+thumb_ifd) + tiff+=self.file.read(entries*12+2)+'\x00\x00\x00\x00' + + # fix up large value offset pointers into data area + for i in range(entries): + entry=thumb_ifd+2+12*i + tag=self.s2n(entry, 2) + field_type=self.s2n(entry+2, 2) + typelen=FIELD_TYPES[field_type][0] + count=self.s2n(entry+4, 4) + oldoff=self.s2n(entry+8, 4) + # start of the 4-byte pointer area in entry + ptr=i*12+18 + # remember strip offsets location + if tag == 0x0111: + strip_off=ptr + strip_len=count*typelen + # is it in the data area? + if count*typelen > 4: + # update offset pointer (nasty "strings are immutable" crap) + # should be able to say "tiff[ptr:ptr+4]=newoff" + newoff=len(tiff) + tiff=tiff[:ptr]+self.n2s(newoff, 4)+tiff[ptr+4:] + # remember strip offsets location + if tag == 0x0111: + strip_off=newoff + strip_len=4 + # get original data and store it + self.file.seek(self.offset+oldoff) + tiff+=self.file.read(count*typelen) + + # add pixel strips and update strip offset info + old_offsets=self.tags['Thumbnail StripOffsets'].values + old_counts=self.tags['Thumbnail StripByteCounts'].values + for i in range(len(old_offsets)): + # update offset pointer (more nasty "strings are immutable" crap) + offset=self.n2s(len(tiff), strip_len) + tiff=tiff[:strip_off]+offset+tiff[strip_off+strip_len:] + strip_off+=strip_len + # add pixel strip to end + self.file.seek(self.offset+old_offsets[i]) + tiff+=self.file.read(old_counts[i]) + + self.tags['TIFFThumbnail']=tiff + + # decode all the camera-specific MakerNote formats + def decode_maker_note(self): + note=self.tags['EXIF MakerNote'] + make=self.tags['Image Make'].printable + model=self.tags['Image Model'].printable + + # Nikon + if make == 'NIKON': + if note.values[0:5] == [78, 105, 107, 111, 110]: # "Nikon" + # older model + self.dump_IFD(note.field_offset+8, 'MakerNote', + dict=MAKERNOTE_NIKON_OLDER_TAGS) + else: + # newer model (E99x or D1) + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_NIKON_NEWER_TAGS) + return + + # Olympus + if make[:7] == 'OLYMPUS': + self.dump_IFD(note.field_offset+8, 'MakerNote', + dict=MAKERNOTE_OLYMPUS_TAGS) + return + + # Casio + if make == 'Casio': + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_CASIO_TAGS) + return + + # Fujifilm + if make == 'FUJIFILM': + # bug: everything else is "Motorola" endian, but the MakerNote + # is "Intel" endian + endian=self.endian + self.endian='I' + # bug: IFD offsets are from beginning of MakerNote, not + # beginning of file header + offset=self.offset + self.offset+=note.field_offset + # process note with bogus values (note is actually at offset 12) + self.dump_IFD(12, 'MakerNote', dict=MAKERNOTE_FUJIFILM_TAGS) + # reset to correct values + self.endian=endian + self.offset=offset + return + + # Canon + if make == 'Canon': + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_CANON_TAGS) + for i in (('MakerNote Tag 0x0001', MAKERNOTE_CANON_TAG_0x001), + ('MakerNote Tag 0x0004', MAKERNOTE_CANON_TAG_0x004)): + if self.debug: + print ' SubMakerNote BitSet for ' +i[0] + self.canon_decode_tag(self.tags[i[0]].values, i[1]) + return + + # decode Canon MakerNote tag based on offset within tag + # see http://www.burren.cx/david/canon.html by David Burren + def canon_decode_tag(self, value, dict): + for i in range(1, len(value)): + x=dict.get(i, ('Unknown', )) +# if self.debug: +# print i, x + name=x[0] + if len(x) > 1: + val=x[1].get(value[i], 'Unknown') + else: + val=value[i] + if self.debug: + print ' '+name+':', val + self.tags['MakerNote '+name]=val + +# process an image file (expects an open file object) +# this is the function that has to deal with all the arbitrary nasty bits +# of the EXIF standard +def process_file(file, debug=0, noclose=0): + # determine whether it's a JPEG or TIFF + data=file.read(12) + if data[0:4] in ['II*\x00', 'MM\x00*']: + # it's a TIFF file + file.seek(0) + endian=file.read(1) + file.read(1) + offset=0 + elif data[0:2] == '\xFF\xD8': + # it's a JPEG file + # skip JFIF style header(s) + while data[2] == '\xFF' and data[6:10] in ('JFIF', 'JFXX', 'OLYM'): + length=ord(data[4])*256+ord(data[5]) + file.read(length-8) + # fake an EXIF beginning of file + data='\xFF\x00'+file.read(10) + if data[2] == '\xFF' and data[6:10] == 'Exif': + # detected EXIF header + offset=file.tell() + endian=file.read(1) + else: + # no EXIF information + return {} + else: + # file format not recognized + return {} + + # deal with the EXIF info we found + if debug: + print {'I': 'Intel', 'M': 'Motorola'}[endian], 'format' + hdr=EXIF_header(file, endian, offset, debug) + ifd_list=hdr.list_IFDs() + ctr=0 + for i in ifd_list: + if ctr == 0: + IFD_name='Image' + elif ctr == 1: + IFD_name='Thumbnail' + thumb_ifd=i + else: + IFD_name='IFD %d' % ctr + if debug: + print ' IFD %d (%s) at offset %d:' % (ctr, IFD_name, i) + hdr.tags['Exif Offset'] = offset + hdr.tags['Exif Endian'] = endian + hdr.tags[IFD_name+' IFDOffset'] = i + hdr.dump_IFD(i, IFD_name) + # EXIF IFD + exif_off=hdr.tags.get(IFD_name+' ExifOffset') + if exif_off: + if debug: + print ' EXIF SubIFD at offset %d:' % exif_off.values[0] + hdr.dump_IFD(exif_off.values[0], 'EXIF') + # Interoperability IFD contained in EXIF IFD + #intr_off=hdr.tags.get('EXIF SubIFD InteroperabilityOffset') + intr_off=hdr.tags.get('EXIF InteroperabilityOffset') + if intr_off: + if debug: + print ' EXIF Interoperability SubSubIFD at offset %d:' \ + % intr_off.values[0] + hdr.dump_IFD(intr_off.values[0], 'EXIF Interoperability', + dict=INTR_TAGS) + # deal with MakerNote contained in EXIF IFD + if hdr.tags.has_key('EXIF MakerNote'): + if debug: + print ' EXIF MakerNote SubSubIFD at offset %d:' \ + % intr_off.values[0] + hdr.decode_maker_note() + # GPS IFD + gps_off=hdr.tags.get(IFD_name+' GPSInfoOffset') + if gps_off: + if debug: + print ' GPS SubIFD at offset %d:' % gps_off.values[0] + hdr.dump_IFD(gps_off.values[0], 'GPS', dict=GPS_TAGS) + ctr+=1 + + + # extract uncompressed TIFF thumbnail + thumb=hdr.tags.get('Thumbnail Compression') + if thumb and thumb.printable == 'Uncompressed TIFF': + hdr.extract_TIFF_thumbnail(thumb_ifd) + + # JPEG thumbnail (thankfully the JPEG data is stored as a unit) + thumb_off=hdr.tags.get('Thumbnail JPEGInterchangeFormat') + if thumb_off: + file.seek(offset+thumb_off.values[0]) + size=hdr.tags['Thumbnail JPEGInterchangeFormatLength'].values[0] + hdr.tags['JPEGThumbnail']=file.read(size) + + # Sometimes in a TIFF file, a JPEG thumbnail is hidden in the MakerNote + # since it's not allowed in a uncompressed TIFF IFD + if not hdr.tags.has_key('JPEGThumbnail'): + thumb_off=hdr.tags.get('MakerNote JPEGThumbnail') + if thumb_off: + file.seek(offset+thumb_off.values[0]) + hdr.tags['JPEGThumbnail']=file.read(thumb_off.field_length) + + if noclose == 0: + file.close() + return hdr.tags + +# library test/debug function (dump given files) +if __name__ == '__main__': + import sys + + if len(sys.argv) < 2: + print 'Usage: %s files...\n' % sys.argv[0] + sys.exit(0) + + for filename in sys.argv[1:]: + try: + file=open(filename, 'rb') + except: + print filename, 'unreadable' + print + continue + print filename+':' + # data=process_file(file, 1) # with debug info + data=process_file(file, 1) + if not data: + print 'No EXIF information found' + continue + +# x=data.keys() +# x.sort() +# for i in x: +# if i in ('JPEGThumbnail', 'TIFFThumbnail'): +# continue +# print ' %s (%s): %s' % \ +# (i, FIELD_TYPES[data[i].field_type][2], data[i].printable) +# if data.has_key('JPEGThumbnail'): +# print 'File has JPEG thumbnail' +# print diff --git a/plugins/imagerotation/imageconverter.desktop b/plugins/imagerotation/imageconverter.desktop new file mode 100644 index 0000000..b304fed --- /dev/null +++ b/plugins/imagerotation/imageconverter.desktop @@ -0,0 +1,358 @@ +[Desktop Entry] +ServiceTypes=KonqPopupMenu/Plugin,image/* +TryExec=convert +Type=Service +Actions=convToJPEG;convToPNG;convToGIF;convToTIF; +X-KDE-Submenu=Convert To +X-KDE-Submenu[ar]=حول إلى +X-KDE-Submenu[ast]=Convertir a +X-KDE-Submenu[be]=Канвертаваць у +X-KDE-Submenu[bg]=Преобразуване в +X-KDE-Submenu[bs]=Pretvori u +X-KDE-Submenu[ca]=Converteix a +X-KDE-Submenu[ca@valencia]=Converteix a +X-KDE-Submenu[cs]=Převést do +X-KDE-Submenu[da]=Konvertér til +X-KDE-Submenu[de]=Umwandeln in +X-KDE-Submenu[el]=Μετατροπή σε +X-KDE-Submenu[en_GB]=Convert To +X-KDE-Submenu[es]=Convertir a +X-KDE-Submenu[et]=Teisendamine +X-KDE-Submenu[eu]=Bihurtu hona +X-KDE-Submenu[fa]=تبدیل به +X-KDE-Submenu[fi]=Muunna muotoon +X-KDE-Submenu[fr]=Convertir en +X-KDE-Submenu[ga]=Tiontaigh Go +X-KDE-Submenu[gl]=Converter en +X-KDE-Submenu[he]=המר אל +X-KDE-Submenu[hne]=ये मां बदलव +X-KDE-Submenu[hr]=Pretvori u +X-KDE-Submenu[hu]=Konvertálás +X-KDE-Submenu[ia]=Converte a +X-KDE-Submenu[id]=Konversi Ke +X-KDE-Submenu[is]=Umbreyta í +X-KDE-Submenu[it]=Converti in +X-KDE-Submenu[ja]=変換 +X-KDE-Submenu[kk]=Келесіге аудару: +X-KDE-Submenu[km]=បម្លែង​ទៅ +X-KDE-Submenu[kn]=ಇದಕ್ಕೆ ಪರಿವರ್ತಿಸು +X-KDE-Submenu[ko]=다음으로 변환 +X-KDE-Submenu[ku]=Veguhezîne Ji +X-KDE-Submenu[lt]=Konvertuoti į +X-KDE-Submenu[lv]=Pārveidot uz +X-KDE-Submenu[mr]=यात रूपांतरीत करा +X-KDE-Submenu[nb]=Konverter til +X-KDE-Submenu[nds]=Ümwanneln na +X-KDE-Submenu[nl]=Converteren naar +X-KDE-Submenu[nn]=Gjer om til +X-KDE-Submenu[pa]=ਬਦਲੋ +X-KDE-Submenu[pl]=Przekształć do +X-KDE-Submenu[pt]=Converter Para +X-KDE-Submenu[pt_BR]=Converter para +X-KDE-Submenu[ro]=Convertește la +X-KDE-Submenu[ru]=Преобразовать в +X-KDE-Submenu[sk]=PreviesÅ¥ do +X-KDE-Submenu[sl]=Pretvori v +X-KDE-Submenu[sr]=Претвори у +X-KDE-Submenu[sr@ijekavian]=Претвори у +X-KDE-Submenu[sr@ijekavianlatin]=Pretvori u +X-KDE-Submenu[sr@latin]=Pretvori u +X-KDE-Submenu[sv]=Konvertera till +X-KDE-Submenu[tg]=Табдилкунӣ ба +X-KDE-Submenu[th]=แปลงเป็น +X-KDE-Submenu[tr]=Dönüştür +X-KDE-Submenu[ug]=ئايلاندۇر +X-KDE-Submenu[uk]=Перетворити на +X-KDE-Submenu[vi]=Chuyển đổi sang +X-KDE-Submenu[wa]=Kivierser viè +X-KDE-Submenu[x-test]=xxConvert Toxx +X-KDE-Submenu[zh_CN]=转换为 +X-KDE-Submenu[zh_TW]=轉換為 +TryExec=convert + +[Desktop Action convToJPEG] +Name=JPEG +Name[ar]=JPEG +Name[ast]=JPEG +Name[be]=JPEG +Name[bg]=JPEG +Name[bs]=JPEG +Name[ca]=JPEG +Name[ca@valencia]=JPEG +Name[cs]=JPEG +Name[da]=JPEG +Name[de]=JPEG +Name[el]=JPEG +Name[en_GB]=JPEG +Name[eo]=JPEG +Name[es]=JPEG +Name[et]=JPEG +Name[eu]=JPEG +Name[fi]=JPEG +Name[fr]=JPEG +Name[ga]=JPEG +Name[gl]=JPEG +Name[he]=JPEG +Name[hne]=जेपीईजी +Name[hr]=JPEG +Name[hu]=JPEG +Name[ia]=JPEG +Name[id]=JPEG +Name[is]=JPEG +Name[it]=JPEG +Name[ja]=JPEG +Name[kk]=JPEG +Name[km]=JPEG +Name[kn]=JPEG +Name[ko]=JPEG +Name[ku]=JPEG +Name[lt]=JPEG +Name[lv]=JPEG +Name[mai]=JPEG +Name[mr]=JPEG +Name[ms]=JPEG +Name[nb]=JPEG +Name[nds]=JPEG +Name[nl]=JPEG +Name[nn]=JPEG +Name[oc]=JPEG +Name[pa]=JPEG +Name[pl]=JPEG +Name[pt]=JPEG +Name[pt_BR]=JPEG +Name[ro]=JPEG +Name[ru]=JPEG +Name[se]=JPEG +Name[sk]=JPEG +Name[sl]=JPEG +Name[sr]=ЈПЕГ +Name[sr@ijekavian]=ЈПЕГ +Name[sr@ijekavianlatin]=JPEG +Name[sr@latin]=JPEG +Name[sv]=JPEG +Name[tg]=JPEG +Name[th]=แฟ้มภาพประเภท JPEG +Name[tr]=JPEG +Name[ug]=JPEG +Name[uk]=JPEG +Name[vi]=JPEG +Name[wa]=JPEG +Name[x-test]=xxJPEGxx +Name[zh_CN]=JPEG +Name[zh_TW]=JPEG +Icon=image-jpeg +Exec=convert %f "`echo %f | perl -pe 's/\\.[^.]+$//'`.jpg" + +[Desktop Action convToPNG] +Name=PNG +Name[ar]=PNG +Name[ast]=PNG +Name[be]=PNG +Name[bg]=PNG +Name[bs]=PNG +Name[ca]=PNG +Name[ca@valencia]=PNG +Name[cs]=PNG +Name[da]=PNG +Name[de]=PNG +Name[el]=PNG +Name[en_GB]=PNG +Name[eo]=PNG +Name[es]=PNG +Name[et]=PNG +Name[eu]=PNG +Name[fi]=PNG +Name[fr]=PNG +Name[ga]=PNG +Name[gl]=PNG +Name[he]=PNG +Name[hne]=पीएनजी +Name[hr]=PNG +Name[hu]=PNG +Name[ia]=PNG +Name[id]=PNG +Name[is]=PNG +Name[it]=PNG +Name[ja]=PNG +Name[kk]=PNG +Name[km]=PNG +Name[kn]=PNG +Name[ko]=PNG +Name[ku]=PNG +Name[lt]=PNG +Name[lv]=PNG +Name[mai]=PNG +Name[mr]=PNG +Name[ms]=PNG +Name[nb]=PNG +Name[nds]=PNG +Name[nl]=PNG +Name[nn]=PNG +Name[oc]=PNG +Name[pa]=PNG +Name[pl]=PNG +Name[pt]=PNG +Name[pt_BR]=PNG +Name[ro]=PNG +Name[ru]=PNG +Name[se]=PNG +Name[sk]=PNG +Name[sl]=PNG +Name[sr]=ПНГ +Name[sr@ijekavian]=ПНГ +Name[sr@ijekavianlatin]=PNG +Name[sr@latin]=PNG +Name[sv]=PNG +Name[tg]=PNG +Name[th]=แฟ้มภาพประเภท PNG +Name[tr]=PNG +Name[ug]=PNG +Name[uk]=PNG +Name[vi]=PNG +Name[wa]=PNG +Name[x-test]=xxPNGxx +Name[zh_CN]=PNG +Name[zh_TW]=PNG +Icon=image-png +Exec=convert %f "`echo %f | perl -pe 's/\\.[^.]+$//'`.png" + +[Desktop Action convToTIF] +Name=TIFF +Name[ar]=TIFF +Name[ast]=TIFF +Name[bg]=TIFF +Name[bs]=TIFF +Name[ca]=TIFF +Name[ca@valencia]=TIFF +Name[cs]=TIF +Name[da]=TIFF +Name[de]=TIFF +Name[el]=TIFF +Name[en_GB]=TIFF +Name[eo]=TIFF +Name[es]=TIFF +Name[et]=TIFF +Name[eu]=TIFF +Name[fi]=TIFF +Name[fr]=TIFF +Name[ga]=TIFF +Name[gl]=TIFF +Name[he]=TIFF +Name[hr]=TIFF +Name[hu]=TIFF +Name[ia]=TIFF +Name[id]=TIFF +Name[is]=TIFF +Name[it]=TIFF +Name[ja]=TIFF +Name[kk]=TIFF +Name[km]=TIFF +Name[ko]=TIFF +Name[lt]=TIFF +Name[lv]=TIFF +Name[mai]=TIFF +Name[mr]=TIFF +Name[ms]=TIFF +Name[nb]=TIFF +Name[nds]=TIFF +Name[nl]=TIFF +Name[nn]=TIFF +Name[pa]=TIFF +Name[pl]=TIFF +Name[pt]=TIFF +Name[pt_BR]=TIFF +Name[ro]=TIFF +Name[ru]=TIFF +Name[se]=TIFF +Name[sk]=TIFF +Name[sl]=TIFF +Name[sr]=ТИФФ +Name[sr@ijekavian]=ТИФФ +Name[sr@ijekavianlatin]=TIFF +Name[sr@latin]=TIFF +Name[sv]=TIFF +Name[tg]=TIFF +Name[th]=แฟ้มภาพประเภท TIF +Name[tr]=TIFF +Name[ug]=TIFF +Name[uk]=TIFF +Name[wa]=TIFF +Name[x-test]=xxTIFFxx +Name[zh_CN]=TIFF +Name[zh_TW]=TIFF +Icon=image-tiff +Exec=convert %f "`echo %f | perl -pe 's/\\.[^.]+$//'`.tif" + +[Desktop Action convToGIF] +Name=GIF +Name[ar]=GIF +Name[ast]=GIF +Name[be]=GIF +Name[bg]=GIF +Name[bs]=GIF +Name[ca]=GIF +Name[ca@valencia]=GIF +Name[cs]=GIF +Name[da]=GIF +Name[de]=GIF +Name[el]=GIF +Name[en_GB]=GIF +Name[eo]=GIF +Name[es]=GIF +Name[et]=GIF +Name[eu]=GIF +Name[fi]=GIF +Name[fr]=GIF +Name[ga]=GIF +Name[gl]=GIF +Name[he]=GIF +Name[hne]=जीआईएफ +Name[hr]=GIF +Name[hu]=GIF +Name[ia]=GIF +Name[id]=GIF +Name[is]=GIF +Name[it]=GIF +Name[ja]=GIF +Name[kk]=GIF +Name[km]=GIF +Name[kn]=GIF +Name[ko]=GIF +Name[ku]=GIF +Name[lt]=GIF +Name[lv]=GIF +Name[mai]=GIF +Name[mr]=GIF +Name[ms]=GIF +Name[nb]=GIF +Name[nds]=GIF +Name[nl]=GIF +Name[nn]=GIF +Name[oc]=GIF +Name[pa]=GIF +Name[pl]=GIF +Name[pt]=GIF +Name[pt_BR]=GIF +Name[ro]=GIF +Name[ru]=GIF +Name[se]=GIF +Name[sk]=GIF +Name[sl]=GIF +Name[sr]=ГИФ +Name[sr@ijekavian]=ГИФ +Name[sr@ijekavianlatin]=GIF +Name[sr@latin]=GIF +Name[sv]=GIF +Name[tg]=GIF +Name[th]=แฟ้มภาพประเภท GIF +Name[tr]=GIF +Name[ug]=GIF +Name[uk]=GIF +Name[vi]=GIF +Name[wa]=GIF +Name[x-test]=xxGIFxx +Name[zh_CN]=GIF +Name[zh_TW]=GIF +Icon=image-gif +Exec=convert %f "`echo %f | perl -pe 's/\\.[^.]+$//'`.gif" + diff --git a/plugins/imagerotation/jpegorient b/plugins/imagerotation/jpegorient new file mode 100755 index 0000000..9504d25 --- /dev/null +++ b/plugins/imagerotation/jpegorient @@ -0,0 +1,85 @@ +#!/bin/sh + +if test "$#" -lt 2; then + echo "Usage: $0 '##|v|h' jpegs" + exit 2 +fi + +die() { + echo "$@"; exit 1 +} + +notify() { + case "$1" in + /*) url=file:"$1" ;; + *) url=file:"$PWD"/"$1" ;; + esac + + konq=`dcop konqueror-\*` + for k in $konq; do + notify=`dcop $k KDirNotify-\*` + for n in $notify; do + dcop $k $n FilesChanged [ "$url" ] # $1 must be a url + done + done +} + + + + +action=$1 + +case $action in +[1-8]|+[1-8]) o=$action ;; +90|[+-]90) o=+6 ;; # Use + for all these +270|[+-]270) o=+8 ;; +180|[+-]180) o=+3 ;; +v|-v) o=+4 ;; +h|-h) o=+2 ;; +*) die cannot understand transformation "$action" ;; +esac + +shift + +for file in "$@"; do + +if orient.py $o "$file" | grep 'orientation changed' >/dev/null 2>&1; then + notify "$file" + continue +fi + +### try jpegtran instead +if which jpegtran-mmx >/dev/null 2>&1; then + JPEGTRAN=jpegtran-mmx +else + if which jpegtran >/dev/null 2>&1; then + JPEGTRAN=jpegtran + else + die could not change orientation + fi +fi + +case $action in +v|-v) c='-flip vertical' ;; +h|-h) c='-flip horizontal' ;; +*90) c='-rotate 90' ;; +*180) c='-rotate 180' ;; +*270) c='-rotate 270' ;; ++5) c='-transpose' ;; ++7) c='-transverse' ;; +*) die cannot understand transformation "$action" using jpegtran ;; +esac # others could be emulated, but ... + +tmp="$file.a.$$" + +cleandie() { + mv -i "$tmp" $"2" /dev/null; die "$@" +} + +mv -i "$file" "$tmp" /dev/null || die unable to move temp files +$JPEGTRAN -copy all -outfile "$file" $c "$tmp" || cleandie error using jpegtran +rm "$tmp" +notify "$file" + +done + diff --git a/plugins/imagerotation/jpegorient.desktop b/plugins/imagerotation/jpegorient.desktop new file mode 100644 index 0000000..1c665c4 --- /dev/null +++ b/plugins/imagerotation/jpegorient.desktop @@ -0,0 +1,359 @@ +[Desktop Entry] +TryExec=jpegorient +Type=Service +ServiceTypes=KonqPopupMenu/Plugin,image/jpeg +Actions=jpegRot90;jpegRot270;jpegFlipV;jpegFlipH; +X-KDE-Submenu=Transform Image +X-KDE-Submenu[ar]=انقل الصورة إلىر +X-KDE-Submenu[ast]=Tresformar imaxe +X-KDE-Submenu[be]=Змяніць відарыс +X-KDE-Submenu[bg]=Преобразуване на изображение +X-KDE-Submenu[bs]=Preoblikuj sliku +X-KDE-Submenu[ca]=Transforma imatge +X-KDE-Submenu[ca@valencia]=Transforma imatge +X-KDE-Submenu[cs]=Transformovat obrázek +X-KDE-Submenu[da]=Transformér billede +X-KDE-Submenu[de]=Bild umwandeln +X-KDE-Submenu[el]=Μετασχηματισμός εικόνας +X-KDE-Submenu[en_GB]=Transform Image +X-KDE-Submenu[es]=Transformar imagen +X-KDE-Submenu[et]=Pildi teisendamine +X-KDE-Submenu[eu]=Eraldatu irudia +X-KDE-Submenu[fa]=تصویر تبدیل +X-KDE-Submenu[fi]=Muokkaa kuvaa +X-KDE-Submenu[fr]=Transformer l'image +X-KDE-Submenu[ga]=Trasfhoirmigh Íomhá +X-KDE-Submenu[gl]=Transformar a imaxe +X-KDE-Submenu[he]=הפוך תמונה +X-KDE-Submenu[hne]=फोटू बदलव +X-KDE-Submenu[hr]=Transformiranje slike +X-KDE-Submenu[hu]=Kép átalakítása +X-KDE-Submenu[ia]=Transforma imagine +X-KDE-Submenu[id]=Transformasi Citra +X-KDE-Submenu[is]=Breyta mynd +X-KDE-Submenu[it]=Trasforma l'immagine +X-KDE-Submenu[ja]=画像を変換 +X-KDE-Submenu[kk]=Кескінді түрлендіру +X-KDE-Submenu[km]=ប្លែង​រូបភាព +X-KDE-Submenu[kn]=ಬಿಂಬವನ್ನು (ಇಮೇಜ್) ರೂಪಾಂತರಗೊಳಿಸು +X-KDE-Submenu[ko]=그림 변형하기 +X-KDE-Submenu[ku]=Wêne Veguherînê +X-KDE-Submenu[lt]=Transformuoti paveikslėlį +X-KDE-Submenu[lv]=Pārveidot attēlu +X-KDE-Submenu[mr]=प्रतिमा रूपांतरीत करा +X-KDE-Submenu[nb]=Transformer bilde +X-KDE-Submenu[nds]=Bild wanneln +X-KDE-Submenu[nl]=Afbeelding transformeren +X-KDE-Submenu[nn]=Omform biletet +X-KDE-Submenu[oc]=Transformar l'imatge +X-KDE-Submenu[pa]=ਚਿੱਤਰ ਬਦਲੋ +X-KDE-Submenu[pl]=Przekształć obraz +X-KDE-Submenu[pt]=Transformar a Imagem +X-KDE-Submenu[pt_BR]=Transformar a imagem +X-KDE-Submenu[ro]=Transformă imaginea +X-KDE-Submenu[ru]=Преобразовать изображение +X-KDE-Submenu[sk]=TransformovaÅ¥ obrázok +X-KDE-Submenu[sl]=Preoblikuj sliko +X-KDE-Submenu[sr]=Преобликуј слику +X-KDE-Submenu[sr@ijekavian]=Преобликуј слику +X-KDE-Submenu[sr@ijekavianlatin]=Preoblikuj sliku +X-KDE-Submenu[sr@latin]=Preoblikuj sliku +X-KDE-Submenu[sv]=Omvandla bild +X-KDE-Submenu[tg]=Тағйири тасвир +X-KDE-Submenu[th]=แปลงรูปภาพ +X-KDE-Submenu[tr]=Resmi Dönüştür +X-KDE-Submenu[ug]=سۈرەت ئايلاندۇرۇش +X-KDE-Submenu[uk]=Перетворити зображення +X-KDE-Submenu[vi]=Chuyển đổi ảnh +X-KDE-Submenu[wa]=Candjî imÃ¥dje +X-KDE-Submenu[x-test]=xxTransform Imagexx +X-KDE-Submenu[zh_CN]=图像变换 +X-KDE-Submenu[zh_TW]=轉換影像 +X-KDE-Require=Write + +[Desktop Action jpegRot90] +Name=Rotate Clockwise +Name[ar]=أدر باتجاه عقارب الساعة +Name[ast]=Xirar nel sentíu horariu +Name[be]=Павярнуць па гадзіннай стрэлцы +Name[bg]=Завъртане по посока на часовниковата стрелка +Name[bs]=Rotiraj u smjeru kazaljke +Name[ca]=Gira en sentit horari +Name[ca@valencia]=Gira en sentit horari +Name[cs]=Rotovat po směru hodin +Name[da]=Rotér med uret +Name[de]=Mit dem Uhrzeigersinn drehen +Name[el]=Περιστροφή με τη Φορά του Ρολογιού +Name[en_GB]=Rotate Clockwise +Name[es]=Girar en el sentido de las agujas del reloj +Name[et]=Pööra päripäeva +Name[eu]=Biratu ordulariaren norantzan +Name[fa]=چرخش در جهت عقربه‌های ساعت +Name[fi]=Käännä myötäpäivään +Name[fr]=Tourner dans le sens horaire +Name[ga]=Rothlaigh go Deisealach +Name[gl]=Rotar no sentido horario +Name[he]=סובב בכיוון השעון +Name[hne]=घड़ी के दिसा मं घुमाव +Name[hr]=Rotiraj u smjeru kazaljke na satu +Name[hu]=Forgatás jobbra +Name[ia]=Rota in senso horari +Name[id]=Rotasikan Searah-Jarum-Jam +Name[is]=Snúa réttsælis +Name[it]=Ruota in senso orario +Name[ja]=時計回りに回転 +Name[kk]=Сағат тілі бойынша бұру +Name[km]=បង្វិល​ស្រប​ទ្រិចនាឡិកា​ +Name[kn]=ಪ್ರದಕ್ಷಿಣಾಕಾರದಲ್ಲಿ ತಿರುಗಿಸು +Name[ko]=시계 방향으로 회전하기 +Name[ku]=Aliyê Gera Saetê Bizivirîne +Name[lt]=Sukti pagal laikrodžio rodyklę +Name[lv]=Pagriezt pulksteņrādÄ«tāja virzienā +Name[mr]=घड्याळाच्या काट्याच्या दिशेने फिरवा +Name[nb]=Roter med urviseren +Name[nds]=Na rechts dreihen +Name[nl]=Rechtsom draaien +Name[nn]=Roter med klokka +Name[pa]=ਸੱਜੇ ਦਾਅ ਘੁੰਮਾਓ +Name[pl]=Obróć w prawo +Name[pt]=Rodar no Sentido Horário +Name[pt_BR]=Girar no sentido horário +Name[ro]=Rotește în sensul acelor de ceasornic +Name[ru]=Повернуть по часовой стрелке +Name[sk]=OtočiÅ¥ v smere hodin +Name[sl]=Zavrti v smeri urinega kazalca +Name[sr]=Окрени у смеру казаљке сата +Name[sr@ijekavian]=Окрени у смјеру казаљке сата +Name[sr@ijekavianlatin]=Okreni u smjeru kazaljke sata +Name[sr@latin]=Okreni u smeru kazaljke sata +Name[sv]=Rotera medurs +Name[tg]=Баргардондани соатӣ +Name[th]=หมุนตามเข็มนาฬิกา +Name[tr]=Saat Yönünde Çevir +Name[ug]=سائەت ئىسترېلكىسى يۆنىلىشىدە چۆرگىلىتىش +Name[uk]=Обернути за годинниковою стрілкою +Name[vi]=Xoay xuôi chiều +Name[wa]=Tourner dins l' sins des aweyes +Name[x-test]=xxRotate Clockwisexx +Name[zh_CN]=顺时针旋转 +Name[zh_TW]=順時針旋轉 +Icon=object-rotate-right +Exec=jpegorient +90 %F + +[Desktop Action jpegRot270] +Name=Rotate Counter-Clockwise +Name[ar]=أدر بعكس اتجاه عقارب الساعة +Name[ast]=Xirar nel sentíu antihorariu +Name[be]=Павярнуць супаць гадзіннай стрэлкі +Name[bg]=Завъртане обратно на посоката на часовниковата стрелка +Name[bs]=Rotiraj suprotno smjeru kazaljke +Name[ca]=Gira en sentit antihorari +Name[ca@valencia]=Gira en sentit antihorari +Name[cs]=Rotovat proti směru hodin +Name[da]=Rotér mod uret +Name[de]=Gegen den Uhrzeigersinn drehen +Name[el]=Περιστροφή αριστερόστροφα +Name[en_GB]=Rotate Anti-Clockwise +Name[es]=Girar en sentido contrario a las agujas del reloj +Name[et]=Pööra vastupäeva +Name[eu]=Biratu ordulariaren aurkako norantzan +Name[fa]=چرخش در خلاف جهت عقربه‌های ساعت +Name[fi]=Käännä vastapäivään +Name[fr]=Tourner dans le sens antihoraire +Name[ga]=Rothlaigh go Tuathalach +Name[gl]=Rotar no sentido antihorario +Name[he]=סובב נגד כיוון השעון +Name[hne]=घड़ी के उलटा दिसा मं घुमाव +Name[hr]=Rotiraj obrnutno od smjera kazaljke na satu +Name[hu]=Forgatás balra +Name[ia]=Rota in senso anti-horari +Name[id]=Rotasikan Lawan-Arah-Jarum-Jam +Name[is]=Snúa rangsælis +Name[it]=Ruota in senso antiorario +Name[ja]=反時計回りに回転 +Name[kk]=Сағат жүрісіне қарсы бұру +Name[km]=បង្វិល​ច្រាស​ទ្រិចនាឡិកា​ +Name[kn]=ಅಪ್ರದಕ್ಷಿಣಾಕಾರದಲ್ಲಿ ತಿರುಗಿಸು +Name[ko]=반시계 방향으로 회전하기 +Name[ku]=Aliyê Dijê Gera Saetê Bizivirîne +Name[lt]=Sukti prieÅ¡ laikrodžio rodyklę +Name[lv]=Pagriezt pretēji pulksteņrādÄ«tājam +Name[mr]=घड्याळाच्या काट्याच्या उलट दिशेने फिरवा +Name[nb]=Roter mot urviseren +Name[nds]=Na links dreihen +Name[nl]=Linksom draaien +Name[nn]=Roter mot klokka +Name[pa]=ਖੱਬੇ ਦਾਅ ਘੁੰਮਾਓ +Name[pl]=Obróć w lewo +Name[pt]=Rodar no Sentido Anti-Horário +Name[pt_BR]=Girar no sentido anti-horário +Name[ro]=Rotește în sensul invers al acelor de ceasornic +Name[ru]=Повернуть против часовой стрелки +Name[sk]=OtočiÅ¥ proti smeru hodin +Name[sl]=Zavrti v nasprotni smeri urinega kazalca +Name[sr]=Окрени супротно смеру казаљке сата +Name[sr@ijekavian]=Окрени супротно смјеру казаљке сата +Name[sr@ijekavianlatin]=Okreni suprotno smjeru kazaljke sata +Name[sr@latin]=Okreni suprotno smeru kazaljke sata +Name[sv]=Rotera moturs +Name[tg]=Баргардондани ғайри соатӣ +Name[th]=หมุนทวนเข็มนาฬิกา +Name[tr]=Saat Yönünün Tersine Çevir +Name[ug]=سائەت ئىسترېلكىسىغا قارشى يۆنىلىشتە ئايلاندۇرىدۇ +Name[uk]=Обернути проти годинникової стрілки +Name[vi]=Xoay ngược chiều +Name[wa]=Tourner dins l' sins contraire des aweyes +Name[x-test]=xxRotate Counter-Clockwisexx +Name[zh_CN]=逆时针旋转 +Name[zh_TW]=逆時針旋轉 +Icon=object-rotate-left +Exec=jpegorient +270 %F + +#[Desktop Action jpegRot180] +#Name=Rotate 180 +#Icon=misc +#Exec=jpegorient +180 %F + +[Desktop Action jpegFlipV] +Name=Flip Vertically +Name[ar]=اقلب رأسيا +Name[ast]=Voltiar verticalmente +Name[be]=Адбіць па вертыкалі +Name[bg]=Вертикално обръщане +Name[bs]=Prevrni uspravno +Name[ca]=Inverteix verticalment +Name[ca@valencia]=Inverteix verticalment +Name[cs]=Převrátit svisle +Name[da]=Spejl lodret +Name[de]=Vertikal spiegeln +Name[el]=Αναστροφή κατακόρυφα +Name[en_GB]=Flip Vertically +Name[es]=Reflejar verticalmente +Name[et]=Peegelda vertikaalselt +Name[eu]=Irauli bertikalki +Name[fa]=قرینه عمودی +Name[fi]=Käännä pystysuunnassa +Name[fr]=Miroir vertical +Name[ga]=Smeach go hIngearach +Name[gl]=Inverter verticalmente +Name[he]=הפוך אנכית +Name[hne]=खड़ा पलटव +Name[hr]=Prebaci vertikalno +Name[hu]=Tükrözés függőlegesen +Name[ia]=Colpa verticalmente +Name[id]=Jungkir Secara Tegak +Name[is]=Spegla lóðrétt +Name[it]=Ribalta verticalmente +Name[ja]=上下反転 +Name[kk]=Төңкеріп аудару +Name[km]=ត្រឡប់​បញ្ឈរ +Name[kn]=ತಲೆಕೆಳಗಾಗಿ ಮಗುಚು +Name[ko]=수직으로 뒤집기 +Name[ku]=Tîkane Bizivirîne +Name[lt]=Versti vertikaliai +Name[lv]=Apmest vertikāli +Name[mai]=ठाड़ उनटू +Name[mr]=उभे पलटी करा +Name[ms]=Balikkan Menegak +Name[nb]=Speilvend loddrett +Name[nds]=Pielrecht spegeln +Name[nl]=Verticaal spiegelen +Name[nn]=Vend loddrett +Name[oc]=Coalevar verticalament +Name[pa]=ਵਰਟੀਕਲ ਝਟਕੋ +Name[pl]=Odbij pionowo +Name[pt]=Inverter Verticalmente +Name[pt_BR]=Inverter verticalmente +Name[ro]=Reflectă vertical +Name[ru]=Отразить по вертикали +Name[sk]=PreklopiÅ¥ zvisle +Name[sl]=Zrcali navpično +Name[sr]=Преврни усправно +Name[sr@ijekavian]=Преврни усправно +Name[sr@ijekavianlatin]=Prevrni uspravno +Name[sr@latin]=Prevrni uspravno +Name[sv]=Vänd vertikalt +Name[tg]=Гардонидани амудӣ +Name[th]=พลิกกลับทางแนวตั้ง +Name[tr]=Dikey Olarak Çevir +Name[ug]=تىك ئايلاندۇر +Name[uk]=Віддзеркалити вертикально +Name[vi]=Lật dọc +Name[wa]=Ratourner d' astampé +Name[x-test]=xxFlip Verticallyxx +Name[zh_CN]=垂直翻转 +Name[zh_TW]=垂直翻轉 +Icon=2uparrow +Exec=jpegorient v %F + +[Desktop Action jpegFlipH] +Name=Flip Horizontally +Name[ar]=اقلب أفقيا +Name[ast]=Voltiar horizontalmente +Name[be]=Адбіць па гарызанталі +Name[bg]=Хоризонтално обръщане +Name[bs]=Prevrni vodoravno +Name[ca]=Inverteix horitzontalment +Name[ca@valencia]=Inverteix horitzontalment +Name[cs]=Převrátit vodorovně +Name[da]=Spejl vandret +Name[de]=Horizontal spiegeln +Name[el]=Αναστροφή οριζόντια +Name[en_GB]=Flip Horizontally +Name[es]=Reflejar horizontalmente +Name[et]=Peegelda horisontaalselt +Name[eu]=Irauli horizontalki +Name[fa]=قرینه افقی +Name[fi]=Käännä vaakasuunnassa +Name[fr]=Miroir horizontal +Name[ga]=Smeach go Cothrománach +Name[gl]=Inverter horizontalmente +Name[he]=הפוך אופקית +Name[hne]=आड़ा पलटव +Name[hr]=Prebaci horizontalno +Name[hu]=Tükrözés vízszintesen +Name[ia]=Colpa horizontalmente +Name[id]=Jungkir Secara Mendatar +Name[is]=Spegla lárétt +Name[it]=Ribalta orizzontalmente +Name[ja]=左右反転 +Name[kk]=Аунатып аудару +Name[km]=ត្រឡប់​​ផ្ដេក +Name[kn]=ಅಡ್ಡಲಾಗಿ ಮಗುಚು +Name[ko]=수평으로 뒤집기 +Name[ku]=Berwar Bizivirîne +Name[lt]=Versti horizontaliai +Name[lv]=Apmest horizontāli +Name[mai]=आड़ा उनटू +Name[mr]=आडवे पलटी करा +Name[ms]=Balikkan Mengufuk +Name[nb]=Speilvend vannrett +Name[nds]=Kimmrecht spegeln +Name[nl]=Horizontaal spiegelen +Name[nn]=Vend vassrett +Name[oc]=Coalevar orizontalament +Name[pa]=ਹਰੀਜ਼ੱਟਲ ਝਟਕੋ +Name[pl]=Odbij poziomo +Name[pt]=Inverter Horizontalmente +Name[pt_BR]=Inverter horizontalmente +Name[ro]=Reflectă orizontal +Name[ru]=Отразить по горизонтали +Name[sk]=PreklopiÅ¥ vodorovne +Name[sl]=Zrcali vodoravno +Name[sr]=Преврни водоравно +Name[sr@ijekavian]=Преврни водоравно +Name[sr@ijekavianlatin]=Prevrni vodoravno +Name[sr@latin]=Prevrni vodoravno +Name[sv]=Vänd horisontellt +Name[tg]=Гардонидани уфуқӣ +Name[th]=พลิกกลับทางแนวนอน +Name[tr]=Yatay Olarak Çevir +Name[ug]=يانتۇ ئايلاندۇر +Name[uk]=Віддзеркалити горизонтально +Name[vi]=Lật ngang +Name[wa]=Ratourner di coutchî +Name[x-test]=xxFlip Horizontallyxx +Name[zh_CN]=水平翻转 +Name[zh_TW]=水平翻轉 +Icon=2rightarrow +Exec=jpegorient h %F diff --git a/plugins/imagerotation/orient.py b/plugins/imagerotation/orient.py new file mode 100755 index 0000000..0671876 --- /dev/null +++ b/plugins/imagerotation/orient.py @@ -0,0 +1,104 @@ +#! /usr/bin/env python +import os +import sys +import exif + +def compose(delta, old): + map=[0, 4, 2, 6, 5, 1, 7, 3] + unmap=[1, 6, 3, 8, 2, 5, 4, 7] + x = map[delta-1] + y = map[old-1] + z = ((x^y)&4) + ((y+(x&3)*(((y&4)>>1)+1))&3) + return unmap[z] + +def deg2o(d): + map={90:6, 270:8, 180:3} + if map.has_key(d): + return map[d] + else: + return 0 + +if len(sys.argv) < 2: + print 'Usage: %s [[+]orientnum] file\n' % sys.argv[0] + sys.exit(1) +try: + if len(sys.argv) == 2: + filename=sys.argv[1] + file=open(filename, "r"); + else: + filename=sys.argv[2] + mod=sys.argv[1] + fd = os.open(filename, os.O_RDWR) + file=os.fdopen(fd,'r') + # check file exists and is readable + file.read(1) + file.seek(0,0) +except: + print 'Cannot open', filename + sys.exit(1) + +tags=exif.process_file(file,0,1) +if not tags: + print 'no EXIF information in', filename + sys.exit(1) +if not tags.has_key('Exif Offset') \ + or not tags.has_key('Image Orientation'): + print 'cannot get orientation info in', filename + sys.exit(1) + +exifp = tags['Exif Offset'] +endian = tags['Exif Endian'] +tagp = tags['Image Orientation'].field_offset + +orientp = exifp + tagp + +if endian == 'M': # MM byte order + orientp += 1 + +file.seek(orientp) +o = ord(file.read(1)) + +if o < 1 or o > 8: + print 'orientation out of range', o + sys.exit(1) + +if len(sys.argv) == 2: + print 'orientation is', o + sys.exit(0) + +try: + if mod[0] == '+': + deltao = int(mod) + if 1 <= deltao and deltao <= 8: + newo = compose(deltao, o) + elif deg2o(deltao) != 0: + newo = compose(deg2o(deltao), o) + else: + print 'cannot understand orientation modification', mod + sys.exit(1) # it will still hit the except ... how to fix? + else: + newo = int(mod) +except: + print 'expected numeric orientation and got',mod + sys.exit(1) + +if newo < 1 or newo > 8: + newo = deg2o(newo) + if newo == 0: + print 'cannot understand orientation', deltao + sys.exit(1) + +os.lseek(fd,orientp,0) +os.write(fd,chr(newo)) + +# Thumbnail orientation : +thumb_ifdp = 0 +if tags.has_key('Thumbnail Orientation'): + thumb_tagp = tags['Thumbnail Orientation'].field_offset + thumb_orientp = exifp + thumb_tagp + if endian == 'M': # MM byte order + thumb_orientp += 1 + os.lseek(fd,thumb_orientp,0) + os.write(fd,chr(newo)) + +print 'orientation changed from', o, 'to', newo diff --git a/plugins/khtmlsettingsplugin/CMakeLists.txt b/plugins/khtmlsettingsplugin/CMakeLists.txt new file mode 100644 index 0000000..ccbc969 --- /dev/null +++ b/plugins/khtmlsettingsplugin/CMakeLists.txt @@ -0,0 +1,24 @@ + + + + +########### next target ############### +add_definitions(-DTRANSLATION_DOMAIN=\"khtmlsettingsplugin\") + +set(khtmlsettingsplugin_PART_SRCS settingsplugin.cpp ) + +add_library(khtmlsettingsplugin MODULE ${khtmlsettingsplugin_PART_SRCS}) + + + +target_link_libraries(khtmlsettingsplugin KF5::Parts) + +install(TARGETS khtmlsettingsplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### + +install( FILES khtmlsettingsplugin.rc khtmlsettingsplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/khtml/kpartplugins ) +install( FILES khtmlsettingsplugin.rc khtmlsettingsplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/kwebkitpart/kpartplugins ) +install( FILES khtmlsettingsplugin.rc khtmlsettingsplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/webenginepart/kpartplugins ) + diff --git a/plugins/khtmlsettingsplugin/Messages.sh b/plugins/khtmlsettingsplugin/Messages.sh new file mode 100644 index 0000000..94ac569 --- /dev/null +++ b/plugins/khtmlsettingsplugin/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/khtmlsettingsplugin.pot diff --git a/plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop b/plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop new file mode 100644 index 0000000..b6d1d6a --- /dev/null +++ b/plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop @@ -0,0 +1,137 @@ +[Desktop Entry] +X-KDE-Library=khtmlsettingsplugin +X-KDE-PluginInfo-Author=Carsten Pfeiffer +X-KDE-PluginInfo-Email=pfeiffer@kde.org +X-KDE-PluginInfo-Name=khtmlsettingsplugin +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=KHTML Settings +Name[ar]=إعدادات KHTML +Name[ast]=Axustes de KHTML +Name[bg]=Настройки на KHTML +Name[bs]=Postavke KHTML‑a +Name[ca]=Arranjament KHTML +Name[ca@valencia]=Arranjament KHTML +Name[cs]=Nastavení KHTML +Name[da]=Indstilling af KHTML +Name[de]=KHTML-Einstellungen +Name[el]=Ρυθμίσεις KHTML +Name[en_GB]=KHTML Settings +Name[es]=Preferencias de KHTML +Name[et]=KHTML-i seadistused +Name[eu]=KHTML ezarpenak +Name[fi]=KHTML-asetukset +Name[fr]=Paramètres de KHTML +Name[ga]=Socruithe KHTML +Name[gl]=Configuración de KHTML +Name[he]=הגדרות KHTML +Name[hne]=के-एचटीएमएल सेटिंग +Name[hr]=Postavke KHTML-a +Name[hu]=KHTML-beállítások +Name[ia]=Preferentias de KHTML +Name[id]=Pengaturan KHTML +Name[is]=Stillingar KHTML +Name[it]=Impostazioni KHTML +Name[ja]=KHTML 設定 +Name[kk]=KHTML параметрлері +Name[km]=ការ​កំណត់ KHTML +Name[ko]=KHTML 설정 +Name[ku]=Mîhengên KHTML +Name[lt]=KHTML nuostatos +Name[lv]=KHTML iestatÄ«jumi +Name[mr]=KHTML संयोजना +Name[nb]=KHTML-innstillinger +Name[nds]=KHTML-Instellen +Name[nl]=KHTML-instellingen +Name[nn]=KHTML-innstillingar +Name[oc]=Paramètres de KHTML +Name[pa]=KHTML ਸੈਟਿੰਗ +Name[pl]=Ustawienia KHTML +Name[pt]=Configuração do KHTML +Name[pt_BR]=Configurações do KHTML +Name[ro]=Preferințe KHTML +Name[ru]=Параметры KHTML +Name[sk]=Nastavenie KHTML +Name[sl]=Nastavitve KHTML +Name[sr]=Поставке КХТМЛ‑а +Name[sr@ijekavian]=Поставке КХТМЛ‑а +Name[sr@ijekavianlatin]=Postavke KHTML‑a +Name[sr@latin]=Postavke KHTML‑a +Name[sv]=KHTML-inställningar +Name[tg]=Танзимоти KHTML +Name[th]=ตั้งค่าต่าง ๆ ของ KHTML +Name[tr]=KHTML Ayarları +Name[ug]=KHTML تەڭشەكلىرى +Name[uk]=Параметри KHTML +Name[wa]=Apontiaedjes KHTML +Name[x-test]=xxKHTML Settingsxx +Name[zh_CN]=KHTML 设置 +Name[zh_TW]=KHTML 設定 +Comment=A fast way to change the KHTML settings +Comment[ar]=طريقة سريعة لتغير إعدادات KHTML +Comment[ast]=Un mou rápidu de camudar los axustes de KHTML +Comment[bg]=Бърз начин за промяна настройките на KHTML +Comment[bs]=Brz način da izmijenite postavke KHTML‑a +Comment[ca]=Una manera ràpida de canviar els paràmetres del KHTML +Comment[ca@valencia]=Una manera ràpida de canviar els paràmetres del KHTML +Comment[cs]=Rychlý způsob jak změnit nastavení KHTML +Comment[da]=En hurtig mÃ¥de at ændre KHTML's indstillinger +Comment[de]=Schnelle Möglichkeit zur Änderung der KHTML-Einstellungen +Comment[el]=Γρήγορος τρόπος αλλαγής των ρυθμίσεων του KHTML +Comment[en_GB]=A fast way to change the KHTML settings +Comment[es]=Una forma rápida de cambiar las preferencias de KHTML +Comment[et]=Võimalus kiiresti muuta KHTML-i seadistusi +Comment[eu]=KHTML ezarpenak era azkarrean aldatzeko modua +Comment[fi]=Nopea tapa vaihtaa KHTML-asetuksia +Comment[fr]=Un moyen rapide pour modifier les paramètres de KHTML +Comment[ga]=Modh tapa chun socruithe KHTML a athrú +Comment[gl]=Unha forma rápida de cambiar a configuración de KHTML +Comment[he]=דרך מהירה לשנות את הגדרות ה־KHTML +Comment[hne]=के-एचटीएमएल सेटिंग बदले के तेज तरीका +Comment[hr]=Brzi način kako promijeniti KHTML postavke +Comment[hu]=Egy gyors módszer a KHTML beállításainak megváltoztatására +Comment[ia]=Un modo rapide de cambiar le preferentias de KHTML +Comment[id]=Sebuah cara cepat untuk mengubah pengaturan KHTML +Comment[is]=Breyta stillingum KHTML á fljótvirkan hátt +Comment[it]=Un modo veloce di cambiare le impostazioni di KHTML +Comment[ja]=KHTML 設定を素早く変更できます +Comment[kk]=KHTML параметрлерін өзгертудің оңай жолы +Comment[km]=វិធី​លឿន​បំផុត​ដើម្បី​ផ្លាស់ប្ដូរ​ការ​កំណត់ KHTML +Comment[ko]=KHTML 설정을 바꿀 수 있는 빠른 방법 +Comment[ku]=Riya lez ji bo guherandina mîhengên KHTML +Comment[lt]=Greitas KHTML nustatymų keitimo bÅ«das +Comment[lv]=Ātrs veids, kā mainÄ«t KHTML iestatÄ«jumus +Comment[mr]=KHTML संयोजना बदलण्यासाठी वेगवान मार्ग +Comment[nb]=En rask mÃ¥te Ã¥ endre innstillinger for KHTML +Comment[nds]=De KHTML-Instellen gau ännern +Comment[nl]=Een snelle manier om de KHTML-instellingen te wijzigen +Comment[nn]=Ein rask mÃ¥te Ã¥ endra KHTML-innstillingane pÃ¥ +Comment[pa]=KHTML ਸੈਟਿੰਗ ਬਦਲਣ ਦਾ ਤੇਜ਼ ਢੰਗ +Comment[pl]=Szybki sposób na zmianę ustawień KHTML +Comment[pt]=Uma forma rápida de alterar a configuração do KHTML +Comment[pt_BR]=Uma forma rápida de alterar as configurações do KHTML +Comment[ro]=O cale rapidă de schimbare a preferințelor KHTML +Comment[ru]=Быстрый способ поменять параметры KHTML +Comment[sk]=Rýchly spôsob ako zmeniÅ¥ nastavenie KHTML +Comment[sl]=Hiter način za spreminjanje nastavitev KHTML +Comment[sr]=Брз начин да измените поставке КХТМЛ‑а +Comment[sr@ijekavian]=Брз начин да измијените поставке КХТМЛ‑а +Comment[sr@ijekavianlatin]=Brz način da izmijenite postavke KHTML‑a +Comment[sr@latin]=Brz način da izmenite postavke KHTML‑a +Comment[sv]=Ett snabbt sätt att ändra KHTML-inställningarna +Comment[tg]=Роҳи тезтарин барои иваз кардани танзимоти KHTML +Comment[th]=หนทางในการตั้งค่าต่าง ๆ ของ KHTML อย่างรวดเร็ว +Comment[tr]=KHTML ayarlarını değiştirmenin hızlı bir yolu +Comment[ug]=KHTML تەڭشىكىنى تېز سۈرئەتتە ئۆزگەرتىدىغان ئۇسۇل +Comment[uk]=Швидкий шлях зміни параметрів KHTML +Comment[wa]=Ene roede façon d' candjî les apontiaedjes di KHTML +Comment[x-test]=xxA fast way to change the KHTML settingsxx +Comment[zh_CN]=一种快速改变 KHTML 设置的方法 +Comment[zh_TW]=快速變更 KHTML 設定的方法 +X-KDE-ParentApp=konqueror +Icon=configure +DocPath=konq-plugins/khtmlsettings/index.html diff --git a/plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc b/plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc new file mode 100644 index 0000000..e19493d --- /dev/null +++ b/plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc @@ -0,0 +1,11 @@ + + + + &Tools + + + +Extra Toolbar + + + diff --git a/plugins/khtmlsettingsplugin/settingsplugin.cpp b/plugins/khtmlsettingsplugin/settingsplugin.cpp new file mode 100644 index 0000000..33ace90 --- /dev/null +++ b/plugins/khtmlsettingsplugin/settingsplugin.cpp @@ -0,0 +1,305 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "settingsplugin.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +K_PLUGIN_FACTORY(SettingsPluginFactory, registerPlugin();) + +SettingsPlugin::SettingsPlugin(QObject *parent, + const QVariantList &) + : KParts::Plugin(parent), mConfig(nullptr) +{ + setComponentData(KAboutData(QStringLiteral("khtmlsettingsplugin"), i18n("HTML Settings"), QStringLiteral("1.0"))); + KActionMenu *menu = new KActionMenu(QIcon::fromTheme(QStringLiteral("configure")), i18n("HTML Settings"), actionCollection()); + actionCollection()->addAction(QStringLiteral("action menu"), menu); + menu->setDelayed(false); + + KToggleAction *action = actionCollection()->add(QStringLiteral("javascript")); + action->setText(i18n("Java&Script")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleJavascript(bool))); + menu->addAction(action); + + action = actionCollection()->add(QStringLiteral("java")); + action->setText(i18n("&Java")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleJava(bool))); + menu->addAction(action); + + action = actionCollection()->add(QStringLiteral("cookies")); + action->setText(i18n("&Cookies")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleCookies(bool))); + menu->addAction(action); + + action = actionCollection()->add(QStringLiteral("plugins")); + action->setText(i18n("&Plugins")); + connect(action, SIGNAL(triggered(bool)), SLOT(togglePlugins(bool))); + menu->addAction(action); + + action = actionCollection()->add(QStringLiteral("imageloading")); + action->setText(i18n("Autoload &Images")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleImageLoading(bool))); + menu->addAction(action); + + //menu->addAction( new KSeparatorAction(actionCollection()) ); + + action = actionCollection()->add(QStringLiteral("useproxy")); + action->setText(i18n("Enable Pro&xy")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleProxy(bool))); + menu->addAction(action); + + action = actionCollection()->add(QStringLiteral("usecache")); + action->setText(i18n("Enable Cac&he")); + connect(action, SIGNAL(triggered(bool)), SLOT(toggleCache(bool))); + menu->addAction(action); + + KSelectAction *sAction = actionCollection()->add(QStringLiteral("cachepolicy")); + sAction->setText(i18n("Cache Po&licy")); + QStringList policies; + policies += i18n("&Keep Cache in Sync"); + policies += i18n("&Use Cache if Possible"); + policies += i18n("&Offline Browsing Mode"); + sAction->setItems(policies); + connect(sAction, SIGNAL(triggered(int)), SLOT(cachePolicyChanged(int))); + + menu->addAction(sAction); + + connect(menu->menu(), SIGNAL(aboutToShow()), SLOT(showPopup())); +} + +SettingsPlugin::~SettingsPlugin() +{ + delete mConfig; +} + +static KParts::HtmlSettingsInterface *settingsInterfaceFor(QObject *obj) +{ + KParts::HtmlExtension *extension = KParts::HtmlExtension::childObject(obj); + return qobject_cast< KParts::HtmlSettingsInterface *>(extension); +} + +void SettingsPlugin::showPopup() +{ + if (!mConfig) { + mConfig = new KConfig(QStringLiteral("settingspluginrc"), KConfig::NoGlobals); + } + + KParts::ReadOnlyPart *part = qobject_cast(parent()); + + KProtocolManager::reparseConfiguration(); + const bool cookies = cookiesEnabled(part->url().url()); + actionCollection()->action(QStringLiteral("cookies"))->setChecked(cookies); + actionCollection()->action(QStringLiteral("useproxy"))->setChecked(KProtocolManager::useProxy()); + actionCollection()->action(QStringLiteral("usecache"))->setChecked(KProtocolManager::useCache()); + + KParts::HtmlSettingsInterface *settings = settingsInterfaceFor(part); + if (settings) { + actionCollection()->action(QStringLiteral("java"))->setChecked(settings->htmlSettingsProperty(KParts::HtmlSettingsInterface::JavaEnabled).toBool()); + actionCollection()->action(QStringLiteral("javascript"))->setChecked(settings->htmlSettingsProperty(KParts::HtmlSettingsInterface::JavascriptEnabled).toBool()); + actionCollection()->action(QStringLiteral("plugins"))->setChecked(settings->htmlSettingsProperty(KParts::HtmlSettingsInterface::PluginsEnabled).toBool()); + actionCollection()->action(QStringLiteral("imageloading"))->setChecked(settings->htmlSettingsProperty(KParts::HtmlSettingsInterface::AutoLoadImages).toBool()); + } + + KIO::CacheControl cc = KProtocolManager::cacheControl(); + switch (cc) { + case KIO::CC_Verify: + static_cast(actionCollection()->action(QStringLiteral("cachepolicy")))->setCurrentItem(0); + break; + case KIO::CC_CacheOnly: + static_cast(actionCollection()->action(QStringLiteral("cachepolicy")))->setCurrentItem(2); + break; + case KIO::CC_Cache: + static_cast(actionCollection()->action(QStringLiteral("cachepolicy")))->setCurrentItem(1); + break; + case KIO::CC_Reload: // nothing for now + case KIO::CC_Refresh: + default: + break; + } +} + +void SettingsPlugin::toggleJava(bool checked) +{ + KParts::HtmlSettingsInterface *settings = settingsInterfaceFor(parent()); + if (settings) { + settings->setHtmlSettingsProperty(KParts::HtmlSettingsInterface::JavaEnabled, checked); + } +} + +void SettingsPlugin::toggleJavascript(bool checked) +{ + KParts::HtmlSettingsInterface *settings = settingsInterfaceFor(parent()); + if (settings) { + settings->setHtmlSettingsProperty(KParts::HtmlSettingsInterface::JavascriptEnabled, checked); + } +} + +void SettingsPlugin::toggleCookies(bool checked) +{ + KParts::ReadOnlyPart *part = qobject_cast(parent()); + if (part) { + const QString advice((checked ? QStringLiteral("Accept") : QStringLiteral("Reject"))); + + // TODO generate interface from the installed org.kde.KCookieServer.xml file + // but not until 4.3 is released, since 4.2 had "void setDomainAdvice" + // while 4.3 has "bool setDomainAdvice". + + QDBusInterface kded(QStringLiteral("org.kde.kded5"), + QStringLiteral("/modules/kcookiejar"), + QStringLiteral("org.kde.KCookieServer")); + QDBusReply reply = kded.call(QStringLiteral("setDomainAdvice"), part->url().url(), advice); + + if (!reply.isValid()) + KMessageBox::sorry(part->widget(), + i18n("The cookie setting could not be changed, because the " + "cookie daemon could not be contacted."), + i18nc("@title:window", "Cookie Settings Unavailable")); + } +} + +void SettingsPlugin::togglePlugins(bool checked) +{ + KParts::HtmlSettingsInterface *settings = settingsInterfaceFor(parent()); + if (settings) { + settings->setHtmlSettingsProperty(KParts::HtmlSettingsInterface::PluginsEnabled, checked); + } +} + +void SettingsPlugin::toggleImageLoading(bool checked) +{ + KParts::HtmlSettingsInterface *settings = settingsInterfaceFor(parent()); + if (settings) { + settings->setHtmlSettingsProperty(KParts::HtmlSettingsInterface::AutoLoadImages, checked); + } +} + +bool SettingsPlugin::cookiesEnabled(const QString &url) +{ + QDBusInterface kded(QStringLiteral("org.kde.kded5"), + QStringLiteral("/modules/kcookiejar"), + QStringLiteral("org.kde.KCookieServer")); + QDBusReply reply = kded.call(QStringLiteral("getDomainAdvice"), url); + + bool enabled = false; + + if (reply.isValid()) { + QString advice = reply; + enabled = (advice == QLatin1String("Accept")); + if (!enabled && advice == QLatin1String("Dunno")) { + // TODO, check the global setting via dcop + KConfig _kc(QStringLiteral("kcookiejarrc"), KConfig::NoGlobals); + KConfigGroup kc(&_kc, "Cookie Policy"); + enabled = (kc.readEntry("CookieGlobalAdvice", "Reject") == QLatin1String("Accept")); + } + } + + return enabled; +} + +// +// sync with kcontrol/kio/ksaveioconfig.* ! +// + +void SettingsPlugin::toggleProxy(bool checked) +{ + KConfigGroup grp(mConfig, QString()); + int type; + + if (checked) { + type = grp.readEntry("SavedProxyType", static_cast(KProtocolManager::ManualProxy)); + } else { + grp.writeEntry("SavedProxyType", static_cast(KProtocolManager::proxyType())); + type = KProtocolManager::NoProxy; + } + + KConfig _config(QStringLiteral("kioslaverc"), KConfig::NoGlobals); + KConfigGroup config(&_config, "Proxy Settings"); + config.writeEntry("ProxyType", type); + + actionCollection()->action(QStringLiteral("useproxy"))->setChecked(checked); + updateIOSlaves(); +} + +void SettingsPlugin::toggleCache(bool checked) +{ + KConfig config(QStringLiteral("kio_httprc"), KConfig::NoGlobals); + KConfigGroup grp(&config, QString()); + grp.writeEntry("UseCache", checked); + actionCollection()->action(QStringLiteral("usecache"))->setChecked(checked); + + updateIOSlaves(); +} + +void SettingsPlugin::cachePolicyChanged(int p) +{ + QString policy; + + switch (p) { + case 0: + policy = KIO::getCacheControlString(KIO::CC_Verify); + break; + case 1: + policy = KIO::getCacheControlString(KIO::CC_Cache); + break; + case 2: + policy = KIO::getCacheControlString(KIO::CC_CacheOnly); + break; + }; + + if (!policy.isEmpty()) { + KConfig config(QStringLiteral("kio_httprc"), KConfig::NoGlobals); + KConfigGroup grp(&config, QString()); + grp.writeEntry("cache", policy); + + updateIOSlaves(); + } +} + +void SettingsPlugin::updateIOSlaves() +{ + QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KIO/Scheduler"), + QStringLiteral("org.kde.KIO.Scheduler"), + QStringLiteral("reparseSlaveConfiguration")); + message << QString(); + QDBusConnection::sessionBus().send(message); +} + +#include "settingsplugin.moc" diff --git a/plugins/khtmlsettingsplugin/settingsplugin.h b/plugins/khtmlsettingsplugin/settingsplugin.h new file mode 100644 index 0000000..df3c3bd --- /dev/null +++ b/plugins/khtmlsettingsplugin/settingsplugin.h @@ -0,0 +1,55 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SETTINGS_PLUGIN +#define SETTINGS_PLUGIN + +#include + +class KConfig; + +class SettingsPlugin : public KParts::Plugin +{ + Q_OBJECT +public: + SettingsPlugin(QObject *parent, + const QVariantList &); + ~SettingsPlugin() override; + +private: + bool cookiesEnabled(const QString &url); + void updateIOSlaves(); + +private slots: + void toggleJavascript(bool checked); + void toggleJava(bool checked); + void toggleCookies(bool checked); + void togglePlugins(bool checked); + void toggleImageLoading(bool checked); + void toggleProxy(bool checked); + void toggleCache(bool checked); + void cachePolicyChanged(int p); + + void showPopup(); + +private: + KConfig *mConfig; +}; + +#endif // SETTINGS_PLUGIN diff --git a/plugins/kimgalleryplugin/16-actions-imagegallery.png b/plugins/kimgalleryplugin/16-actions-imagegallery.png new file mode 100644 index 0000000000000000000000000000000000000000..b30485db9d5dd160e2555942df7e369a48ceea98 GIT binary patch literal 871 zcmV-t1DO1YP)Gt4H?49}n8J zEg$F;XRDkKlv4E6YK;YJYzpOxL#Ld=VHa>-cWL0s9dLKwyYJoi>l4SETeJ201Kv+Q zAD$%=SzT6EhRPGZ-HUqe>#7C-k$;g$tSirCc72nZ+v+`as&zMy{d@>zbL+acD;|9z zfWTAEpLditHEq}{%VqC^H5<}snwIS7NPkdQyS-FRezED-ZvS6f-|yTG7_)&RM;6R& zY+S#yxOnkCRV~ajG8RmV5GcVk7oaFP=+U!`gab^6>o2TYy{Z{NP9|4cLm|gU1qI7? zS+dvIGe!~j9~LsHTX~QW2s{L2sI~Wy3J-I*_cK1JkG`&|swI_5#pOW2>8hw$u`wRY zr|aHYzVpIV95Ny$93+)9RUzMo=>~0s$Qv& z=`Doie7s>Fni*$Q8^!LEI52R6iQpvF)fL?G`!R=OocZwc>l@!}s1X6f<+`|E6g2}q zOmfE0Sa^Wb!)MX|{Dp%9$B6ioG*!PtD6|M^rje@B-KYhQmu)tib#{gR{vAJ*m+yG{ z$9vPby#1u3I_2XcW5ychh>Ov6f$1rY_ueYRxg>}FV47gZms@57Tbm0VUmZPs)AOK7 z$;-|n8j~0sPaz5>!I(iXMQELTm6rVVb6q}aLi_A!aahKAx3HEW9&sre1BUGnOn zfHY5J(jt<{5h%u>Muru6@KSDAe^DO1d$H%Y0f8qhagEX)YJJ*yqV(XRji002ovPDHLkV1g|Co#Frh literal 0 HcmV?d00001 diff --git a/plugins/kimgalleryplugin/22-actions-imagegallery.png b/plugins/kimgalleryplugin/22-actions-imagegallery.png new file mode 100644 index 0000000000000000000000000000000000000000..debb7f4c918ff54bc38d9532a3f116530afa1014 GIT binary patch literal 1438 zcmV;P1!4M$P)K|J2U3=KK- zHXEMu#YdnfhFY5Yj;amVMdDvbBXE~%+^W}rVmKcdW0Yf3lAKyiEejf#%RRXgM+_IN+PN;D?jZ{ z@#Li&!~UyoFXzH88qaXy0w|Bi)Mc@}@E%23ULgp52|xhgKoCmu@L}hNSFZG-y1LvX z=lv}-Veh^>lAOAB{oYkU0FPZX_UP}o$~!xoEA)E(J7r~#^Au$)1}I7tX-JY1qF?|o zn4#B~JB}Y$T_*SqT1ZdIQ(P-b_IFO`&3+c^>z3;>LfzfHcz~wKhKtS3rhe!e?;QnyowC_nPIw#P~LL(ZS$}@_e2- zYc$rrPm(niAPy+AoC&F%3jUZJ;S7x(fj~43MB;#w20He~P{fR2Jr>1xv!}7mmBLw> zsH~{4IRLn@i(XsPd~)z$&v{9r$!tcAAYY08Sp|X#Ak6}T2!H@c05S?FH3~RF-N#OD z8J~MjAgHK=6!c=jBU6*4ya&JlcF`*)AH98RIv$T_DW8wc zs#H7MPG{X2npP@!)`BXn3H1sd>G&*&>?-2P3B+3S0IxjM`qTdKs`u0hJtucaIfgpFxFDca~%d z;ppkjqBEIP46ynz*5Run+3 zEkHwq3Egda)Y_Gpj1ed+5EMlP;#~@lg~J?|N^FG=9kQQN$U1dqc|BgWH=*5J4VB6Y zgT?@>Q3kD+0?*LkDhiOP)F4JtFiIjGt>$rSEQ7<1S|ykCxhU-6@n*Ihb&SbT+u1!I zG?5P;@dzdbfR=y)5*aOtjE;n$CLqsCu*7-Ph!Xb6L^v#>)Yl@gdRZblJ~qBaV-J>v zI6fY`T2tpaSz@SdvgqXyC<0MVLRJt_2mv;UfQ2EUGl>9~5);utd@JnVn4R@6FD<+0 zMn->~T3lS5r}2dEe^~OJJVo9%73CY|0u-rJNw5}5FfkI;GLDNzLb-*p*>#s|(dG4d zClc|*bSNBIotvABq|@mP02Y8m;|cyilnsV9m#P}_Ij3DL(8yxaqU%v$Y$LidG4XJ6 zczAefX=!OvlB6{N2>=qFfyUFs;hR6th{EQB-Y)jw_1h2ce>32}G&{dOv$eGq1CRs2 s<2jKHHH78Ji{!a|X4vpQAn~0307QdKoeI{mumAu607*qoM6N<$g00MlwEzGB literal 0 HcmV?d00001 diff --git a/plugins/kimgalleryplugin/CMakeLists.txt b/plugins/kimgalleryplugin/CMakeLists.txt new file mode 100644 index 0000000..87c67a8 --- /dev/null +++ b/plugins/kimgalleryplugin/CMakeLists.txt @@ -0,0 +1,22 @@ +########### next target ############### +add_definitions(-DTRANSLATION_DOMAIN=\"imgalleryplugin\") +set(kimgallery_PART_SRCS imgalleryplugin.cpp imgallerydialog.cpp ) + +add_library(kimgallery MODULE ${kimgallery_PART_SRCS}) + + + +target_link_libraries(kimgallery KF5::Parts KF5::KDELibs4Support) + +install(TARGETS kimgallery DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### + +install( FILES kimgalleryplugin.rc kimgalleryplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/dolphinpart/kpartplugins ) + +set(kimagegallery_ICONS 16-actions-imagegallery.png 22-actions-imagegallery.png) + +ecm_install_icons(ICONS ${kimagegallery_ICONS} DESTINATION ${KDE_INSTALL_ICONDIR} THEME hicolor) + + diff --git a/plugins/kimgalleryplugin/Messages.sh b/plugins/kimgalleryplugin/Messages.sh new file mode 100644 index 0000000..7017c26 --- /dev/null +++ b/plugins/kimgalleryplugin/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/imgalleryplugin.pot diff --git a/plugins/kimgalleryplugin/imgallerydialog.cpp b/plugins/kimgalleryplugin/imgallerydialog.cpp new file mode 100644 index 0000000..90e70f9 --- /dev/null +++ b/plugins/kimgalleryplugin/imgallerydialog.cpp @@ -0,0 +1,482 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl +Andreas Schlapbach + +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 "imgallerydialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +KIGPDialog::KIGPDialog(QWidget *parent, const QString &path) + : KPageDialog(parent) +{ + setStandardButtons(QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttonBox()->button(QDialogButtonBox::Ok)->setDefault(true); + setModal(true); + setFaceType(List); + + m_path = path; + setWindowTitle(i18nc("@title:window", "Create Image Gallery")); + KGuiItem::assign(buttonBox()->button(QDialogButtonBox::Ok), KGuiItem(i18n("Create"), QStringLiteral("imagegallery"))); + m_config = new KConfig(QStringLiteral("kimgallerypluginrc"), KConfig::NoGlobals); + setupLookPage(path); + setupDirectoryPage(path); + setupThumbnailPage(path); + connect(buttonBox()->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(slotDefault())); +} + +void KIGPDialog::slotDefault() +{ + m_title->setText(i18n("Image Gallery for %1", m_path)); + m_imagesPerRow->setValue(4); + m_imageName->setChecked(true); + m_imageSize->setChecked(false); + m_imageProperty->setChecked(false); + m_fontName->setItemText(m_fontName->currentIndex(), QFontDatabase::systemFont(QFontDatabase::GeneralFont).family()); + m_fontSize->setValue(14); + m_foregroundColor->setColor(QColor(QStringLiteral("#d0ffd0"))); + m_backgroundColor->setColor(QColor(QStringLiteral("#333333"))); + + m_imageNameReq->setUrl(QUrl::fromLocalFile(m_path + "images.html")); + m_recurseSubDir->setChecked(false); + m_recursionLevel->setEnabled(false); + m_recursionLevel->setValue(0); + m_copyOriginalFiles->setChecked(false); + m_useCommentFile->setChecked(false); + m_commentFileReq->setUrl(QUrl::fromLocalFile(m_path + "comments")); + m_commentFileReq->setEnabled(false); + + m_imageFormat->setItemText(m_imageFormat->currentIndex(), QStringLiteral("JPEG")); + m_thumbnailSize->setValue(140); + m_colorDepthSet->setChecked(false); + m_colorDepth->setItemText(m_colorDepth->currentIndex(), QStringLiteral("8")); +} + +void KIGPDialog::setupLookPage(const QString &path) +{ + QFrame *page = new QFrame(); + KPageWidgetItem *pageItem = new KPageWidgetItem(page, i18n("Look")); + pageItem->setHeader(i18n("Page Look")); + pageItem->setIcon(QIcon::fromTheme("fill-color")); + addPage(pageItem); + + KConfigGroup look = m_config->group("Look"); + QVBoxLayout *vlay = new QVBoxLayout(page); + vlay->setContentsMargins(0, 0, 0, 0); + + QLabel *label = new QLabel(i18n("&Page title:"), page); + vlay->addWidget(label); + + m_title = new QLineEdit(i18n("Image Gallery for %1", path), page); + vlay->addWidget(m_title); + label->setBuddy(m_title); + + m_imagesPerRow = new KIntNumInput(look.readEntry("ImagesPerRow", 4), page); + m_imagesPerRow->setRange(1, 8, 1); + m_imagesPerRow->setSliderEnabled(true); + m_imagesPerRow->setLabel(i18n("I&mages per row:")); + vlay->addWidget(m_imagesPerRow); + + QGridLayout *grid = new QGridLayout(); + grid->setContentsMargins(2, 2, 2, 2); + grid->setSpacing(2); + vlay->addLayout(grid); + + m_imageName = new QCheckBox(i18n("Show image file &name"), page); + m_imageName->setChecked(look.readEntry("ImageName", true)); + grid->addWidget(m_imageName, 0, 0); + + m_imageSize = new QCheckBox(i18n("Show image file &size"), page); + m_imageSize->setChecked(look.readEntry("ImageSize", false)); + grid->addWidget(m_imageSize, 0, 1); + + m_imageProperty = new QCheckBox(i18n("Show image &dimensions"), page); + m_imageProperty->setChecked(look.readEntry("ImageProperty", false)); + grid->addWidget(m_imageProperty, 1, 0); + + QHBoxLayout *hlay11 = new QHBoxLayout(); + vlay->addLayout(hlay11); + + m_fontName = new QComboBox(page); + QStringList standardFonts; + KFontChooser::getFontList(standardFonts, 0); + m_fontName->addItems(standardFonts); + m_fontName->setItemText(m_fontName->currentIndex(), look.readEntry("FontName", QFontDatabase::systemFont(QFontDatabase::GeneralFont).family())); + + label = new QLabel(i18n("Fon&t name:"), page); + label->setBuddy(m_fontName); + hlay11->addWidget(label); + hlay11->addStretch(1); + hlay11->addWidget(m_fontName); + + QHBoxLayout *hlay12 = new QHBoxLayout(); + vlay->addLayout(hlay12); + + m_fontSize = new QSpinBox(page); + m_fontSize->setMinimum(6); + m_fontSize->setMaximum(15); + m_fontSize->setSingleStep(1); + m_fontSize->setValue(look.readEntry("FontSize", 14)); + + label = new QLabel(i18n("Font si&ze:"), page); + label->setBuddy(m_fontSize); + hlay12->addWidget(label); + hlay12->addStretch(1); + hlay12->addWidget(m_fontSize); + + QHBoxLayout *hlay1 = new QHBoxLayout(); + vlay->addLayout(hlay1); + + m_foregroundColor = new KColorButton(page); + m_foregroundColor->setColor(QColor(look.readEntry("ForegroundColor", "#d0ffd0"))); + + label = new QLabel(i18n("&Foreground color:"), page); + label->setBuddy(m_foregroundColor); + hlay1->addWidget(label); + hlay1->addStretch(1); + hlay1->addWidget(m_foregroundColor); + + QHBoxLayout *hlay2 = new QHBoxLayout(); + vlay->addLayout(hlay2); + + m_backgroundColor = new KColorButton(page); + m_backgroundColor->setColor(QColor(look.readEntry("BackgroundColor", "#333333"))); + + label = new QLabel(i18n("&Background color:"), page); + hlay2->addWidget(label); + label->setBuddy(m_backgroundColor); + hlay2->addStretch(1); + hlay2->addWidget(m_backgroundColor); + + vlay->addStretch(1); +} + +void KIGPDialog::setupDirectoryPage(const QString &path) +{ + QFrame *page = new QFrame(); + KPageWidgetItem *pageItem = new KPageWidgetItem(page, i18n("Folders")); + pageItem->setHeader(i18n("Folders")); + pageItem->setIcon(QIcon::fromTheme("folder")); + addPage(pageItem); + + KConfigGroup group = m_config->group("Directory"); + QVBoxLayout *dvlay = new QVBoxLayout(page); + dvlay->setContentsMargins(0, 0, 0, 0); + + QLabel *label; + label = new QLabel(i18n("&Save to HTML file:"), page); + dvlay->addWidget(label); + QString whatsThis; + whatsThis = i18n("

The name of the HTML file this gallery will be saved to.

"); + label->setWhatsThis(whatsThis); + + m_imageNameReq = new KUrlRequester(QUrl::fromLocalFile(QString(path + "images.html")), page); + label->setBuddy(m_imageNameReq); + dvlay->addWidget(m_imageNameReq); + connect(m_imageNameReq, SIGNAL(textChanged(QString)), + this, SLOT(imageUrlChanged(QString))); + m_imageNameReq->setWhatsThis(whatsThis); + + const bool recurseSubDir = group.readEntry("RecurseSubDirectories", false); + m_recurseSubDir = new QCheckBox(i18n("&Recurse subfolders"), page); + m_recurseSubDir->setChecked(recurseSubDir); + whatsThis = i18n("

Whether subfolders should be included for the " + "image gallery creation or not.

"); + m_recurseSubDir->setWhatsThis(whatsThis); + + const int recursionLevel = group.readEntry("RecursionLevel", 0); + m_recursionLevel = new KIntNumInput(recursionLevel, page); + m_recursionLevel->setRange(0, 99, 1); + m_recursionLevel->setSliderEnabled(true); + m_recursionLevel->setLabel(i18n("Rec&ursion depth:")); + if (recursionLevel == 0) { + m_recursionLevel->setSpecialValueText(i18n("Endless")); + } + m_recursionLevel->setEnabled(recurseSubDir); + whatsThis = i18n("

You can limit the number of folders the " + "image gallery creator will traverse to by setting an " + "upper bound for the recursion depth.

"); + m_recursionLevel->setWhatsThis(whatsThis); + + connect(m_recurseSubDir, SIGNAL(toggled(bool)), + m_recursionLevel, SLOT(setEnabled(bool))); + + dvlay->addWidget(m_recurseSubDir); + dvlay->addWidget(m_recursionLevel); + + m_copyOriginalFiles = new QCheckBox(i18n("Copy or&iginal files"), page); + m_copyOriginalFiles->setChecked(group.readEntry("CopyOriginalFiles", false)); + dvlay->addWidget(m_copyOriginalFiles); + whatsThis = i18n("

This makes a copy of all images and the gallery will refer " + "to these copies instead of the original images.

"); + m_copyOriginalFiles->setWhatsThis(whatsThis); + + const bool useCommentFile = group.readEntry("UseCommentFile", false); + m_useCommentFile = new QCheckBox(i18n("Use &comment file"), page); + m_useCommentFile->setChecked(useCommentFile); + dvlay->addWidget(m_useCommentFile); + + whatsThis = i18n("

If you enable this option you can specify " + "a comment file which will be used for generating " + "subtitles for the images.

" + "

For details about the file format please see " + "the \"What's This?\" help below.

"); + m_useCommentFile->setWhatsThis(whatsThis); + + label = new QLabel(i18n("Comments &file:"), page); + label->setEnabled(useCommentFile); + dvlay->addWidget(label); + whatsThis = i18n("

You can specify the name of the comment file here. " + "The comment file contains the subtitles for the images. " + "The format of this file is:

" + "

FILENAME1:" + "
Description" + "
" + "
FILENAME2:" + "
Description" + "
" + "
and so on

"); + label->setWhatsThis(whatsThis); + + m_commentFileReq = new KUrlRequester(QUrl::fromLocalFile(QString(path + "comments")), page); + m_commentFileReq->setEnabled(useCommentFile); + label->setBuddy(m_commentFileReq); + dvlay->addWidget(m_commentFileReq); + m_commentFileReq->setWhatsThis(whatsThis); + + connect(m_useCommentFile, SIGNAL(toggled(bool)), + label, SLOT(setEnabled(bool))); + connect(m_useCommentFile, SIGNAL(toggled(bool)), + m_commentFileReq, SLOT(setEnabled(bool))); + + dvlay->addStretch(1); +} + +void KIGPDialog::setupThumbnailPage(const QString &path) +{ + Q_UNUSED(path); + + QFrame *page = new QFrame(); + KPageWidgetItem *pageItem = new KPageWidgetItem(page, i18n("Thumbnails")); + pageItem->setHeader(i18n("Thumbnails")); + pageItem->setIcon(QIcon::fromTheme("view-preview")); + addPage(pageItem); + + KConfigGroup group = m_config->group("Thumbnails"); + QLabel *label; + + QVBoxLayout *vlay = new QVBoxLayout(page); + vlay->setContentsMargins(0, 0, 0, 0); + + QHBoxLayout *hlay3 = new QHBoxLayout(); + vlay->addLayout(hlay3); + + m_imageFormat = new QComboBox(page); + QStringList lstImgageFormat; + lstImgageFormat << QStringLiteral("JPEG") << QStringLiteral("PNG"); + m_imageFormat->addItems(lstImgageFormat); + m_imageFormat->setItemText(m_imageFormat->currentIndex(), group.readEntry("ImageFormat", "JPEG")); + + label = new QLabel(i18n("Image format f&or the thumbnails:"), page); + hlay3->addWidget(label); + label->setBuddy(m_imageFormat); + hlay3->addStretch(1); + hlay3->addWidget(m_imageFormat); + + m_thumbnailSize = new KIntNumInput(group.readEntry("ThumbnailSize", 140), page); + m_thumbnailSize->setRange(10, 1000, 1); + m_thumbnailSize->setLabel(i18n("Thumbnail size:")); + m_thumbnailSize->setSliderEnabled(true); + vlay->addWidget(m_thumbnailSize); + + QGridLayout *grid = new QGridLayout(); + grid->setContentsMargins(2, 2, 2, 2); + grid->setSpacing(2); + vlay->addLayout(grid); + + QHBoxLayout *hlay4 = new QHBoxLayout(); + vlay->addLayout(hlay4); + const bool colorDepthSet = group.readEntry("ColorDepthSet", false); + m_colorDepthSet = new QCheckBox(i18n("&Set different color depth:"), page); + m_colorDepthSet->setChecked(colorDepthSet); + hlay4->addWidget(m_colorDepthSet); + + m_colorDepth = new QComboBox(page); + QStringList lst; + lst << QStringLiteral("1") << QStringLiteral("8") << QStringLiteral("16") << QStringLiteral("32"); + m_colorDepth->addItems(lst); + m_colorDepth->setItemText(m_colorDepth->currentIndex(), group.readEntry("ColorDepth", "8")); + m_colorDepth->setEnabled(colorDepthSet); + hlay4->addWidget(m_colorDepth); + + connect(m_colorDepthSet, SIGNAL(toggled(bool)), + m_colorDepth, SLOT(setEnabled(bool))); + + vlay->addStretch(1); + +} + +void KIGPDialog::writeConfig() +{ + KConfigGroup group = m_config->group("Look"); + group.writeEntry("ImagesPerRow", getImagesPerRow()); + group.writeEntry("ImageName", printImageName()); + group.writeEntry("ImageSize", printImageSize()); + group.writeEntry("ImageProperty", printImageProperty()); + group.writeEntry("FontName", getFontName()); + group.writeEntry("FontSize", getFontSize()); + group.writeEntry("ForegroundColor", getForegroundColor().name()); + group.writeEntry("BackgroundColor", getBackgroundColor().name()); + + group = m_config->group("Directory"); + group.writeEntry("RecurseSubDirectories", recurseSubDirectories()); + group.writeEntry("RecursionLevel", recursionLevel()); + group.writeEntry("CopyOriginalFiles", copyOriginalFiles()); + group.writeEntry("UseCommentFile", useCommentFile()); + + group = m_config->group("Thumbnails"); + group.writeEntry("ThumbnailSize", getThumbnailSize()); + group.writeEntry("ColorDepth", getColorDepth()); + group.writeEntry("ColorDepthSet", colorDepthSet()); + group.writeEntry("ImageFormat", getImageFormat()); + group.sync(); +} + +KIGPDialog::~KIGPDialog() +{ + delete m_config; +} + +void KIGPDialog::imageUrlChanged(const QString &url) +{ + buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(!url.isEmpty()); +} + +bool KIGPDialog::printImageName() const +{ + return m_imageName->isChecked(); +} + +bool KIGPDialog::printImageSize() const +{ + return m_imageSize->isChecked(); +} + +bool KIGPDialog::printImageProperty() const +{ + return m_imageProperty->isChecked(); +} + +bool KIGPDialog::recurseSubDirectories() const +{ + return m_recurseSubDir->isChecked(); +} + +int KIGPDialog::recursionLevel() const +{ + return m_recursionLevel->value(); +} + +bool KIGPDialog::copyOriginalFiles() const +{ + return m_copyOriginalFiles->isChecked(); +} + +bool KIGPDialog::useCommentFile() const +{ + return m_useCommentFile->isChecked(); +} + +int KIGPDialog::getImagesPerRow() const +{ + return m_imagesPerRow->value(); +} + +int KIGPDialog::getThumbnailSize() const +{ + return m_thumbnailSize->value(); +} + +int KIGPDialog::getColorDepth() const +{ + return m_colorDepth->currentText().toInt(); +} + +bool KIGPDialog::colorDepthSet() const +{ + return m_colorDepthSet->isChecked(); +} + +const QString KIGPDialog::getTitle() const +{ + return m_title->text(); +} + +const QUrl KIGPDialog::getImageUrl() const +{ + return m_imageNameReq->url(); +} + +const QString KIGPDialog::getCommentFile() const +{ + return m_commentFileReq->url().toLocalFile(); +} + +const QString KIGPDialog::getFontName() const +{ + return m_fontName->currentText(); +} + +const QString KIGPDialog::getFontSize() const +{ + return m_fontSize->text(); +} + +const QColor KIGPDialog::getBackgroundColor() const +{ + return m_backgroundColor->color(); +} + +const QColor KIGPDialog::getForegroundColor() const +{ + return m_foregroundColor->color(); +} + +const QString KIGPDialog::getImageFormat() const +{ + return m_imageFormat->currentText(); +} diff --git a/plugins/kimgalleryplugin/imgallerydialog.h b/plugins/kimgalleryplugin/imgallerydialog.h new file mode 100644 index 0000000..141bbaa --- /dev/null +++ b/plugins/kimgalleryplugin/imgallerydialog.h @@ -0,0 +1,110 @@ +/* This file is part of the KDE project + + Copyright (C) 2001, 2003 Lukas Tinkl + Andreas Schlapbach + + 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 KONQ_PLUGINS_IMGALLERYDIALOG_H +#define KONQ_PLUGINS_IMGALLERYDIALOG_H + +#include + +class KIntNumInput; +class QCheckBox; +class QLineEdit; +class KUrlRequester; +class QSpinBox; +class KColorButton; +class KConfig; +class QComboBox; + +typedef QMap CommentMap; + +class KIGPDialog : public KPageDialog +{ + Q_OBJECT + +public: + explicit KIGPDialog(QWidget *parent, const QString &path); + ~KIGPDialog() override; + + bool isDialogOk() const; + bool printImageName() const; + bool printImageSize() const; + bool printImageProperty() const; + bool copyOriginalFiles() const; + bool useCommentFile() const; + bool recurseSubDirectories() const; + int recursionLevel() const; + bool colorDepthSet() const; + + int getImagesPerRow() const; + int getThumbnailSize() const; + int getColorDepth() const; + + const QString getTitle() const; + const QUrl getImageUrl() const; + const QString getCommentFile() const; + const QString getFontName() const; + const QString getFontSize() const; + + const QColor getBackgroundColor() const; + const QColor getForegroundColor() const; + + const QString getImageFormat() const; + + void writeConfig(); +protected slots: + void imageUrlChanged(const QString &); + void slotDefault(); + +private: + KColorButton *m_foregroundColor; + KColorButton *m_backgroundColor; + + QLineEdit *m_title; + QString m_path; + + KIntNumInput *m_imagesPerRow; + KIntNumInput *m_thumbnailSize; + KIntNumInput *m_recursionLevel; + QSpinBox *m_fontSize; + + QCheckBox *m_copyOriginalFiles; + QCheckBox *m_imageName; + QCheckBox *m_imageSize; + QCheckBox *m_imageProperty; + QCheckBox *m_useCommentFile; + QCheckBox *m_recurseSubDir; + QCheckBox *m_colorDepthSet; + + QComboBox *m_fontName; + QComboBox *m_imageFormat; + QComboBox *m_colorDepth; + + KUrlRequester *m_imageNameReq; + KUrlRequester *m_commentFileReq; + + KConfig *m_config; + +private: + void setupLookPage(const QString &path); + void setupDirectoryPage(const QString &path); + void setupThumbnailPage(const QString &path); +}; + +#endif // KONQ_PLUGINS_IMGALLERYDIALOG_H diff --git a/plugins/kimgalleryplugin/imgalleryplugin.cpp b/plugins/kimgalleryplugin/imgalleryplugin.cpp new file mode 100644 index 0000000..4ad7c00 --- /dev/null +++ b/plugins/kimgalleryplugin/imgalleryplugin.cpp @@ -0,0 +1,541 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl +Andreas Schlapbach + +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 "imgalleryplugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "imgallerydialog.h" + +//KDELibs4Support +#include + +K_PLUGIN_FACTORY(KImGalleryPluginFactory, registerPlugin();) + +static QString directory(const QUrl &url) { + return url.adjusted(QUrl::StripTrailingSlash).adjusted(QUrl::RemoveFilename).toLocalFile(); +} + +KImGalleryPlugin::KImGalleryPlugin(QObject *parent, const QVariantList &) + : KParts::Plugin(parent), m_commentMap(nullptr) +{ + QAction *a = actionCollection()->addAction(QStringLiteral("create_img_gallery")); + a->setText(i18n("&Create Image Gallery...")); + a->setIcon(QIcon::fromTheme(QStringLiteral("imagegallery"))); + actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL + Qt::Key_I)); + connect(a, SIGNAL(triggered()), this, SLOT(slotExecute())); +} + +void KImGalleryPlugin::slotExecute() +{ + m_progressDlg = nullptr; + if (!parent()) { + KMessageBox::sorry(nullptr, i18n("Could not create the plugin, please report a bug.")); + return; + } + m_part = qobject_cast(parent()); + + if (!m_part || !m_part->url().isLocalFile()) { //TODO support remote URLs too? + KMessageBox::sorry(m_part->widget(), i18n("Creating an image gallery works only on local folders.")); + return; + } + + QString path = m_part->url().adjusted(QUrl::StripTrailingSlash).toLocalFile() + '/'; + m_configDlg = new KIGPDialog(m_part->widget(), path); + + if (m_configDlg->exec() == QDialog::Accepted) { + kDebug(90170) << "dialog is ok"; + m_configDlg->writeConfig(); + m_copyFiles = m_configDlg->copyOriginalFiles(); + m_recurseSubDirectories = m_configDlg->recurseSubDirectories(); + m_useCommentFile = m_configDlg->useCommentFile(); + m_imagesPerRow = m_configDlg->getImagesPerRow(); + + QUrl url(m_configDlg->getImageUrl()); + if (!url.isEmpty() && url.isValid()) { + m_progressDlg = new QProgressDialog(m_part->widget()); + QObject::connect(m_progressDlg, SIGNAL(canceled()), this, SLOT(slotCancelled())); + + m_progressDlg->setLabelText(i18n("Creating thumbnails")); + QPushButton *button = new QPushButton(m_progressDlg); + KGuiItem::assign(button, KStandardGuiItem::cancel()); + m_progressDlg->setCancelButton(button); + m_cancelled = false; + m_progressDlg->show(); + if (createHtml(url, m_part->url().path(), m_configDlg->recursionLevel() > 0 ? m_configDlg->recursionLevel() + 1 : 0, m_configDlg->getImageFormat())) { + KToolInvocation::invokeBrowser(url.url()); // Open a browser to show the result + } else { + deleteCancelledGallery(url, m_part->url().path(), m_configDlg->recursionLevel() > 0 ? m_configDlg->recursionLevel() + 1 : 0, m_configDlg->getImageFormat()); + } + } + } + delete m_progressDlg; +} + +bool KImGalleryPlugin::createDirectory(const QDir &dir, const QString &imgGalleryDir, const QString &dirName) +{ + QDir thumb_dir(dir); + + if (!thumb_dir.exists()) { + thumb_dir.setPath(imgGalleryDir); + if (!(thumb_dir.mkdir(dirName/*, false*/))) { + KMessageBox::sorry(m_part->widget(), i18n("Could not create folder: %1", thumb_dir.path())); + return false; + } else { + thumb_dir.setPath(imgGalleryDir + '/' + dirName + '/'); + return true; + } + } else { + return true; + } +} + +void KImGalleryPlugin::createHead(QTextStream &stream) +{ + const QString chsetName = QTextCodec::codecForLocale()->name(); + + stream << "" << endl; + stream << "" << endl; + stream << "" << endl; + stream << "" << endl; + stream << "" << m_configDlg->getTitle().toHtmlEscaped() << "" << endl; + stream << "" << endl; + stream << "" << endl; + createCSSSection(stream); + stream << "" << endl; +} + +void KImGalleryPlugin::createCSSSection(QTextStream &stream) +{ + const QString backgroundColor = m_configDlg->getBackgroundColor().name(); + const QString foregroundColor = m_configDlg->getForegroundColor().name(); + //adding a touch of style + stream << "" << endl; +} + +QString KImGalleryPlugin::extension(const QString &imageFormat) +{ + if (imageFormat == QLatin1String("PNG")) { + return QStringLiteral(".png"); + } + if (imageFormat == QLatin1String("JPEG")) { + return QStringLiteral(".jpg"); + } + Q_ASSERT(false); + return QString(); +} + +void KImGalleryPlugin::createBody(QTextStream &stream, const QString &sourceDirName, const QStringList &subDirList, + const QDir &imageDir, const QUrl &url, const QString &imageFormat) +{ + int numOfImages = imageDir.count(); + const QString imgGalleryDir = directory(url); + const QString today(KLocale::global()->formatDate(QDate::currentDate())); + + stream << "\n

" << m_configDlg->getTitle().toHtmlEscaped() << "

" << endl; + stream << i18n("Number of images: %1", numOfImages) << "
" << endl; + stream << i18n("Created on: %1", today) << "

" << endl; + + stream << "
" << endl; + + if (m_recurseSubDirectories && subDirList.count() > 2) { //subDirList.count() is always >= 2 because of the "." and ".." directories + stream << i18n("Subfolders:") << "
" << endl; + for (QStringList::ConstIterator it = subDirList.constBegin(); it != subDirList.constEnd(); it++) { + if (*it == QLatin1String(".") || *it == QLatin1String("..")) { + continue; //disregard the "." and ".." directories + } + stream << "
" << *it << "
" << endl; + } + stream << "
" << endl; + } + + stream << "" << endl; + + //table with images + int imgIndex; + QFileInfo imginfo; + QPixmap imgProp; + for (imgIndex = 0; !m_cancelled && (imgIndex < numOfImages);) { + stream << "" << endl; + + for (int col = 0; !m_cancelled && (col < m_imagesPerRow) && (imgIndex < numOfImages); col++) { + const QString imgName = imageDir[imgIndex]; + + if (m_copyFiles) { + stream << "" << endl; + + m_progressDlg->setMaximum(numOfImages); + m_progressDlg->setValue(imgIndex); + qApp->processEvents(); + imgIndex++; + } + stream << "" << endl; + } + //close the HTML + stream << "
\n"; + } else { + stream << "\n"; + } + + if (createThumb(imgName, sourceDirName, imgGalleryDir, imageFormat)) { + const QString imgPath("thumbs/" + imgName + extension(imageFormat)); + stream << "\"""; + m_progressDlg->setLabelText(i18n("Created thumbnail for: \n%1", imgName)); + } else { + kDebug(90170) << "Creating thumbnail for " << imgName << " failed"; + m_progressDlg->setLabelText(i18n("Creating thumbnail for: \n%1\n failed", imgName)); + } + stream << "" << endl; + + if (m_configDlg->printImageName()) { + stream << "
" << imgName << "
" << endl; + } + + if (m_configDlg->printImageProperty()) { +#ifdef __GNUC__ +#warning "kde4: verify it : imageDir.absoluteFilePath(imgName,true)"; +#endif + imgProp.load(imageDir.absoluteFilePath(imgName)); + stream << "
" << imgProp.width() << " x " << imgProp.height() << "
" << endl; + } + + if (m_configDlg->printImageSize()) { + imginfo.setFile(imageDir, imgName); + stream << "
(" << (imginfo.size() / 1024) << " " << i18n("KiB") << ")" << "
" << endl; + } + + if (m_useCommentFile) { + QString imgComment = (*m_commentMap)[imgName]; + stream << "
" << imgComment.toHtmlEscaped() << "
" << endl; + } + stream << "
\n\n" << endl; +} + +bool KImGalleryPlugin::createHtml(const QUrl &url, const QString &sourceDirName, int recursionLevel, const QString &imageFormat) +{ + if (m_cancelled) { + return false; + } + + if (!parent() || !parent()->inherits("DolphinPart")) { + return false; + } + + QStringList subDirList; + if (m_recurseSubDirectories && (recursionLevel >= 0)) { //recursionLevel == 0 means endless + QDir toplevel_dir = QDir(sourceDirName); + toplevel_dir.setFilter(QDir::Dirs | QDir::Readable | QDir::Writable); + subDirList = toplevel_dir.entryList(); + + for (QStringList::ConstIterator it = subDirList.constBegin(); it != subDirList.constEnd() && !m_cancelled; it++) { + const QString currentDir = *it; + if (currentDir == QLatin1String(".") || currentDir == QLatin1String("..")) { + continue; //disregard the "." and ".." directories + } + QDir subDir = QDir(directory(url) + '/' + currentDir); + if (!subDir.exists()) { + subDir.setPath(directory(url)); + if (!(subDir.mkdir(currentDir/*, false*/))) { + KMessageBox::sorry(m_part->widget(), i18n("Could not create folder: %1", subDir.path())); + continue; + } else { + subDir.setPath(directory(url) + '/' + currentDir); + } + } + if (!createHtml(QUrl::fromLocalFile(subDir.path() + '/' + url.fileName()), sourceDirName + '/' + currentDir, + recursionLevel > 1 ? recursionLevel - 1 : 0, imageFormat)) { + return false; + } + } + } + + if (m_useCommentFile) { + loadCommentFile(); + } + + kDebug(90170) << "sourceDirName: " << sourceDirName; + //We're interested in only the patterns, so look for the first | + //#### perhaps an accessor should be added to KImageIO instead? + QString filter = KImageIO::pattern(KImageIO::Reading).section('|', 0, 0); + + QDir imageDir(sourceDirName, filter.toLatin1(), + QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::Readable); + + const QString imgGalleryDir = directory(url); + kDebug(90170) << "imgGalleryDir: " << imgGalleryDir; + + // Create the "thumbs" subdirectory if necessary + QDir thumb_dir(imgGalleryDir + QLatin1String("/thumbs/")); + if (createDirectory(thumb_dir, imgGalleryDir, QStringLiteral("thumbs")) == false) { + return false; + } + + // Create the "images" subdirectory if necessary + QDir images_dir(imgGalleryDir + QLatin1String("/images/")); + if (m_copyFiles) { + if (createDirectory(images_dir, imgGalleryDir, QStringLiteral("images")) == false) { + return false; + } + } + + QFile file(url.path()); + kDebug(90170) << "url.path(): " << url.path() << ", thumb_dir: " << thumb_dir.path() + << ", imageDir: " << imageDir.path() << endl; + + if (imageDir.exists() && file.open(QIODevice::WriteOnly)) { + QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForLocale()); + + createHead(stream); + createBody(stream, sourceDirName, subDirList, imageDir, url, imageFormat); //ugly + + file.close(); + + return !m_cancelled; + + } else { + QString path = url.toLocalFile(); + if (!path.endsWith("/")) { + path += '/'; + } + KMessageBox::sorry(m_part->widget(), i18n("Could not open file: %1", path)); + return false; + } +} + +void KImGalleryPlugin::deleteCancelledGallery(const QUrl &url, const QString &sourceDirName, int recursionLevel, const QString &imageFormat) +{ + if (m_recurseSubDirectories && (recursionLevel >= 0)) { + QStringList subDirList; + QDir toplevel_dir = QDir(sourceDirName); + toplevel_dir.setFilter(QDir::Dirs); + subDirList = toplevel_dir.entryList(); + + for (QStringList::ConstIterator it = subDirList.constBegin(); it != subDirList.constEnd(); it++) { + if (*it == QLatin1String(".") || *it == QLatin1String("..") || *it == QLatin1String("thumbs") || (m_copyFiles && *it == QLatin1String("images"))) { + continue; //disregard the "." and ".." directories + } + deleteCancelledGallery(QUrl::fromLocalFile(directory(url) + '/' + *it + '/' + url.fileName()), + sourceDirName + '/' + *it, + recursionLevel > 1 ? recursionLevel - 1 : 0, imageFormat); + } + } + + const QString imgGalleryDir = directory(url); + QDir thumb_dir(imgGalleryDir + QLatin1String("/thumbs/")); + QDir images_dir(imgGalleryDir + QLatin1String("/images/")); + QDir imageDir(sourceDirName, QStringLiteral("*.png *.PNG *.gif *.GIF *.jpg *.JPG *.jpeg *.JPEG *.bmp *.BMP"), + QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::Readable); + QFile file(url.path()); + + // Remove the image file .. + file.remove(); + // ..all the thumbnails .. + for (uint i = 0; i < imageDir.count(); i++) { + const QString imgName = imageDir[i]; + const QString imgNameFormat = imgName + extension(imageFormat); + bool isRemoved = thumb_dir.remove(imgNameFormat); + kDebug(90170) << "removing: " << thumb_dir.path() << "/" << imgNameFormat << "; " << isRemoved; + } + // ..and the thumb directory + thumb_dir.rmdir(thumb_dir.path()); + + // ..and the images directory if images were to be copied + if (m_copyFiles) { + for (uint i = 0; i < imageDir.count(); i++) { + const QString imgName = imageDir[i]; + bool isRemoved = images_dir.remove(imgName); + kDebug(90170) << "removing: " << images_dir.path() << "/" << imgName << "; " << isRemoved; + } + images_dir.rmdir(images_dir.path()); + } +} + +void KImGalleryPlugin::loadCommentFile() +{ + QFile file(m_configDlg->getCommentFile()); + if (file.open(QIODevice::ReadOnly)) { + kDebug(90170) << "File opened."; + + QTextStream *m_textStream = new QTextStream(&file); + m_textStream->setCodec(QTextCodec::codecForLocale()); + + delete m_commentMap; + m_commentMap = new CommentMap; + + QString picName, picComment, curLine, curLineStripped; + while (!m_textStream->atEnd()) { + curLine = m_textStream->readLine(); + curLineStripped = curLine.trimmed(); + // Lines starting with '#' are comment + if (!(curLineStripped.isEmpty()) && !curLineStripped.startsWith(QLatin1String("#"))) { + if (curLineStripped.endsWith(QLatin1String(":"))) { + picComment.clear(); + picName = curLineStripped.left(curLineStripped.length() - 1); + kDebug(90170) << "picName: " << picName; + } else { + do { + //kDebug(90170) << "picComment"; + picComment += curLine + '\n'; + curLine = m_textStream->readLine(); + } while (!m_textStream->atEnd() && !(curLine.trimmed().isEmpty()) && + !curLine.trimmed().startsWith(QLatin1String("#"))); + //kDebug(90170) << "Pic comment: " << picComment; + m_commentMap->insert(picName, picComment); + } + } + } + CommentMap::ConstIterator it; + for (it = m_commentMap->constBegin(); it != m_commentMap->constEnd(); ++it) { + kDebug(90170) << "picName: " << it.key() << ", picComment: " << it.value(); + } + file.close(); + kDebug(90170) << "File closed."; + delete m_textStream; + } else { + KMessageBox::sorry(m_part->widget(), i18n("Could not open file: %1", m_configDlg->getCommentFile())); + m_useCommentFile = false; + } +} + +bool KImGalleryPlugin::createThumb(const QString &imgName, const QString &sourceDirName, + const QString &imgGalleryDir, const QString &imageFormat) +{ + QImage img; + const QString pixPath = sourceDirName + QLatin1String("/") + imgName; + + if (m_copyFiles) { + QUrl srcURL = QUrl::fromLocalFile(pixPath); + //kDebug(90170) << "srcURL: " << srcURL; + QUrl destURL = QUrl::fromLocalFile(imgGalleryDir + QLatin1String("/images/") + imgName); + //kDebug(90170) << "destURL: " << destURL; + KIO::NetAccess::file_copy(srcURL, destURL, static_cast(parent())->widget()); + } + + const QString imgNameFormat = imgName + extension(imageFormat); + const QString thumbDir = imgGalleryDir + QLatin1String("/thumbs/"); + int extent = m_configDlg->getThumbnailSize(); + + // this code is stolen from kdebase/kioslave/thumbnail/imagecreator.cpp + // (c) 2000 gis and malte + + m_imgWidth = 120; // Setting the size of the images is + m_imgHeight = 90; // required to generate faster 'loading' pages + if (img.load(pixPath)) { + int w = img.width(), h = img.height(); + // scale to pixie size + // kDebug(90170) << "w: " << w << " h: " << h; + // Resizing if to big + if (w > extent || h > extent) { + if (w > h) { + h = (int)((double)(h * extent) / w); + if (h == 0) { + h = 1; + } + w = extent; + Q_ASSERT(h <= extent); + } else { + w = (int)((double)(w * extent) / h); + if (w == 0) { + w = 1; + } + h = extent; + Q_ASSERT(w <= extent); + } + const QImage scaleImg(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + if (scaleImg.width() != w || scaleImg.height() != h) { + kDebug(90170) << "Resizing failed. Aborting."; + return false; + } + img = scaleImg; + if (m_configDlg->colorDepthSet() == true) { + QImage::Format format; + switch (m_configDlg->getColorDepth()) { + case 1: + format = QImage::Format_Mono; + break; + case 8: + format = QImage::Format_Indexed8; + break; + case 16: + format = QImage::Format_RGB16; + break; + case 32: + default: + format = QImage::Format_RGB32; + break; + } + + const QImage depthImg(img.convertToFormat(format)); + img = depthImg; + } + } + kDebug(90170) << "Saving thumbnail to: " << thumbDir + imgNameFormat; + if (!img.save(thumbDir + imgNameFormat, imageFormat.toLatin1())) { + kDebug(90170) << "Saving failed. Aborting."; + return false; + } + m_imgWidth = w; + m_imgHeight = h; + return true; + } + return false; +} + +void KImGalleryPlugin::slotCancelled() +{ + m_cancelled = true; +} + +#include "imgalleryplugin.moc" diff --git a/plugins/kimgalleryplugin/imgalleryplugin.h b/plugins/kimgalleryplugin/imgalleryplugin.h new file mode 100644 index 0000000..c0f3efc --- /dev/null +++ b/plugins/kimgalleryplugin/imgalleryplugin.h @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl +Andreas Schlapbach + +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 kimgalleryplugin_h +#define kimgalleryplugin_h + +#include +#include +#include + +class QProgressDialog; +class KIGPDialog; +class QTextStream; + +typedef QMap CommentMap; + +class KImGalleryPlugin : public KParts::Plugin +{ + Q_OBJECT +public: + KImGalleryPlugin(QObject *parent, + const QVariantList &); + ~KImGalleryPlugin() override {} + +public slots: + void slotExecute(); + void slotCancelled(); + +private: + bool m_cancelled; + bool m_recurseSubDirectories; + bool m_copyFiles; + bool m_useCommentFile; + + int m_imgWidth; + int m_imgHeight; + int m_imagesPerRow; + + QProgressDialog *m_progressDlg; + + KParts::ReadOnlyPart *m_part; + + KIGPDialog *m_configDlg; + + CommentMap *m_commentMap; + + bool createDirectory(const QDir &thumb_dir, const QString &imgGalleryDir, const QString &dirName); + + void createHead(QTextStream &stream); + void createCSSSection(QTextStream &stream); + void createBody(QTextStream &stream, const QString &sourceDirName, const QStringList &subDirList, const QDir &imageDir, const QUrl &url, const QString &imageFormat); + + bool createThumb(const QString &imgName, const QString &sourceDirName, const QString &imgGalleryDir, const QString &imageFormat); + + bool createHtml(const QUrl &url, const QString &sourceDirName, int recursionLevel, const QString &imageFormat); + void deleteCancelledGallery(const QUrl &url, const QString &sourceDirName, int recursionLevel, const QString &imageFormat); + void loadCommentFile(); + + static QString extension(const QString &imageFormat); +}; + +#endif diff --git a/plugins/kimgalleryplugin/kimgalleryplugin.desktop b/plugins/kimgalleryplugin/kimgalleryplugin.desktop new file mode 100644 index 0000000..0ae6390 --- /dev/null +++ b/plugins/kimgalleryplugin/kimgalleryplugin.desktop @@ -0,0 +1,134 @@ +[Desktop Entry] +X-KDE-PluginInfo-Author=Lukas Tinkl,Andreas Schlapbach +X-KDE-PluginInfo-Email=lukas@kde.org,schlpbch@iam.unibe.ch +X-KDE-PluginInfo-Name=ImgGalleryPlugin +X-KDE-PluginInfo-Version=3.4 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=LGPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Image Gallery +Name[ar]=معرض الصور +Name[ast]=Galería d'imáxenes +Name[bg]=Галерия с изображения +Name[bs]=Galerija slika +Name[ca]=Galeria d'imatges +Name[ca@valencia]=Galeria d'imatges +Name[cs]=Galerie obrázků +Name[da]=Billedgalleri +Name[de]=Bildergalerie +Name[el]=Συλλογή εικόνων +Name[en_GB]=Image Gallery +Name[es]=Galería de imágenes +Name[et]=Pildigalerii +Name[eu]=Irudien galeria +Name[fi]=Kuvagalleria +Name[fr]=Galerie d'images +Name[ga]=Gailearaí Íomhánna +Name[gl]=Galería de imaxes +Name[he]=גלריית תמונות +Name[hne]=फोटू ओसारी +Name[hr]=Galerija slika +Name[hu]=Képtár +Name[ia]=Galeria de imagine +Name[id]=Galeri Citra +Name[is]=Myndasafn +Name[it]=Galleria di immagini +Name[ja]=イメージギャラリー +Name[kk]=Кескін галереясы +Name[km]=វិចិត្រសាល​រូបភាព +Name[ko]=그림 갤러리 +Name[ku]=Pêşengeha Wêneyan +Name[lt]=Paveikslėlių galerija +Name[lv]=Attēlu galerija +Name[ml]=ചിത്രശാല +Name[mr]=प्रतिमा प्रदर्शन +Name[nb]=Bildegalleri +Name[nds]=Bildgalerie +Name[nl]=Afbeeldingsgalerij +Name[nn]=Biletgalleri +Name[pa]=ਚਿੱਤਰ ਗੈਲਰੀ +Name[pl]=Galeria obrazów +Name[pt]=Galeria de Imagens +Name[pt_BR]=Galeria de imagens +Name[ro]=Galerie de imagini +Name[ru]=Галерея изображений +Name[sk]=Galéria obrázkov +Name[sl]=Galerija slik +Name[sr]=Галерија слика +Name[sr@ijekavian]=Галерија слика +Name[sr@ijekavianlatin]=Galerija slika +Name[sr@latin]=Galerija slika +Name[sv]=Bildgalleri +Name[tg]=Галереяи тасвирҳо +Name[th]=คลังภาพ +Name[tr]=Resim Galerisi +Name[ug]=سۈرەت يىغقۇچ +Name[uk]=Галерея зображень +Name[wa]=Galreye d' imådje +Name[x-test]=xxImage Galleryxx +Name[zh_CN]=图片库 +Name[zh_TW]=影像收藏本 +Comment=An easy way to generate an HTML image gallery +Comment[ar]=طريقة سريعة لإنشاء معرض صور HTML +Comment[ast]=Un mou fácil de xenerar una galería d'imáxenes HTML +Comment[bg]=Лесен начин за създаване на галерия с изображения в HTML +Comment[bs]=Lak način da napravite HTML galeriju slika +Comment[ca]=Una manera senzilla de generar una galeria d'imatges HTML +Comment[ca@valencia]=Una manera senzilla de generar una galeria d'imatges HTML +Comment[cs]=Jednoduchý způsob jak vygenerovat galerii obrázků HTML galerii obrázků +Comment[da]=En let måde at skabe et billedgalleri i HTML-format på +Comment[de]=Eine einfache Möglichkeit, eine Bildergalerie als Webseite zu erstellen +Comment[el]=Εύκολος τρόπος δημιουργίας μιας συλλογής εικόνων σε HTML +Comment[en_GB]=An easy way to generate a HTML image gallery +Comment[es]=Una forma sencilla de generar una galería de imágenes HTML +Comment[et]=Võimalus kiiresti luua HTML-pildigalerii +Comment[eu]=Modu erraz bat HTMLko irudien galeria sortzeko +Comment[fi]=Helppo tapa tuottaa HTML-kuvagalleria +Comment[fr]=Un moyen simple pour générer une galerie d'images HTML +Comment[ga]=Modh éasca chun gailearaí íomhá HTML a chruthú +Comment[gl]=Unha forma fácil de xerar unha galería HTML de imaxes +Comment[he]=דרך קלה לחולל גלריית תמונות HTML +Comment[hr]=Lagan način kako generirati galeriju slika u HTML-u +Comment[hu]=Egy egyszerű módszer HTML-képtárak előállítására +Comment[ia]=Un modo facile de generar un galeria de imagines HTML +Comment[id]=Sebuah cara cepat untuk menghasilkan galeri gambar HTML +Comment[is]=Búa til HTML-myndasafn á fljótvirkan hátt +Comment[it]=Un modo facile per generare una galleria d'immagini in HTML +Comment[ja]=HTML イメージギャラリーを簡単に作成できます +Comment[kk]=HTML Кескін галереясын құрудың оңай жолы +Comment[km]=វិធីសាស្ត្រ​ងាយស្រួល​ក្នុងការ​បង្កើត​វិចិត្រសាល​រូបភាព HTML +Comment[ko]=HTML 그림 갤러리를 만들 수 있는 쉬운 방법 +Comment[lt]=Paprastas HTML nuotraukų galerijos sukūrimo būdas +Comment[lv]=Viegls veids, kā izveidot HTML attēlu galeriju +Comment[mr]=HTML प्रतिमा प्रदर्शन करण्याकरिता सोपा मार्ग +Comment[nb]=En enkel måte å lage et HTML bildegalleri +Comment[nds]=En HTML-Bildgalerie eenfach opstellen +Comment[nl]=Een eenvoudige manier om een HTML-afbeeldingengalerij aan te maken +Comment[nn]=Ein enkel måte å laga eit HTML-biletgalleri på +Comment[pa]=ਇੱਕ HTML ਚਿੱਤਰ ਗੈਲਰੀ ਬਣਾਉਣ ਦਾ ਸੌਖਾ ਢੰਗ +Comment[pl]=Łatwy sposób na wygenerowanie galerii obrazów HTML +Comment[pt]=Uma forma fácil de gerar uma galeria de imagens em HTML +Comment[pt_BR]=Uma forma fácil de gerar uma galeria de imagens em HTML +Comment[ro]=O cale rapidă de a genera o galerie de imagini HTML +Comment[ru]=Легкий способ создать галерею изображений в HTML +Comment[sk]=Jednoduchý spôsob ako vytvoriť HTML galériu obrázkov +Comment[sl]=Preprost način za ustvaritev galerije slik HTML +Comment[sr]=Лак начин да направите ХТМЛ галерију слика +Comment[sr@ijekavian]=Лак начин да направите ХТМЛ галерију слика +Comment[sr@ijekavianlatin]=Lak način da napravite HTML galeriju slika +Comment[sr@latin]=Lak način da napravite HTML galeriju slika +Comment[sv]=Ett enkelt sätt att skapa ett HTML-bildgalleri +Comment[tg]=Роҳи осон барои эҷоди галереяи тасвирҳои HTML +Comment[th]=หนทางในการสร้างคลังภาพรูปแบบ HTML อย่างง่าย ๆ +Comment[tr]=HTML resim galerisi oluşturmanın kolay bir yolu +Comment[ug]=HTML سۈرەت يىغقۇچ ھاسىل قىلىدىغان ئاددىي ئۇسۇل +Comment[uk]=Простий спосіб створити галерею зображень в HTML +Comment[wa]=Ene åjheye façon d' askepyî ene galreye d' imådje HTML +Comment[x-test]=xxAn easy way to generate an HTML image galleryxx +Comment[zh_CN]=一种生成 HTML 图片集的便捷方式 +Comment[zh_TW]=產生 HTML 影像收藏的簡易方式 +Icon=imagegallery +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/imgallery/index.html diff --git a/plugins/kimgalleryplugin/kimgalleryplugin.rc b/plugins/kimgalleryplugin/kimgalleryplugin.rc new file mode 100644 index 0000000..6d7a57e --- /dev/null +++ b/plugins/kimgalleryplugin/kimgalleryplugin.rc @@ -0,0 +1,8 @@ + + + + &Tools + + + + diff --git a/plugins/searchbar/CMakeLists.txt b/plugins/searchbar/CMakeLists.txt new file mode 100644 index 0000000..77729e4 --- /dev/null +++ b/plugins/searchbar/CMakeLists.txt @@ -0,0 +1,28 @@ +project (searchbar) +add_definitions(-DTRANSLATION_DOMAIN=\"searchbarplugin\") +find_package(Qt5 REQUIRED Script) + +add_subdirectory( icons ) +add_subdirectory( opensearch ) + +########### next target ############### + +set(searchbarplugin_PART_SRCS + searchbar.cpp + OpenSearchManager.cpp + SuggestionEngine.cpp + WebShortcutWidget.cpp + opensearch/OpenSearchEngine.cpp + opensearch/OpenSearchReader.cpp + opensearch/OpenSearchWriter.cpp) + +add_library(searchbarplugin MODULE ${searchbarplugin_PART_SRCS}) + +target_link_libraries(searchbarplugin KF5::Parts Qt5::Script KF5::KDELibs4Support) + +install(TARGETS searchbarplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + +########### install files ############### + +install( FILES searchbar.rc searchbar.desktop DESTINATION ${KDE_INSTALL_DATADIR}/konqueror/kpartplugins ) + diff --git a/plugins/searchbar/Messages.sh b/plugins/searchbar/Messages.sh new file mode 100644 index 0000000..e23f5c6 --- /dev/null +++ b/plugins/searchbar/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/searchbarplugin.pot diff --git a/plugins/searchbar/OpenSearchManager.cpp b/plugins/searchbar/OpenSearchManager.cpp new file mode 100644 index 0000000..8a55843 --- /dev/null +++ b/plugins/searchbar/OpenSearchManager.cpp @@ -0,0 +1,169 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 "OpenSearchManager.h" + +#include +#include +#include + +#include +#include +#include + +#include "opensearch/OpenSearchEngine.h" +#include "opensearch/OpenSearchReader.h" +#include "opensearch/OpenSearchWriter.h" + +OpenSearchManager::OpenSearchManager(QObject *parent) + : QObject(parent) + , m_activeEngine(nullptr) +{ + m_state = IDLE; +} + +OpenSearchManager::~OpenSearchManager() +{ + qDeleteAll(m_enginesMap); + m_enginesMap.clear(); +} + +void OpenSearchManager::setSearchProvider(const QString &searchProvider) +{ + m_activeEngine = nullptr; + + if (!m_enginesMap.contains(searchProvider)) { + const QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "konqueror/opensearch/" + searchProvider + ".xml"); + if (fileName.isEmpty()) { + return; + } + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + kWarning(1202) << "Cannot open opensearch description file: " + fileName; + return; + } + + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(&file); + + if (engine) { + m_enginesMap.insert(searchProvider, engine); + } else { + return; + } + } + + m_activeEngine = m_enginesMap.value(searchProvider); +} + +bool OpenSearchManager::isSuggestionAvailable() +{ + return m_activeEngine != nullptr; +} + +void OpenSearchManager::addOpenSearchEngine(const QUrl &url, const QString &title) +{ + Q_UNUSED(title); + + m_jobData.clear(); + + if (m_state != IDLE) { + // TODO: cancel job + } + + m_state = REQ_DESCRIPTION; + KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + connect(job, SIGNAL(data(KIO::Job*,QByteArray)), + this, SLOT(dataReceived(KIO::Job*,QByteArray))); + connect(job, SIGNAL(result(KJob*)), SLOT(jobFinished(KJob*))); +} + +void OpenSearchManager::requestSuggestion(const QString &searchText) +{ + if (!m_activeEngine) { + return; + } + + if (m_state != IDLE) { + // TODO: cancel job + } + m_state = REQ_SUGGESTION; + + QUrl url = m_activeEngine->suggestionsUrl(searchText); + kDebug(1202) << "Requesting for suggestions: " << url.url(); + m_jobData.clear(); + KIO::TransferJob *job = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + connect(job, SIGNAL(data(KIO::Job*,QByteArray)), + this, SLOT(dataReceived(KIO::Job*,QByteArray))); + connect(job, SIGNAL(result(KJob*)), SLOT(jobFinished(KJob*))); +} + +void OpenSearchManager::dataReceived(KIO::Job *job, const QByteArray &data) +{ + Q_UNUSED(job); + m_jobData.append(data); +} + +void OpenSearchManager::jobFinished(KJob *job) +{ + if (job->error()) { + return; // just silently return + } + + if (m_state == REQ_SUGGESTION) { + const QStringList suggestionsList = m_activeEngine->parseSuggestion(m_jobData); + kDebug(1202) << "Received suggestion from " << m_activeEngine->name() << ": " << suggestionsList; + + emit suggestionReceived(suggestionsList); + } else if (m_state == REQ_DESCRIPTION) { + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(m_jobData); + if (engine) { + m_enginesMap.insert(engine->name(), engine); + QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/konqueror/opensearch/"), QStandardPaths::LocateDirectory) + "/"; + QString fileName = trimmedEngineName(engine->name()); + QFile file(path + fileName + ".xml"); + OpenSearchWriter writer; + writer.write(&file, engine); + + QString searchUrl = OpenSearchEngine::parseTemplate(QStringLiteral("\\{@}"), engine->searchUrlTemplate()); + emit openSearchEngineAdded(engine->name(), searchUrl, fileName); + } else { + kFatal() << "Error while adding new open search engine"; + } + } +} + +QString OpenSearchManager::trimmedEngineName(const QString &engineName) const +{ + QString trimmed; + QString::ConstIterator constIter = engineName.constBegin(); + while (constIter != engineName.constEnd()) { + if (constIter->isSpace()) { + trimmed.append('-'); + } else if (*constIter != '.') { + trimmed.append(constIter->toLower()); + } + constIter++; + } + + return trimmed; +} + diff --git a/plugins/searchbar/OpenSearchManager.h b/plugins/searchbar/OpenSearchManager.h new file mode 100644 index 0000000..ff8c239 --- /dev/null +++ b/plugins/searchbar/OpenSearchManager.h @@ -0,0 +1,86 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 OPENSEARCHMANAGER_H +#define OPENSEARCHMANAGER_H + +#include +#include + +class OpenSearchEngine; + +/** + * This class acts as a proxy between the SearchBar plugin and the individual suggestion engine. + * This class has a map of all available engines, and route the suggestion request to the correct engine + */ +class OpenSearchManager : public QObject +{ + Q_OBJECT + + enum STATE { + REQ_SUGGESTION, + REQ_DESCRIPTION, + IDLE + }; +public: + /** + * Constructor + */ + explicit OpenSearchManager(QObject *parent = nullptr); + + ~OpenSearchManager() override; + + void setSearchProvider(const QString &searchProvider); + + /** + * Check whether a search suggestion engine is available for the given search provider + * @param searchProvider the queried search provider + */ + bool isSuggestionAvailable(); + + void addOpenSearchEngine(const QUrl &url, const QString &title); + +public slots: + /** + * Ask the specific suggestion engine to request for suggestion for the search text + * @param searchProvider the search provider that provides the suggestion service + * @param searchText the text to be queried to the suggestion service + */ + void requestSuggestion(const QString &searchProvider); + +private slots: + void dataReceived(KIO::Job *job, const QByteArray &data); + void jobFinished(KJob *job); + +signals: + void suggestionReceived(const QStringList &suggestion); + void openSearchEngineAdded(const QString &name, const QString &searchUrl, const QString &fileName); + +private: + QString trimmedEngineName(const QString &engineName) const; + + // QString substitutueSearchText(const QString &searchText, const QString &requestURL) const; + QByteArray m_jobData; + QMap m_enginesMap; + OpenSearchEngine *m_activeEngine; + STATE m_state; +}; + +#endif // OPENSEARCHMANAGER_H + diff --git a/plugins/searchbar/SuggestionEngine.cpp b/plugins/searchbar/SuggestionEngine.cpp new file mode 100644 index 0000000..87ddc30 --- /dev/null +++ b/plugins/searchbar/SuggestionEngine.cpp @@ -0,0 +1,53 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 "SuggestionEngine.h" + +#include +#include + +#include + +SuggestionEngine::SuggestionEngine(const QString &engineName, QObject *parent) + : QObject(parent), + m_engineName(engineName) +{ + // First get the suggestion request URL for this engine + KService::Ptr service = KService::serviceByDesktopPath(QStringLiteral("searchproviders/%1.desktop").arg(m_engineName)); + + if (service) { + const QString suggestionURL = service->property(QStringLiteral("Suggest")).toString(); + if (!suggestionURL.isNull() && !suggestionURL.isEmpty()) { + m_requestURL = suggestionURL; + } else { + qWarning() << "Missing property [Suggest] for suggestion engine: " + m_engineName; + } + } +} + +QString SuggestionEngine::requestURL() const +{ + return m_requestURL; +} + +QString SuggestionEngine::engineName() const +{ + return m_engineName; +} + diff --git a/plugins/searchbar/SuggestionEngine.h b/plugins/searchbar/SuggestionEngine.h new file mode 100644 index 0000000..c548f68 --- /dev/null +++ b/plugins/searchbar/SuggestionEngine.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 SUGGESTIONENGINE_H +#define SUGGESTIONENGINE_H + +#include + +/** + * Parent class for all suggestion engines. Each suggestion engine is responsible for + * parsing the reply from the suggestion provider (host) + */ +class SuggestionEngine : public QObject +{ + Q_OBJECT + +public: + /** + * Constructor. + * @param engineName the engine name + */ + SuggestionEngine(const QString &engineName, QObject *parent = nullptr); + + /** + * Get the request URL for the suggestion service + */ + QString requestURL() const; + + /** + * Get the engine name for this engine + */ + QString engineName() const; + + /** + * To be reimplemented by subclass. Parse the suggestion reply to a QStringList + */ + virtual QStringList parseSuggestion(const QByteArray &response) const = 0; + +protected: + QString m_engineName; + QString m_requestURL; +}; + +#endif // SUGGESTIONENGINE_H + diff --git a/plugins/searchbar/WebShortcutWidget.cpp b/plugins/searchbar/WebShortcutWidget.cpp new file mode 100644 index 0000000..6206365 --- /dev/null +++ b/plugins/searchbar/WebShortcutWidget.cpp @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 "WebShortcutWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +WebShortcutWidget::WebShortcutWidget(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout = new QVBoxLayout(this); + QHBoxLayout *titleLayout = new QHBoxLayout(); + mainLayout->addLayout(titleLayout); + QLabel *iconLabel = new QLabel(this); + QIcon wsIcon = QIcon::fromTheme(QStringLiteral("preferences-web-browser-shortcuts")); + iconLabel->setPixmap(wsIcon.pixmap(22, 22)); + titleLayout->addWidget(iconLabel); + m_searchTitleLabel = new QLabel(i18n("Set Uri Shortcuts"), this); + QFont boldFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); + boldFont.setBold(true); + m_searchTitleLabel->setFont(boldFont); + titleLayout->addWidget(m_searchTitleLabel); + titleLayout->addStretch(); + + QFormLayout *formLayout = new QFormLayout(); + mainLayout->addLayout(formLayout); + + QFont smallFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); + m_nameLineEdit = new QLineEdit(this); + m_nameLineEdit->setEnabled(false); + m_nameLineEdit->setFont(smallFont); + QLabel *nameLabel = new QLabel(i18n("Name:"), this); + nameLabel->setFont(smallFont); + formLayout->addRow(nameLabel, m_nameLineEdit); + + QLabel *shortcutsLabel = new QLabel(i18n("Shortcuts:"), this); + shortcutsLabel->setFont(smallFont); + m_wsLineEdit = new QLineEdit(this); + m_wsLineEdit->setMinimumWidth(100); + m_wsLineEdit->setFont(smallFont); + formLayout->addRow(shortcutsLabel, m_wsLineEdit); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + mainLayout->addWidget(buttonBox); + connect(buttonBox, &QDialogButtonBox::accepted, this, &WebShortcutWidget::okClicked); + connect(buttonBox, &QDialogButtonBox::rejected, this, &WebShortcutWidget::cancelClicked); + + resize(minimumSizeHint()); + + QTimer::singleShot(0, m_wsLineEdit, SLOT(setFocus())); +} + +void WebShortcutWidget::show(const QString &openSearchName, const QString &fileName) +{ + m_wsLineEdit->clear(); + m_nameLineEdit->setText(openSearchName); + m_fileName = fileName; + + QDialog::show(); +} + +void WebShortcutWidget::okClicked() +{ + hide(); + emit webShortcutSet(m_nameLineEdit->text(), m_wsLineEdit->text(), m_fileName); +} + +void WebShortcutWidget::cancelClicked() +{ + hide(); +} + diff --git a/plugins/searchbar/WebShortcutWidget.h b/plugins/searchbar/WebShortcutWidget.h new file mode 100644 index 0000000..bea67b5 --- /dev/null +++ b/plugins/searchbar/WebShortcutWidget.h @@ -0,0 +1,51 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the 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 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 WEBSHORTCUTWIDGET_H +#define WEBSHORTCUTWIDGET_H + +#include + +class QLabel; +class QLineEdit; + +class WebShortcutWidget : public QDialog +{ + Q_OBJECT +public: + WebShortcutWidget(QWidget *parent = nullptr); + + void show(const QString &openSearchName, const QString &fileName); + +private slots: + void okClicked(); + void cancelClicked(); + +signals: + void webShortcutSet(const QString &openSearchName, const QString &webShortcut, const QString &fileName); + +private: + QLabel *m_searchTitleLabel; + QLineEdit *m_wsLineEdit; + QLineEdit *m_nameLineEdit; + QString m_fileName; +}; + +#endif // WEBSHORTCUTWIDGET_H + diff --git a/plugins/searchbar/icons/16-actions-google.png b/plugins/searchbar/icons/16-actions-google.png new file mode 100644 index 0000000000000000000000000000000000000000..eb724487e32e73dc53a5df1dd16d323d116a107e GIT binary patch literal 459 zcmV;+0W|)JP)71MH)0_8#QMfHfJC@Y9l;sDnfB9Lvb!!voJ_?I#GN(QG7nL z13t3^MOuSWWs6j3jah7vTWyhKb(e;eu7{Mbh?cO4m#~eRvyq;*lApGgqPdx*yP>PV zq_4uJu*9je#jCW(tF_0hw#d1`(7(pi!^+ph%Gb-$+|1J5&C=b^)Zfq5-_X|J)Y;3_@9ORG?eFvR83Xn9`1knw`T6_%`~3a={{H^{|NsAnUfL=E z004tYL_t&-(_>)gK?Mx#wkW_1DqyN2AuO$K1rspf6;?IUQWRvdga~MG=s?s9K~z|? zib4(0ga~Le=%N}b$!LixAjV*VDxk)o0%97A2y!Wc1uU5PA+mA|P-~T$#ceXTQ)Y}+X^vZMkzR3> zU~-jZc9>;%m}q&LZhoG2g`;?grFn>^eT=AnjH!Q)s(_EGf{?6(k*tHSsD!UQg}jc5 zm#~eRvyPjylApGdpSP5txS6E8nx(s(r@fu1zMrbUrm)1Sv&O5m$E>!FDb3?eFvM@bvKU_4646_4fGo_xbtx`}(M$`~3a>{{H{}|K6aB`2YX_ z%t=H+R2b7^;1&?Y0vNcpT`_=zEd#e*JO+q~fD4CO8z?KP8hS+`3kONFDH=ID>ML+E zOCf~q*(3uYnj$rY;le(w!qG5ugJodCal(w=aO)!7VZ!bVLfBlQ#UPJOSdKvto3Jc{ z5;kFV1_>zN!^p(K%mym##K0a75f1S*XJGP!3diy=Xu#dazy_dy1!gi>Hd1v5T0pjG3~Lp0<*o zww9u~n4`LyrMsJ_yr8SUp{u~7t--Fh$+5c2vb)Q(yUet`&9%PHxxvu7!qL6N)4#^l z!pYXh&f3V%+RM@0&C=b@)85h6;L_LO+1}>d;OOAv>f+|?h1CE z@AK~P^ziZZ@$&WZ^!M`_1NHX!_V@Ys`1<(y`uX|$`}_R+{Qdm>{r>*`|Ns9QKTDGU z00AFKL_t(|+LhB+Qvxv%!0|tF_5xV2D_F1>RBYG~6~SIPkP`(J@htHDUwqO_h9Lv{ znEYmUlWcG}dX!NKC@LbCs~(s}I$sWaoG!bY0BQ%;W6veveX|kI+Wv(e-CA-3y-zZ@ z?V>I6pG^1LYCa`!t+DVT_7donN~BtFzDmvRO-sNBQTa5-+aid=r1BnCU`Gj@aHaxz z;6VivVEa*lIAEwi2Dnr<*#Kc{HR2tgn4O;))h#duix$Y<#6tD3Td=?ha4+TVhex5r zw+nm{@PH}4#g!e7L@g#?W1tNM4)4x`bFI*^ znk^aHWN@$<(AvHJaI)Oko2g8p`j4Xq-O8u{`~nj>Mw*ujQaAtr002ovPDHLkV1hgk Bb#nj! literal 0 HcmV?d00001 diff --git a/plugins/searchbar/icons/48-actions-google.png b/plugins/searchbar/icons/48-actions-google.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ba8d0eb1f66511af4a7fca8451d89f63b90135 GIT binary patch literal 1078 zcmV-61j+k}P)c|B8oK2&}_vjaY}1V2@O zK~{i6S%O4af=XY8O<{;pWs6m5j#g=oS!|G6ZIN7Vl3Z_+UU8IQa+P6om1A_5WObKi zc9>^)nrL~NX?mM$e4K87o^XJma)P0AgQ0YUqIQO)cZZ~Sh^2Xmrh18{e~zkvkE(%? ztAdcMgORL+lC6c4t%j7Yhm@~~m9L1Fu!)zjikPvBn6iwSvW}axkDIiSowbpkwvwN= zm7%zoqq&%)x|yWAnx(s%ro5Y{yqu@KpQ^v0tG}bI!K1Fiq_4uOwa2Ws$gQ`?u(`^y zy34b>%(T4Cw7t!?zs|S6&$+?Sy28=C!_vLQ)4s;kzsA(S$JN5g*2c`)#?9Hs&f3V% z+R4w`%Fx`)(cI3{-p|zE&(+`2*5K3F;?&vV*4pFO+vL~W<=EZj+1}>c-{;-o=-%S# z;N*`{{R2~4-^&q0005eNklnp&!yvgWa4*boZ`r*sIo%M2LgCBP$e)0hUpKv8|6jnx+<>|) zJti@$yru8(N1*EtH7B2%OG5j)Xd0|USP)|7uTpEqr~5l=qHK)FKKd934`nh!oa-(= zBEr1V_`M?(Yz5L(@vUS=dz8pU3~bvHVl#{^P6P47=AiSWqaVRmbBx3yKnS7ZsX~{3 zmlPnNi1zmqQE)hB1Q;^DWmKI@mdO1KBfISXS3_!;L zl(fJ369)*QK+XgFVMr$&AQHe72gnAX<^YWVRMHNWk#Wgss=V^jEMsH6XWHGd<{9 literal 0 HcmV?d00001 diff --git a/plugins/searchbar/icons/64-actions-google.png b/plugins/searchbar/icons/64-actions-google.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc1e3bcbef97844c2b4e6e5b73004de17f170f1 GIT binary patch literal 1281 zcmV+c1^)VpP)c{omb zIZ%5#QG7d5d_7ZrK2&}_vjaY}1VB}PLRf)AS%O4af<;<`NnM3XUWQ6vhD%_FOks#k zVTev*iBe^YRcVe^X^vWLkz8+*U2v0Mag<%|zb%djKg`;+cquD8jrxXQA-%eB7Fw!hA~!O*(G z(Y(Xby~NYK#nZpW)WOKs!^+ph%Gbrq*v8D+#?9Ht&f3Y(+se?~&ePt{)Zfq5-_X|J z)!O6N+vL~W<=EZj+u!Hh;OO1q=-%S#-{R@u*3|=;^yq*=IrF>?d9n1=IQR| z>hI|4@9XXI?C$dJ@bvHT^z!ug^BDv4_4oAk`1SVq_V@Ys`1<(y`uX|$`uh9(`~3U- z{rvs?{r&#_{{H{}|Kdz10RR93Z%IT!RCwC$*Zo(^Q5?YW&sy71o{~ajp_%6*Oi7Zq z6@|%E8q&;D44HXqDP!_HZ6i^prnb*N>Fe|D9Gu;I&F%Q5)BDGL?q28ayWQ{k4wfmc zpFy()K*_!+%>fwz6GH>O-q42$3E;W2y3Du;rdzP0-1#7$IWX9|0n*cLZN5E{0gyOr z0;*vDk#@KD+WC`KOCC(8F*k?*0zBJDD|cRgg})W*+^Yk%he9CPp$CAh$|smsxLzfq zBH+yqP|E8?X76o^K0hS@hUl|yiXg8ZfKucGaWg1w{)XJ%0#xyVR2A(%iu@+EaDopw z>B|nFs8w)<3-~mk)PTZ_5a0saLCFvk1BZ7F^MD}G2INm;4FNBufscAnT8Yv?8~m(R z9@s`ew>+?%fS@!mt|1^S4ZHwqR2uNp`}HUdcnC1a11_NA(!dR%BGSNPpq@$tQJ}oi zz*IH?jmXS?$ll~=b#;2Kc3(Vm+;)=zU=aZ(Hjod0)XoAbX_WPe3HUs14ZBMWKxvPS zvj9I(9ilsGDJ^lc4^yg`riI@H!U0-xpAFzSpsovmT3Qj}03-8gTr|c9Y_wvS17JN+ zRzA>3*D%QgMoWP5i-9G`18^{xfW<)`Kzr2j0lcLlVPQW9I7s8qd;lFl<@T|GYMQA#1>J)?S&g#doFg4*h%f#k23W0x#BKF`P00000NkvXXu0mjf5$=z$ literal 0 HcmV?d00001 diff --git a/plugins/searchbar/icons/CMakeLists.txt b/plugins/searchbar/icons/CMakeLists.txt new file mode 100644 index 0000000..48a8bda --- /dev/null +++ b/plugins/searchbar/icons/CMakeLists.txt @@ -0,0 +1,9 @@ +set(searchbar_ICONS + 16-actions-google.png + 22-actions-google.png + 32-actions-google.png + 48-actions-google.png + 64-actions-google.png + sc-actions-google.svgz + ) +ecm_install_icons(ICONS ${searchbar_ICONS} DESTINATION ${DATA_INSTALL_DIR}/konqueror/icons/ THEME hicolor ) diff --git a/plugins/searchbar/icons/sc-actions-google.svgz b/plugins/searchbar/icons/sc-actions-google.svgz new file mode 100644 index 0000000000000000000000000000000000000000..9b4ba866cceadbf551a4e82626b3f29e0b2e6c37 GIT binary patch literal 2043 zcmV{#?~>24IhJ*GKNF14l33++QC6G# z*>4|zn)_LDY_qD!c6Al+XH`A>;q7;C{xY8@@0ysku}IEkyG?$sJ{|My5R<=c+xDW zq<)So*2H6dYVzKFo?mJ<#Tu$pCTGxx{cz0ZS>D3Yd{ft(U1Uh>%XRGf)E-Xlf8#?Nt3D(upJ?dCo!t|7 z?I1oJ>ZYBq%Uwj+>%V#9Xu2VbX1!cg^z>qy3##Xw$|7FMMnS#$J?8C=)r$@ zT`f{?cfCxvzRqQZlIEism--cr(TfxE6%7>0Ul9?dD4E`~%2pyN~r4r7(wY4ePyUABt5``HI-Wg?!l zxM}Ls0jn8@W{>h>Z2m~xA#1l|LC5xS2ZJ>dT@G7!M~C?^UEkXQU=152wZ*RgbB%0K2XB1 zs3FPpi9e@=2#~_MucAc7mE!uFpCKyxhL!>KuMiRbkcf4S%l24)iAy0h^UiZ4oIO0; z^#UlNe!5!!CFdL=TYt^M=8LNU);wK}!!O{co%+;pHXXPxcK-Q)6K zb^R&%XVsSfJ7v$Nm22jda3Xb{87-~1$-52}Qh1ko!Gdwf8<=7qT?wf-Oe-0T95BbB z=UK492(q3ugJg~eW&MT6U|A5>dT|k3aKTIv+QB*mrlb*40#z_KG9*DU$(_`MA-IrM zB;GQGuIm8IGAERluy%nNkBEdi7MwCZaf)$ol%P1CS+1;2tYzLBZ}f!0+BhbiRKj1N z+B2`5vaXM#l+%eux|RoLfJqjD3If(jcbR*eq6SF`*+hEgph}ox!3RW4XkLv%^wc|8 zfB_9_$-y)zGO6dx3gf*>1X!h)PpJk0hi1gUuGI|DWT4C^O=Fk?F(xEZFp#f5@BuGOaP=lZX1;q|bTc=SYYLH5KVG?DS;@kz3O87y(q!P zs8kA=SR|2{K%KP~1fiY5Y9$hffK;IzFr^hW%%Bkg-Y+ykfNJw2Ls4r^$FOnpxeZRgXV`M`q4 zCm2(Xv|gYGEPL;zREhCS2lC$CHOio$-IyxS<0g#8w6EI83)Isd<0E0BztpG+wA%e0 zz!ld)QoH)S!HNW89O7`%t^i}_tQ}jZHC?9yYR18MQuL}reW&Q9;DllM42A~K*lHK1 zdjY5ph}YfkPMcsIVIuJ06)+fkVP%3Gs71WPxX~2k9id8L08EPdy%5-e1e}68!!2P( zT5Z4tCYbUjNOA!=#-5yWN0+Iy-R*AOHHw5iD(f~Gu7njqbe#>xSS*8P8e3r$VKN{i zM+*`ZY|MZ;ue+rM9bnf_n!qeg0auepVBsR_hyL7OmmKGpz6`G(Oz4Xp6U4vj2~9?` zT7BaWt;4gK?|$As$@7<<-f5M-{!#VYCqhV0MZfsWKFMBrdUun%>CZ5A5$X3+{MjI< Z*Z4d4VuQbG;@4rk{U4XWC&W$_0003G^Sl56 literal 0 HcmV?d00001 diff --git a/plugins/searchbar/opensearch/CMakeLists.txt b/plugins/searchbar/opensearch/CMakeLists.txt new file mode 100644 index 0000000..92a2083 --- /dev/null +++ b/plugins/searchbar/opensearch/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory( engines ) + diff --git a/plugins/searchbar/opensearch/OpenSearchEngine.cpp b/plugins/searchbar/opensearch/OpenSearchEngine.cpp new file mode 100644 index 0000000..ca59c9d --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchEngine.cpp @@ -0,0 +1,226 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Christian Franke + * Copyright 2009 Fredy Yanardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "OpenSearchEngine.h" + +#include + +#include +#include +#include +#include + +OpenSearchEngine::OpenSearchEngine(QObject *) + : m_scriptEngine(nullptr) +{ +} + +OpenSearchEngine::~OpenSearchEngine() +{ + delete m_scriptEngine; +} + +QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate) +{ + QString result = searchTemplate; + result.replace(QLatin1String("{count}"), QLatin1String("20")); + result.replace(QLatin1String("{startIndex}"), QLatin1String("0")); + result.replace(QLatin1String("{startPage}"), QLatin1String("0")); + result.replace(QLatin1String("{language}"), KLocale::global()->language()); + result.replace(QLatin1String("{inputEncoding}"), QLatin1String("UTF-8")); + result.replace(QLatin1String("{outputEncoding}"), QLatin1String("UTF-8")); + result.replace(QLatin1String("{searchTerms}"), searchTerm); + return result; +} + +QString OpenSearchEngine::name() const +{ + return m_name; +} + +void OpenSearchEngine::setName(const QString &name) +{ + m_name = name; +} + +QString OpenSearchEngine::description() const +{ + return m_description; +} + +void OpenSearchEngine::setDescription(const QString &description) +{ + m_description = description; +} + +QString OpenSearchEngine::searchUrlTemplate() const +{ + return m_searchUrlTemplate; +} + +void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate) +{ + m_searchUrlTemplate = searchUrlTemplate; +} + +QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const +{ + if (m_searchUrlTemplate.isEmpty()) { + return QUrl(); + } + + QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8()); + + QList::const_iterator end = m_searchParameters.constEnd(); + QList::const_iterator i = m_searchParameters.constBegin(); + for (; i != end; ++i) { + retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); + } + + return retVal; +} + +bool OpenSearchEngine::providesSuggestions() const +{ + return !m_suggestionsUrlTemplate.isEmpty(); +} + +QString OpenSearchEngine::suggestionsUrlTemplate() const +{ + return m_suggestionsUrlTemplate; +} + +void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate) +{ + m_suggestionsUrlTemplate = suggestionsUrlTemplate; +} + +QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const +{ + if (m_suggestionsUrlTemplate.isEmpty()) { + return QUrl(); + } + + QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8()); + + QList::const_iterator end = m_suggestionsParameters.constEnd(); + QList::const_iterator i = m_suggestionsParameters.constBegin(); + for (; i != end; ++i) { + retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); + } + + return retVal; +} + +QList OpenSearchEngine::searchParameters() const +{ + return m_searchParameters; +} + +void OpenSearchEngine::setSearchParameters(const QList &searchParameters) +{ + m_searchParameters = searchParameters; +} + +QList OpenSearchEngine::suggestionsParameters() const +{ + return m_suggestionsParameters; +} + +void OpenSearchEngine::setSuggestionsParameters(const QList &suggestionsParameters) +{ + m_suggestionsParameters = suggestionsParameters; +} + +QString OpenSearchEngine::imageUrl() const +{ + return m_imageUrl; +} + +void OpenSearchEngine::setImageUrl(const QString &imageUrl) +{ + m_imageUrl = imageUrl; +} + +QImage OpenSearchEngine::image() const +{ + return m_image; +} + +void OpenSearchEngine::setImage(const QImage &image) +{ + m_image = image; +} + +bool OpenSearchEngine::isValid() const +{ + return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty()); +} + +bool OpenSearchEngine::operator==(const OpenSearchEngine &other) const +{ + return (m_name == other.m_name + && m_description == other.m_description + && m_imageUrl == other.m_imageUrl + && m_searchUrlTemplate == other.m_searchUrlTemplate + && m_suggestionsUrlTemplate == other.m_suggestionsUrlTemplate + && m_searchParameters == other.m_searchParameters + && m_suggestionsParameters == other.m_suggestionsParameters); +} + +bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const +{ + return (m_name < other.m_name); +} + +QStringList OpenSearchEngine::parseSuggestion(const QByteArray &resp) +{ + const QString response = QString::fromUtf8(resp.constData(), resp.size()).trimmed(); + + if (response.isEmpty()) { + return QStringList(); + } + + if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']'))) { + return QStringList(); + } + + if (!m_scriptEngine) { + m_scriptEngine = new QScriptEngine(); + } + + // Evaluate the JSON response using QtScript. + if (!m_scriptEngine->canEvaluate(response)) { + return QStringList(); + } + + QScriptValue responseParts = m_scriptEngine->evaluate(response); + + if (!responseParts.property(1).isArray()) { + return QStringList(); + } + + QStringList suggestionsList; + qScriptValueToSequence(responseParts.property(1), suggestionsList); + + return suggestionsList; +} + diff --git a/plugins/searchbar/opensearch/OpenSearchEngine.h b/plugins/searchbar/opensearch/OpenSearchEngine.h new file mode 100644 index 0000000..7c09bad --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchEngine.h @@ -0,0 +1,91 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Christian Franke + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHENGINE_H +#define OPENSEARCHENGINE_H + +#include +#include + +#include + +class QScriptEngine; + +class OpenSearchEngine +{ +public: + typedef QPair Parameter; + + OpenSearchEngine(QObject *parent = nullptr); + ~OpenSearchEngine(); + + QString name() const; + void setName(const QString &name); + + QString description() const; + void setDescription(const QString &description); + + QString searchUrlTemplate() const; + void setSearchUrlTemplate(const QString &searchUrl); + QUrl searchUrl(const QString &searchTerm) const; + + bool providesSuggestions() const; + + QString suggestionsUrlTemplate() const; + void setSuggestionsUrlTemplate(const QString &suggestionsUrl); + QUrl suggestionsUrl(const QString &searchTerm) const; + + QList searchParameters() const; + void setSearchParameters(const QList &searchParameters); + + QList suggestionsParameters() const; + void setSuggestionsParameters(const QList &suggestionsParameters); + + QString imageUrl() const; + void setImageUrl(const QString &url); + + QImage image() const; + void setImage(const QImage &image); + + bool isValid() const; + + bool operator==(const OpenSearchEngine &other) const; + bool operator<(const OpenSearchEngine &other) const; + + QStringList parseSuggestion(const QByteArray &response); + + static QString parseTemplate(const QString &searchTerm, const QString &searchTemplate); + +private: + QString m_name; + QString m_description; + + QString m_imageUrl; + QImage m_image; + + QString m_searchUrlTemplate; + QString m_suggestionsUrlTemplate; + QList m_searchParameters; + QList m_suggestionsParameters; + + QScriptEngine *m_scriptEngine; +}; + +#endif // OPENSEARCHENGINE_H diff --git a/plugins/searchbar/opensearch/OpenSearchReader.cpp b/plugins/searchbar/opensearch/OpenSearchReader.cpp new file mode 100644 index 0000000..ec3f97f --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchReader.cpp @@ -0,0 +1,132 @@ +/* + * Copyright 2009 Jakub Wieczorek + * Copyright 2009 Fredy Yanardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "OpenSearchReader.h" + +#include "OpenSearchEngine.h" + +#include + +#include + +OpenSearchReader::OpenSearchReader() + : QXmlStreamReader() +{ +} + +OpenSearchEngine *OpenSearchReader::read(const QByteArray &data) +{ + clear(); + + addData(data); + + return read(); +} + +OpenSearchEngine *OpenSearchReader::read(QIODevice *device) +{ + clear(); + + if (!device->isOpen()) { + device->open(QIODevice::ReadOnly); + } + + setDevice(device); + return read(); +} + +OpenSearchEngine *OpenSearchReader::read() +{ + OpenSearchEngine *engine = new OpenSearchEngine(); + + while (!isStartElement() && !atEnd()) { + readNext(); + } + + if (name() != QLatin1String("OpenSearchDescription") + || namespaceUri() != QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) { + raiseError(i18n("The file is not an OpenSearch 1.1 file.")); + return engine; + } + + while (!(isEndElement() && name() == QLatin1String("OpenSearchDescription")) && !atEnd()) { + readNext(); + + if (!isStartElement()) { + continue; + } + + if (name() == QLatin1String("ShortName")) { + engine->setName(readElementText()); + } else if (name() == QLatin1String("Description")) { + engine->setDescription(readElementText()); + } else if (name() == QLatin1String("Url")) { + QString type = attributes().value(QLatin1String("type")).toString(); + QString url = attributes().value(QLatin1String("template")).toString(); + + if (url.isEmpty()) { + continue; + } + + QList parameters; + + readNext(); + + while (!(isEndElement() && name() == QLatin1String("Url"))) { + if (!isStartElement() || (name() != QLatin1String("Param") && name() != QLatin1String("Parameter"))) { + readNext(); + continue; + } + + QString key = attributes().value(QLatin1String("name")).toString(); + QString value = attributes().value(QLatin1String("value")).toString(); + + if (!key.isEmpty() && !value.isEmpty()) { + parameters.append(OpenSearchEngine::Parameter(key, value)); + } + + while (!isEndElement()) { + readNext(); + } + } + + if (type == QLatin1String("application/x-suggestions+json")) { + engine->setSuggestionsUrlTemplate(url); + engine->setSuggestionsParameters(parameters); + } else { + engine->setSearchUrlTemplate(url); + engine->setSearchParameters(parameters); + } + } else if (name() == QLatin1String("Image")) { + engine->setImageUrl(readElementText()); + } + + if (!engine->name().isEmpty() + && !engine->description().isEmpty() + && !engine->suggestionsUrlTemplate().isEmpty() + && !engine->searchUrlTemplate().isEmpty() + && !engine->imageUrl().isEmpty()) { + break; + } + } + + return engine; +} + diff --git a/plugins/searchbar/opensearch/OpenSearchReader.h b/plugins/searchbar/opensearch/OpenSearchReader.h new file mode 100644 index 0000000..0a576b4 --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchReader.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHREADER_H +#define OPENSEARCHREADER_H + +#include + +class OpenSearchEngine; + +class OpenSearchReader : public QXmlStreamReader +{ +public: + OpenSearchReader(); + + OpenSearchEngine *read(const QByteArray &data); + OpenSearchEngine *read(QIODevice *device); + +private: + OpenSearchEngine *read(); +}; + +#endif // OPENSEARCHREADER_H diff --git a/plugins/searchbar/opensearch/OpenSearchWriter.cpp b/plugins/searchbar/opensearch/OpenSearchWriter.cpp new file mode 100644 index 0000000..b8be333 --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchWriter.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "OpenSearchWriter.h" + +#include "OpenSearchEngine.h" + +#include + +OpenSearchWriter::OpenSearchWriter() + : QXmlStreamWriter() +{ + setAutoFormatting(true); +} + +bool OpenSearchWriter::write(QIODevice *device, OpenSearchEngine *engine) +{ + if (!engine) { + return false; + } + + if (!device->isOpen()) { + device->open(QIODevice::WriteOnly); + } + + setDevice(device); + write(engine); + return true; +} + +void OpenSearchWriter::write(OpenSearchEngine *engine) +{ + writeStartDocument(); + writeStartElement(QStringLiteral("OpenSearchDescription")); + writeDefaultNamespace(QStringLiteral("http://a9.com/-/spec/opensearch/1.1/")); + + if (!engine->name().isEmpty()) { + writeTextElement(QStringLiteral("ShortName"), engine->name()); + } + + if (!engine->description().isEmpty()) { + writeTextElement(QStringLiteral("Description"), engine->description()); + } + + if (!engine->searchUrlTemplate().isEmpty()) { + writeStartElement(QStringLiteral("Url")); + writeAttribute(QStringLiteral("method"), QStringLiteral("get")); + writeAttribute(QStringLiteral("template"), engine->searchUrlTemplate()); + + if (!engine->searchParameters().empty()) { + writeNamespace(QStringLiteral("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QStringLiteral("p")); + + QList::const_iterator end = engine->searchParameters().constEnd(); + QList::const_iterator i = engine->searchParameters().constBegin(); + for (; i != end; ++i) { + writeStartElement(QStringLiteral("p:Parameter")); + writeAttribute(QStringLiteral("name"), i->first); + writeAttribute(QStringLiteral("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->suggestionsUrlTemplate().isEmpty()) { + writeStartElement(QStringLiteral("Url")); + writeAttribute(QStringLiteral("method"), QStringLiteral("get")); + writeAttribute(QStringLiteral("type"), QStringLiteral("application/x-suggestions+json")); + writeAttribute(QStringLiteral("template"), engine->suggestionsUrlTemplate()); + + if (!engine->suggestionsParameters().empty()) { + writeNamespace(QStringLiteral("http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"), QStringLiteral("p")); + + QList::const_iterator end = engine->suggestionsParameters().constEnd(); + QList::const_iterator i = engine->suggestionsParameters().constBegin(); + for (; i != end; ++i) { + writeStartElement(QStringLiteral("p:Parameter")); + writeAttribute(QStringLiteral("name"), i->first); + writeAttribute(QStringLiteral("value"), i->second); + writeEndElement(); + } + } + + writeEndElement(); + } + + if (!engine->imageUrl().isEmpty()) { + writeTextElement(QStringLiteral("Image"), engine->imageUrl()); + } + + writeEndElement(); + writeEndDocument(); +} + diff --git a/plugins/searchbar/opensearch/OpenSearchWriter.h b/plugins/searchbar/opensearch/OpenSearchWriter.h new file mode 100644 index 0000000..7584d71 --- /dev/null +++ b/plugins/searchbar/opensearch/OpenSearchWriter.h @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Jakub Wieczorek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef OPENSEARCHWRITER_H +#define OPENSEARCHWRITER_H + +#include + +class QIODevice; + +class OpenSearchEngine; + +class OpenSearchWriter : public QXmlStreamWriter +{ +public: + OpenSearchWriter(); + + bool write(QIODevice *device, OpenSearchEngine *engine); + +private: + void write(OpenSearchEngine *engine); +}; + +#endif + diff --git a/plugins/searchbar/opensearch/engines/CMakeLists.txt b/plugins/searchbar/opensearch/engines/CMakeLists.txt new file mode 100644 index 0000000..15a31f2 --- /dev/null +++ b/plugins/searchbar/opensearch/engines/CMakeLists.txt @@ -0,0 +1,2 @@ +install( FILES google.xml DESTINATION ${KDE_INSTALL_DATADIR}/konqueror/opensearch ) + diff --git a/plugins/searchbar/opensearch/engines/google.xml b/plugins/searchbar/opensearch/engines/google.xml new file mode 100644 index 0000000..622a073 --- /dev/null +++ b/plugins/searchbar/opensearch/engines/google.xml @@ -0,0 +1,9 @@ + + + Google + Google Web Search + + + http://www.google.com/favicon.ico + + diff --git a/plugins/searchbar/searchbar.cpp b/plugins/searchbar/searchbar.cpp new file mode 100644 index 0000000..85f53de --- /dev/null +++ b/plugins/searchbar/searchbar.cpp @@ -0,0 +1,746 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Arend van Beelen jr. + Copyright (C) 2009 Fredy Yanardi + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "searchbar.h" + +#include "OpenSearchManager.h" +#include "WebShortcutWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +K_PLUGIN_FACTORY(SearchBarPluginFactory, registerPlugin();) + +SearchBarPlugin::SearchBarPlugin(QObject *parent, + const QVariantList &) : + KParts::Plugin(parent), + m_popupMenu(nullptr), + m_addWSWidget(nullptr), + m_searchMode(UseSearchProvider), + m_urlEnterLock(false), + m_openSearchManager(new OpenSearchManager(this)), + m_reloadConfiguration(false) +{ + m_searchCombo = new SearchBarCombo(nullptr); + m_searchCombo->lineEdit()->installEventFilter(this); + connect(m_searchCombo, SIGNAL(activated(QString)), + SLOT(startSearch(QString))); + connect(m_searchCombo, SIGNAL(iconClicked()), SLOT(showSelectionMenu())); + m_searchCombo->setWhatsThis(i18n("Search Bar

" + "Enter a search term. Click on the icon to change search mode or provider.

")); + connect(m_searchCombo, SIGNAL(suggestionEnabled(bool)), this, SLOT(enableSuggestion(bool))); + + m_searchComboAction = new QWidgetAction(actionCollection()); + actionCollection()->addAction(QStringLiteral("toolbar_search_bar"), m_searchComboAction); + m_searchComboAction->setText(i18n("Search Bar")); + m_searchComboAction->setDefaultWidget(m_searchCombo); + actionCollection()->setShortcutsConfigurable(m_searchComboAction, false); + + QAction *a = actionCollection()->addAction(QStringLiteral("focus_search_bar")); + a->setText(i18n("Focus Searchbar")); + actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S)); + connect(a, SIGNAL(triggered()), this, SLOT(focusSearchbar())); + m_searchProvidersDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/kde5/services/searchproviders/"; + QDir().mkpath(m_searchProvidersDir); + configurationChanged(); + + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + connect(m_timer, SIGNAL(timeout()), SLOT(requestSuggestion())); + + // parent is the KonqMainWindow and we want to listen to PartActivateEvent events. + parent->installEventFilter(this); + + connect(m_searchCombo->lineEdit(), SIGNAL(textEdited(QString)), + SLOT(searchTextChanged(QString))); + connect(m_openSearchManager, SIGNAL(suggestionReceived(QStringList)), + SLOT(addSearchSuggestion(QStringList))); + connect(m_openSearchManager, SIGNAL(openSearchEngineAdded(QString,QString,QString)), + SLOT(openSearchEngineAdded(QString,QString,QString))); + + QDBusConnection::sessionBus().connect(QString(), QString(), QStringLiteral("org.kde.KUriFilterPlugin"), + QStringLiteral("configure"), this, SLOT(reloadConfiguration())); +} + +SearchBarPlugin::~SearchBarPlugin() +{ + KConfigGroup config(KSharedConfig::openConfig(), "SearchBar"); + config.writeEntry("Mode", (int) m_searchMode); + config.writeEntry("CurrentEngine", m_currentEngine); + config.writeEntry("SuggestionEnabled", m_suggestionEnabled); + + delete m_searchCombo; + m_searchCombo = nullptr; +} + +bool SearchBarPlugin::eventFilter(QObject *o, QEvent *e) +{ + if (qobject_cast(o) && KParts::PartActivateEvent::test(e)) { + KParts::PartActivateEvent *partEvent = static_cast(e); + KParts::ReadOnlyPart *part = qobject_cast(partEvent->part()); + //kDebug() << "Embedded part changed to " << part; + if (part && (!m_part || part != m_part.data())) { + m_part = part; + + // Delete the popup menu so a new one can be created with the + // appropriate entries the next time it is shown... + // ######## TODO: This loses the opensearch entries for the old part!!! + if (m_popupMenu) { + delete m_popupMenu; + m_popupMenu = nullptr; + m_addSearchActions.clear(); // the actions had the menu as parent, so they're deleted now + } + + // Change the search mode if it is set to FindInThisPage since + // that feature is currently KHTML specific. It is also completely + // redundant and unnecessary. + if (m_searchMode == FindInThisPage && enableFindInPage()) { + nextSearchEntry(); + } + + connect(part, SIGNAL(completed()), this, SLOT(HTMLDocLoaded())); + connect(part, SIGNAL(started(KIO::Job*)), this, SLOT(HTMLLoadingStarted())); + } + // Delay since when destroying tabs part 0 gets activated for a bit, before the proper part + QTimer::singleShot(0, this, SLOT(updateComboVisibility())); + } else if (o == m_searchCombo->lineEdit() && e->type() == QEvent::KeyPress) { + QKeyEvent *k = (QKeyEvent *)e; + if (k->modifiers() & Qt::ControlModifier) { + if (k->key() == Qt::Key_Down) { + nextSearchEntry(); + return true; + } + if (k->key() == Qt::Key_Up) { + previousSearchEntry(); + return true; + } + } + } + return KParts::Plugin::eventFilter(o, e); +} + +void SearchBarPlugin::nextSearchEntry() +{ + if (m_searchMode == FindInThisPage) { + m_searchMode = UseSearchProvider; + if (m_searchEngines.isEmpty()) { + m_currentEngine = QStringLiteral("google"); + } else { + m_currentEngine = m_searchEngines.first(); + } + } else { + const int index = m_searchEngines.indexOf(m_currentEngine) + 1; + if (index >= m_searchEngines.count()) { + m_searchMode = FindInThisPage; + } else { + m_currentEngine = m_searchEngines.at(index); + } + } + setIcon(); +} + +void SearchBarPlugin::previousSearchEntry() +{ + if (m_searchMode == FindInThisPage) { + m_searchMode = UseSearchProvider; + if (m_searchEngines.isEmpty()) { + m_currentEngine = QStringLiteral("google"); + } else { + m_currentEngine = m_searchEngines.last(); + } + } else { + const int index = m_searchEngines.indexOf(m_currentEngine) - 1; + if (index <= 0) { + m_searchMode = FindInThisPage; + } else { + m_currentEngine = m_searchEngines.at(index); + } + } + setIcon(); +} + +// Called when activating the combobox (Key_Return, or item in popup or in completionbox) +void SearchBarPlugin::startSearch(const QString &search) +{ + if (m_urlEnterLock || search.isEmpty() || !m_part) { + return; + } + m_timer->stop(); + m_lastSearch = search; + + if (m_searchMode == FindInThisPage) { + KParts::TextExtension *textExt = KParts::TextExtension::childObject(m_part.data()); + if (textExt) { + textExt->findText(search, nullptr); + } + } else if (m_searchMode == UseSearchProvider) { + m_urlEnterLock = true; + const KUriFilterSearchProvider &provider = m_searchProviders.value(m_currentEngine); + KUriFilterData data; + data.setData(provider.defaultKey() + m_delimiter + search); + //kDebug() << "Query:" << (provider.defaultKey() + m_delimiter + search); + if (!KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) { + qWarning() << "Failed to filter using web shortcut:" << provider.defaultKey(); + return; + } + + KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(m_part.data()); + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + KParts::OpenUrlArguments arguments; + KParts::BrowserArguments browserArguments; + browserArguments.setNewTab(true); + if (ext) { + emit ext->createNewWindow(data.uri(), arguments, browserArguments); + } + } else { + if (ext) { + emit ext->openUrlRequest(data.uri()); + if (m_part) { + m_part.data()->widget()->setFocus(); // #152923 + } + } + } + } + + m_searchCombo->addToHistory(search); + m_searchCombo->setItemIcon(0, m_searchIcon); + + m_urlEnterLock = false; +} + +void SearchBarPlugin::setIcon() +{ + if (m_searchMode == FindInThisPage) { + m_searchIcon = QIcon::fromTheme(QStringLiteral("edit-find")).pixmap(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize)); + } else { + const QString engine = (m_currentEngine.isEmpty() ? m_searchEngines.first() : m_currentEngine); + //kDebug() << "Icon Name:" << m_searchProviders.value(engine).iconName(); + const QString iconName = m_searchProviders.value(engine).iconName(); + if (iconName.startsWith(QLatin1Char('/'))) { + m_searchIcon = QPixmap(iconName); + } else { + m_searchIcon = QIcon::fromTheme(iconName).pixmap(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize)); + } + } + + // Create a bit wider icon with arrow + QPixmap arrowmap = QPixmap(m_searchIcon.width() + 5, m_searchIcon.height() + 5); + arrowmap.fill(m_searchCombo->lineEdit()->palette().color(m_searchCombo->lineEdit()->backgroundRole())); + QPainter p(&arrowmap); + p.drawPixmap(0, 2, m_searchIcon); + QStyleOption opt; + opt.state = QStyle::State_None; + opt.rect = QRect(arrowmap.width() - 6, arrowmap.height() - 5, 6, 5); + m_searchCombo->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, m_searchCombo); + p.end(); + m_searchIcon = arrowmap; + m_searchCombo->setIcon(m_searchIcon); + + // Set the placeholder text to be the search engine name... + if (m_searchProviders.contains(m_currentEngine)) { + m_searchCombo->lineEdit()->setPlaceholderText(m_searchProviders.value(m_currentEngine).name()); + } +} + +void SearchBarPlugin::showSelectionMenu() +{ + // Update the configuration, if needed, before showing the menu items... + if (m_reloadConfiguration) { + configurationChanged(); + } + + if (!m_popupMenu) { + m_popupMenu = new QMenu(m_searchCombo); + m_popupMenu->setObjectName(QStringLiteral("search selection menu")); + + if (enableFindInPage()) { + m_popupMenu->addAction(QIcon::fromTheme(QStringLiteral("edit-find")), i18n("Find in This Page"), this, SLOT(useFindInThisPage())); + m_popupMenu->addSeparator(); + } + + for (int i = 0, count = m_searchEngines.count(); i != count; ++i) { + const KUriFilterSearchProvider &provider = m_searchProviders.value(m_searchEngines.at(i)); + QAction *action = m_popupMenu->addAction(QIcon::fromTheme(provider.iconName()), provider.name()); + action->setData(QVariant::fromValue(i)); + } + + m_popupMenu->addSeparator(); + m_popupMenu->addAction(QIcon::fromTheme(QStringLiteral("preferences-web-browser-shortcuts")), i18n("Select Search Engines..."), + this, SLOT(selectSearchEngines())); + connect(m_popupMenu, SIGNAL(triggered(QAction*)), SLOT(menuActionTriggered(QAction*))); + } else { + Q_FOREACH (QAction *action, m_addSearchActions) { + m_popupMenu->removeAction(action); + delete action; + } + m_addSearchActions.clear(); + } + + QList actions = m_popupMenu->actions(); + QAction *before = nullptr; + if (actions.size() > 1) { + before = actions[actions.size() - 2]; + } + + Q_FOREACH (const QString &title, m_openSearchDescs.keys()) { + QAction *addSearchAction = new QAction(m_popupMenu); + addSearchAction->setText(i18n("Add %1...", title)); + m_addSearchActions.append(addSearchAction); + addSearchAction->setData(QVariant::fromValue(title)); + m_popupMenu->insertAction(before, addSearchAction); + } + + m_popupMenu->popup(m_searchCombo->mapToGlobal(QPoint(0, m_searchCombo->height() + 1))); +} + +void SearchBarPlugin::useFindInThisPage() +{ + m_searchMode = FindInThisPage; + setIcon(); +} + +void SearchBarPlugin::menuActionTriggered(QAction *action) +{ + bool ok = false; + const int id = action->data().toInt(&ok); + if (ok) { + m_searchMode = UseSearchProvider; + m_currentEngine = m_searchEngines.at(id); + setIcon(); + m_openSearchManager->setSearchProvider(m_currentEngine); + m_searchCombo->lineEdit()->selectAll(); + return; + } + + m_searchCombo->lineEdit()->setPlaceholderText(QString()); + const QString openSearchTitle = action->data().toString(); + if (!openSearchTitle.isEmpty()) { + const QString openSearchHref = m_openSearchDescs.value(openSearchTitle); + QUrl url; + QUrl openSearchUrl = QUrl(openSearchHref); + if (openSearchUrl.isRelative()) { + const QUrl docUrl = m_part ? m_part.data()->url() : QUrl(); + QString host = docUrl.scheme() + QLatin1String("://") + docUrl.host(); + if (docUrl.port() != -1) { + host += QLatin1String(":") + QString::number(docUrl.port()); + } + url = docUrl.resolved(QUrl(openSearchHref)); + } else { + url = QUrl(openSearchHref); + } + //kDebug() << "Adding open search Engine: " << openSearchTitle << " : " << openSearchHref; + m_openSearchManager->addOpenSearchEngine(url, openSearchTitle); + } +} + +void SearchBarPlugin::selectSearchEngines() +{ + KRun::runCommand(QStringLiteral("kcmshell5 webshortcuts"), (m_part ? m_part.data()->widget() : nullptr)); +} + +void SearchBarPlugin::configurationChanged() +{ + delete m_popupMenu; + m_popupMenu = nullptr; + m_addSearchActions.clear(); + m_searchEngines.clear(); + m_searchProviders.clear(); + + KUriFilterData data; + data.setSearchFilteringOptions(KUriFilterData::RetrievePreferredSearchProvidersOnly); + data.setAlternateDefaultSearchProvider(QStringLiteral("google")); + + if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) { + m_delimiter = data.searchTermSeparator(); + Q_FOREACH (const QString &engine, data.preferredSearchProviders()) { + //kDebug() << "Found search provider:" << engine; + const KUriFilterSearchProvider &provider = data.queryForSearchProvider(engine); + m_searchProviders.insert(provider.desktopEntryName(), provider); + m_searchEngines << provider.desktopEntryName(); + } + } + + //kDebug() << "Found search engines:" << m_searchEngines; + KConfigGroup config = KConfigGroup(KSharedConfig::openConfig(), "SearchBar"); + m_searchMode = (SearchModes) config.readEntry("Mode", static_cast(UseSearchProvider)); + const QString defaultSearchEngine((m_searchEngines.isEmpty() ? QStringLiteral("google") : m_searchEngines.first())); + m_currentEngine = config.readEntry("CurrentEngine", defaultSearchEngine); + m_suggestionEnabled = config.readEntry("SuggestionEnabled", true); + + m_searchCombo->setSuggestionEnabled(m_suggestionEnabled); + m_openSearchManager->setSearchProvider(m_currentEngine); + + m_reloadConfiguration = false; + setIcon(); +} + +void SearchBarPlugin::reloadConfiguration() +{ + // NOTE: We do not directly connect the dbus signal to the configurationChanged + // slot because our slot my be called before the filter plugins, in which case we + // simply end up retrieving the same configuration information from the plugin. + m_reloadConfiguration = true; +} + +void SearchBarPlugin::updateComboVisibility() +{ + if (!m_part) { + return; + } + // NOTE: We hide the search combobox if the embedded kpart is ReadWrite + // because web browsers by their very nature are ReadOnly kparts... + m_searchComboAction->setVisible((!m_part.data()->inherits("ReadWritePart") && + !m_searchComboAction->associatedWidgets().isEmpty())); + m_openSearchDescs.clear(); +} + +void SearchBarPlugin::focusSearchbar() +{ + m_searchCombo->setFocus(Qt::ShortcutFocusReason); +} + +void SearchBarPlugin::searchTextChanged(const QString &text) +{ + // Don't do anything if the user just activated the search for this text + // Popping up suggestions again would just lead to an annoying popup (#231213) + if (m_lastSearch == text) { + return; + } + + // Don't do anything if the user is still pressing on the mouse button + if (qApp->mouseButtons()) { + return; + } + + // 400 ms delay before requesting for suggestions, so we don't flood the provider with suggestion request + m_timer->start(400); +} + +void SearchBarPlugin::requestSuggestion() +{ + m_searchCombo->clearSuggestions(); + + if (m_suggestionEnabled && m_searchMode != FindInThisPage && + m_openSearchManager->isSuggestionAvailable() && + !m_searchCombo->lineEdit()->text().isEmpty()) { + m_openSearchManager->requestSuggestion(m_searchCombo->lineEdit()->text()); + } +} + +void SearchBarPlugin::enableSuggestion(bool enable) +{ + m_suggestionEnabled = enable; +} + +void SearchBarPlugin::HTMLDocLoaded() +{ + if (!m_part || m_part.data()->url().host().isEmpty()) { + return; + } + + // Testcase for this code: http://search.iwsearch.net + KParts::HtmlExtension *ext = KParts::HtmlExtension::childObject(m_part.data()); + KParts::SelectorInterface *selectorInterface = qobject_cast(ext); + + if (selectorInterface) { + //if (headElelement.getAttribute("profile") != "http://a9.com/-/spec/opensearch/1.1/") { + // kWarning() << "Warning: there is no profile attribute or wrong profile attribute in , as specified by open search specification 1.1"; + //} + const QString query(QStringLiteral("head > link[rel=\"search\"][type=\"application/opensearchdescription+xml\"]")); + const QList linkNodes = selectorInterface->querySelectorAll(query, KParts::SelectorInterface::EntireContent); + //kDebug() << "Found" << linkNodes.length() << "links in" << m_part->url(); + Q_FOREACH (const KParts::SelectorInterface::Element &link, linkNodes) { + const QString title = link.attribute(QStringLiteral("title")); + const QString href = link.attribute(QStringLiteral("href")); + //kDebug() << "Found opensearch" << title << href; + m_openSearchDescs.insert(title, href); + // TODO associate this with m_part; we can get descs from multiple tabs here... + } + } +} + +void SearchBarPlugin::openSearchEngineAdded(const QString &name, const QString &searchUrl, const QString &fileName) +{ + //kDebug() << "New Open Search Engine Added: " << name << ", searchUrl " << searchUrl; + + KConfig _service(m_searchProvidersDir + fileName + ".desktop", KConfig::SimpleConfig); + KConfigGroup service(&_service, "Desktop Entry"); + service.writeEntry("Type", "Service"); + service.writeEntry("ServiceTypes", "SearchProvider"); + service.writeEntry("Name", name); + service.writeEntry("Query", searchUrl); + service.writeEntry("Keys", fileName); + // TODO + service.writeEntry("Charset", "" /* provider->charset() */); + + // we might be overwriting a hidden entry + service.writeEntry("Hidden", false); + + // Show the add web shortcut widget + if (!m_addWSWidget) { + m_addWSWidget = new WebShortcutWidget(m_searchCombo); + m_addWSWidget->setWindowFlags(Qt::Popup); + + connect(m_addWSWidget, SIGNAL(webShortcutSet(QString,QString,QString)), + this, SLOT(webShortcutSet(QString,QString,QString))); + } + + QPoint pos = m_searchCombo->mapToGlobal(QPoint(m_searchCombo->width() - m_addWSWidget->width(), m_searchCombo->height() + 1)); + m_addWSWidget->setGeometry(QRect(pos, m_addWSWidget->size())); + m_addWSWidget->show(name, fileName); +} + +void SearchBarPlugin::webShortcutSet(const QString &name, const QString &webShortcut, const QString &fileName) +{ + Q_UNUSED(name); + KConfig _service(m_searchProvidersDir + fileName + ".desktop", KConfig::SimpleConfig); + KConfigGroup service(&_service, "Desktop Entry"); + service.writeEntry("Keys", webShortcut); + _service.sync(); + + // Update filters in running applications including ourselves... + QDBusConnection::sessionBus().send(QDBusMessage::createSignal(QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), QStringLiteral("configure"))); + + // If the providers changed, tell sycoca to rebuild its database... + KBuildSycocaProgressDialog::rebuildKSycoca(m_searchCombo); +} + +void SearchBarPlugin::HTMLLoadingStarted() +{ + // reset the open search availability, so that if there is previously detected engine, + // it will not be shown + m_openSearchDescs.clear(); +} + +void SearchBarPlugin::addSearchSuggestion(const QStringList &suggestions) +{ + m_searchCombo->setSuggestionItems(suggestions); +} + +SearchBarCombo::SearchBarCombo(QWidget *parent) + : KHistoryComboBox(true, parent) +{ + setDuplicatesEnabled(false); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setMaximumWidth(300); + connect(this, SIGNAL(cleared()), SLOT(historyCleared())); + + Q_ASSERT(useCompletion()); + + KConfigGroup config(KSharedConfig::openConfig(), "SearchBar"); + setCompletionMode(static_cast(config.readEntry("CompletionMode", static_cast(KCompletion::CompletionPopup)))); + const QStringList list = config.readEntry("History list", QStringList()); + setHistoryItems(list, true); + Q_ASSERT(currentText().isEmpty()); // KHistoryComboBox calls clearEditText + + m_enableAction = new QAction(i18n("Enable Suggestion"), this); + m_enableAction->setCheckable(true); + connect(m_enableAction, SIGNAL(toggled(bool)), this, SIGNAL(suggestionEnabled(bool))); + + connect(this, SIGNAL(aboutToShowContextMenu(QMenu*)), SLOT(addEnableMenuItem(QMenu*))); + + // use our own item delegate to display our fancy stuff :D + KCompletionBox *box = completionBox(); + box->setItemDelegate(new SearchBarItemDelegate(this)); + connect(lineEdit(), SIGNAL(textEdited(QString)), box, SLOT(setCancelledText(QString))); +} + +SearchBarCombo::~SearchBarCombo() +{ + KConfigGroup config(KSharedConfig::openConfig(), "SearchBar"); + config.writeEntry("History list", historyItems()); + const int mode = completionMode(); + config.writeEntry("CompletionMode", mode); + delete m_enableAction; +} + +const QPixmap &SearchBarCombo::icon() const +{ + return m_icon; +} + +void SearchBarCombo::setIcon(const QPixmap &icon) +{ + m_icon = icon; + const QString editText = currentText(); + if (count() == 0) { + insertItem(0, m_icon, nullptr); + } else { + for (int i = 0; i < count(); i++) { + setItemIcon(i, m_icon); + } + } + setEditText(editText); +} + +void SearchBarCombo::setSuggestionEnabled(bool enable) +{ + m_enableAction->setChecked(enable); +} + +int SearchBarCombo::findHistoryItem(const QString &searchText) +{ + for (int i = 0; i < count(); i++) { + if (itemText(i) == searchText) { + return i; + } + } + + return -1; +} + +void SearchBarCombo::mousePressEvent(QMouseEvent *e) +{ + QStyleOptionComplex opt; + int x0 = QStyle::visualRect(layoutDirection(), style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this), rect()).x(); + + if (e->x() > x0 + 2 && e->x() < lineEdit()->x()) { + emit iconClicked(); + e->accept(); + } else { + KHistoryComboBox::mousePressEvent(e); + } +} + +void SearchBarCombo::historyCleared() +{ + setIcon(m_icon); +} + +void SearchBarCombo::setSuggestionItems(const QStringList &suggestions) +{ + if (!m_suggestions.isEmpty()) { + clearSuggestions(); + } + + m_suggestions = suggestions; + if (!suggestions.isEmpty()) { + const int size = completionBox()->count(); + QListWidgetItem *item = new QListWidgetItem(suggestions.at(0)); + item->setData(Qt::UserRole, "suggestion"); + completionBox()->insertItem(size + 1, item); + const int suggestionCount = suggestions.count(); + for (int i = 1; i < suggestionCount; i++) { + completionBox()->insertItem(size + 1 + i, suggestions.at(i)); + } + completionBox()->popup(); + } +} + +void SearchBarCombo::clearSuggestions() +{ + // Removing items can change the current item in completion box, + // which makes the lineEdit emit textEdited, and we would then + // re-enter this method, so block lineEdit signals. + const bool oldBlock = lineEdit()->blockSignals(true); + int size = completionBox()->count(); + if (!m_suggestions.isEmpty() && size >= m_suggestions.count()) { + for (int i = size - 1; i >= size - m_suggestions.size(); i--) { + completionBox()->takeItem(i); + } + } + m_suggestions.clear(); + lineEdit()->blockSignals(oldBlock); +} + +void SearchBarCombo::addEnableMenuItem(QMenu *menu) +{ + if (menu) { + menu->addAction(m_enableAction); + } +} + +SearchBarItemDelegate::SearchBarItemDelegate(QObject *parent) + : QItemDelegate(parent) +{ +} + +void SearchBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QString userText = index.data(Qt::UserRole).toString(); + QString text = index.data(Qt::DisplayRole).toString(); + + // Get item data + if (!userText.isEmpty()) { + // This font is for the "information" text, small size + italic + gray in color + QFont usrTxtFont = option.font; + usrTxtFont.setItalic(true); + usrTxtFont.setPointSize(6); + + QFontMetrics usrTxtFontMetrics(usrTxtFont); + int width = usrTxtFontMetrics.width(userText); + QRect rect(option.rect.x(), option.rect.y(), option.rect.width() - width, option.rect.height()); + QFontMetrics textFontMetrics(option.font); + QString elidedText = textFontMetrics.elidedText(text, + Qt::ElideRight, option.rect.width() - width - option.decorationSize.width()); + + QAbstractItemModel *itemModel = const_cast(index.model()); + itemModel->setData(index, elidedText, Qt::DisplayRole); + QItemDelegate::paint(painter, option, index); + itemModel->setData(index, text, Qt::DisplayRole); + + painter->setFont(usrTxtFont); + painter->setPen(QPen(QColor(Qt::gray))); + painter->drawText(option.rect, Qt::AlignRight, userText); + + // Draw a separator above this item + if (index.row() > 0) { + painter->drawLine(option.rect.x(), option.rect.y(), option.rect.x() + option.rect.width(), option.rect.y()); + } + } else { + QItemDelegate::paint(painter, option, index); + } +} + +bool SearchBarPlugin::enableFindInPage() const +{ + return true; +} + +#include "searchbar.moc" diff --git a/plugins/searchbar/searchbar.desktop b/plugins/searchbar/searchbar.desktop new file mode 100644 index 0000000..014fb66 --- /dev/null +++ b/plugins/searchbar/searchbar.desktop @@ -0,0 +1,137 @@ +[Desktop Entry] +Icon=system-search +Type=Service +X-KDE-Library=searchbar +X-KDE-PluginInfo-Author=Arend van Beelen jr. +X-KDE-PluginInfo-Email=arend@auton.nl +X-KDE-PluginInfo-Name=searchbar +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Extensions +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Search Bar +Name[ar]=شريط البحث +Name[ast]=Barra de gueta +Name[be]=Панель пошуку +Name[bg]=Лента за търсене +Name[bs]=Pretraživačka traka +Name[ca]=Barra de cerca +Name[ca@valencia]=Barra de cerca +Name[cs]=Panel pro vyhledávání +Name[da]=Søgelinje +Name[de]=Suchleiste +Name[el]=Γραμμή αναζήτησης +Name[en_GB]=Search Bar +Name[eo]=Serĉbreto +Name[es]=Barra de búsqueda +Name[et]=Otsimisriba +Name[eu]=Bilaketa-barra +Name[fi]=Hakurivi +Name[fr]=Barre de recherche +Name[ga]=Barra Cuardaigh +Name[gl]=Barra de buscas +Name[he]=סרגל חיפוש +Name[hne]=खोज पट्टी +Name[hr]=Traka za pretragu +Name[hu]=Keresősáv +Name[ia]=Barra de cerca +Name[id]=Bilah Pencarian +Name[is]=Leitarslá +Name[it]=Barra di ricerca +Name[ja]=検索バー +Name[kk]=Іздеу панелі +Name[km]=របារ​ស្វែងរក +Name[ko]=찾기 도구 모음 +Name[ku]=Darikê Lêgerînê +Name[lt]=Paieškos juosta +Name[lv]=Meklēšanas josla +Name[mr]=शोध पट्टी +Name[ms]=Bar Carian +Name[nb]=Søkelinje +Name[nds]=Söökbalken +Name[nl]=Zoekbalk +Name[nn]=Søkjelinje +Name[pa]=ਖੋਜ ਪੱਟੀ +Name[pl]=Pasek wyszukiwania +Name[pt]=Barra de Procura +Name[pt_BR]=Barra de pesquisa +Name[ro]=Bară de căutare +Name[ru]=Панель поиска +Name[sk]=Lišta pre vyhľadávanie +Name[sl]=Iskalna vrstica +Name[sr]=Трака претраге +Name[sr@ijekavian]=Трака претраге +Name[sr@ijekavianlatin]=Traka pretrage +Name[sr@latin]=Traka pretrage +Name[sv]=Sökrad +Name[tg]=Лавҳаи ҷустуҷӯӣ +Name[th]=แถบการค้นหา +Name[tr]=Arama Çubuğu +Name[ug]=ئىزدەش بالدىقى +Name[uk]=Панель пошуку +Name[wa]=Båre di cweraedje +Name[x-test]=xxSearch Barxx +Name[zh_CN]=搜索栏 +Name[zh_TW]=搜尋列 +Comment=Provides a text box for easier access to search engines like Google. +Comment[ar]=تزود صندوق النص بنفاذ سريع لمحركات البحث مثل جوجل +Comment[ast]=Apurre una caxa de testu pa un accesu más fácil a los motores de gueta como Google. +Comment[bg]=Текстово поле за лесен достъп до търсачки като Гугъл +Comment[bs]=Omogućava polje za unos teksta za lakši pristup pretraživačima poput Google-a. +Comment[ca]=Proporciona un quadre de text per a un accés més fàcil als motors de cerca com el Google. +Comment[ca@valencia]=Proporciona un quadre de text per a un accés més fàcil als motors de cerca com el Google. +Comment[cs]=Poskytuje textové pole pro snazší přístup k vyhledávačům, jako je Google. +Comment[da]=Tilføjer en søgelinje der giver nem adgang til søgemaskiner som Google. +Comment[de]=Zeigt ein Eingabefeld für direkten Zugriff auf Suchmaschinen wie Google. +Comment[el]=Σας παρουσιάζει ένα πεδίο κειμένου για γρήγορη πρόσβαση σε μηχανές αναζήτησης όπως το Google. +Comment[en_GB]=Provides a text box for easier access to search engines like Google. +Comment[es]=Proporciona un área de texto para facilitar el acceso a motores de búsqueda,como Google. +Comment[et]=Võimaldab kasutada tekstikasti kiireks ligipääsuks otsingumootoritele, nt. Google. +Comment[eu]=Testu-koadro bat eskaintzen du Google bezalako bilaketa-motorrak errazago atzitzeko +Comment[fi]=Hakurivi mahdollistaa Googlen tapaisten hakukoneiden helpon käytön. +Comment[fr]=Fournit une boîte de texte pour un accès simplifié aux moteurs de recherche comme Google. +Comment[ga]=Soláthraíonn sé seo bosca téacs a thugann rochtain níos fusa ar innill chuardaigh cosúil le Google. +Comment[gl]=Fornece unha caixa de texto para acceder directamente a motores de busca como Google. +Comment[he]=מספק תיבת טקסט עבור גישה קלה למנועי חיפוש דוגמת Google. +Comment[hr]=Daje tekstualno polje za lakši pristup pretraživačima kao što je Google. +Comment[hu]=Egy szövegdobozt biztosít az egyszerűbb hozzáférésért az olyan keresőmotorokhoz, mint a Google. +Comment[ia]=Forni un quadrato de texto per un accesso plus facile a motores de cerca como Google. +Comment[id]=Menyediakan kotak teks untuk akses lebih mudah ke mesin pencari +Comment[is]=Birtir textareit til að auðvelda aðgang að leitarvélum á borð við Google +Comment[it]=Fornisce una casella di testo per un accesso più facile ai motori di ricerca come Google. +Comment[ja]=Google のような検索エンジンに簡単にアクセスできるテキストボックスを提供します。 +Comment[kk]=Google секілді іздегіштерге оңай қатынасу жолы. +Comment[km]=ផ្ដល់​ប្រអប់​អត្ថបទ​សម្រាប់​ការ​ចូល​ដំណើរ​ការ​ងាយ​ស្រួល​ដល់​ម៉ាស៊ីន​ស្វែងរក ដូច​ជា Google ។ +Comment[ko]=Google과 같은 검색 엔진에 쉽게 접근하는 텍스트 상자입니다. +Comment[lt]=Rodo tekstinį lauką, lengvam paieškos variklių, tokių kaip Google, naudojimui. +Comment[lv]=Nodrošina ievades lauku ērtākai meklēšanai tīmeklī ar, piemēram, Google. +Comment[mr]=गूगल सारख्या शोध इंजिना कडे सहजपणे जाण्याकरिता मजकूर पट्टी +Comment[nb]=Viser et tekstvindu som gir lett tilgang til søkemotorer slik som Google. +Comment[nds]=Stellt en Textfeld för den Direkttogriep op Söökmaschinen as "Google" praat. +Comment[nl]=Levert een tekstvak voor snelle toegang tot zoekmachines zoals Google. +Comment[nn]=Viser eit tekstvindauge som gjev enkel tilgang til søkjemotorar som Google +Comment[pa]=ਖੋਜ ਇੰਜਣ, ਜਿਵੇਂ ਕਿ ਗੂਗਲ ਦੀ ਸੌਖੀ ਵਰਤੋਂ ਲਈ ਇੱਕ ਟੈਕਸਟ-ਬਾਕਸ ਦਿੰਦਾ ਹੈ +Comment[pl]=Zapewnia pole tekstowe w celu łatwiejszego dostępu do wyszukiwarek takich jak Google. +Comment[pt]=Dá-lhe um campo de texto para acesso directo a motores de busca como o Google. +Comment[pt_BR]=Fornece uma caixa de texto para fácil acesso aos mecanismos de pesquisa como o Google. +Comment[ro]=Furnizează o căsuță de text pentru acces ușor la motoare de căutare cum ar fi Google. +Comment[ru]=Поле ввода для отправки запросов к поисковым машинам типа Google. +Comment[sk]=Pre jednoduchší prístup k vyhľadávačom poskytuje textové pole, ako je napríklad Google. +Comment[sl]=Besedilno polje za lažji dostop do iskalnikov, kot je Google. +Comment[sr]=Даје поље за унос текста за лакши приступ претраживачима попут Гугла. +Comment[sr@ijekavian]=Даје поље за унос текста за лакши приступ претраживачима попут Гугла. +Comment[sr@ijekavianlatin]=Daje polje za unos teksta za lakši pristup pretraživačima poput Googlea. +Comment[sr@latin]=Daje polje za unos teksta za lakši pristup pretraživačima poput Googlea. +Comment[sv]=Visar en textruta för enklare åtkomst av söktjänster som Google. +Comment[tg]=Барои ҷустуҷӯӣ кардан дар Интернет, масалан ба воситаи Google, сатри ҷустуҷӯӣ дастрас мекунад. +Comment[th]=แสดงกล่องข้อความเพื่อเรียกใช้บริการค้นหาคล้ายของกูเกิลได้ง่ายขึ้น +Comment[tr]=Google gibi arama motorloruna kolayca ulaşmak için yazı kutususu sağlar. +Comment[ug]=گۇگىلغا ئوخشاش ئىزدەش ماتورىنى زىيارەت قىلىشقا قۇلايلىق تېكىست رامكىسى بىلەن تەمىنلەيدۇ. +Comment[uk]=Надає прямий доступ до пошукових систем таких, як Google. +Comment[wa]=Dene ene boesse di tecse po moussî pus åjheymint dins des moteurs di cweraedje come Google. +Comment[x-test]=xxProvides a text box for easier access to search engines like Google.xx +Comment[zh_CN]=提供一个可以易于访问像 Google 这样的搜索引擎的文本框 +Comment[zh_TW]=提供文字盒以方便使用像 Google 之類的搜尋引擎。 +X-KDE-ParentApp=konqueror diff --git a/plugins/searchbar/searchbar.h b/plugins/searchbar/searchbar.h new file mode 100644 index 0000000..abf5ddc --- /dev/null +++ b/plugins/searchbar/searchbar.h @@ -0,0 +1,241 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Arend van Beelen jr. + Copyright (C) 2009 Fredy Yanardi + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SEARCHBAR_PLUGIN +#define SEARCHBAR_PLUGIN + +#include +#include +#include + +#include +#include +#include + +//KDELibs4Support + + +namespace KParts +{ +class Part; +class ReadOnlyPart; +} + +class OpenSearchManager; +class WebShortcutWidget; + +class QAction; +class QMenu; +class QTimer; +class QWidgetAction; + +/** + * Combo box which catches mouse clicks on the pixmap. + */ +class SearchBarCombo : public KHistoryComboBox +{ + Q_OBJECT + +public: + /** + * Constructor. + */ + SearchBarCombo(QWidget *parent); + + /** + * Destructor. + */ + ~SearchBarCombo() override; + + /** + * Returns the icon currently displayed in the combo box. + */ + const QPixmap &icon() const; + + /** + * Sets the icon displayed in the combo box. + */ + void setIcon(const QPixmap &icon); + + /** + * Check/uncheck the menu entry for setting suggestion according to enable + */ + void setSuggestionEnabled(bool enable); + + /** + * Finds a history item by its text. + * @return The item number, or -1 if the item is not found. + */ + int findHistoryItem(const QString &text); + + /** + * Sets whether the plugin is active. It can be inactive + * in case the current Konqueror part isn't a KHTML part. + */ + void setPluginActive(bool pluginActive); + + /** + * Set the suggestion items after to be displayed by this ComboBox + * This method will automatically pop up the ComboBox's list. + */ + void setSuggestionItems(const QStringList &suggestions); + + /** + * Clear all previously set suggestion items for this ComboBox + */ + void clearSuggestions(); + +Q_SIGNALS: + /** + * Emitted when the icon was clicked. + */ + void iconClicked(); + + /** + * Emitted when the suggestion enable state is changed via the popup menu + */ + void suggestionEnabled(bool enable); + +protected: + /** + * Captures mouse clicks and emits iconClicked() if the icon + * was clicked. + */ + void mousePressEvent(QMouseEvent *e) override; + +private Q_SLOTS: + void historyCleared(); + void addEnableMenuItem(QMenu *menu); + +private: + QPixmap m_icon; + QAction *m_enableAction; + QStringList m_suggestions; +}; + +/** + * Plugin that provides a search bar for Konqueror. This search bar is located + * next to the location bar and will show a small icon indicating the search + * provider it will use. + * + * @author Arend van Beelen jr. + * @version $Id$ + */ +class SearchBarPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + /** Possible search modes */ + enum SearchModes { FindInThisPage = 0, UseSearchProvider }; + + SearchBarPlugin(QObject *parent, + const QVariantList &); + ~SearchBarPlugin() override; + +protected: + bool eventFilter(QObject *o, QEvent *e) override; + +private Q_SLOTS: + /** + * Starts a search by putting the query URL from the selected + * search provider in the locationbar and calling goURL() + */ + void startSearch(const QString &search); + + /** + * Sets the icon to indicate which search engine is used. + */ + void setIcon(); + + /** + * Opens the selection menu. + */ + void showSelectionMenu(); + + void useFindInThisPage(); + void menuActionTriggered(QAction *); + void selectSearchEngines(); + void configurationChanged(); + void reloadConfiguration(); + + /** + * Show or hide the combo box + */ + void updateComboVisibility(); + + void focusSearchbar(); + + void searchTextChanged(const QString &text); + + void addSearchSuggestion(const QStringList &suggestion); + + void requestSuggestion(); + + void enableSuggestion(bool enable); + + void HTMLLoadingStarted(); + + void HTMLDocLoaded(); + + void openSearchEngineAdded(const QString &name, const QString &searchUrl, const QString &fileName); + + void webShortcutSet(const QString &name, const QString &webShortcut, const QString &fileName); + +private: + bool enableFindInPage() const; + void nextSearchEntry(); + void previousSearchEntry(); + + QWeakPointer m_part; + SearchBarCombo *m_searchCombo; + QWidgetAction *m_searchComboAction; + QList m_addSearchActions; + QMenu *m_popupMenu; + WebShortcutWidget *m_addWSWidget; + QPixmap m_searchIcon; + SearchModes m_searchMode; + QString m_providerName; + bool m_urlEnterLock; + QString m_lastSearch; + QString m_currentEngine; + QStringList m_searchEngines; + QMap m_searchProviders; + QChar m_delimiter; + OpenSearchManager *m_openSearchManager; + QTimer *m_timer; + bool m_suggestionEnabled; + QMap m_openSearchDescs; + bool m_reloadConfiguration; + QString m_searchProvidersDir; +}; + +/** + * An item delegate for combo box completion items, to give some fancy stuff + * to the completion items + */ +class SearchBarItemDelegate : public QItemDelegate +{ +public: + SearchBarItemDelegate(QObject *parent = nullptr); + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; + +#endif // SEARCHBAR_PLUGIN diff --git a/plugins/searchbar/searchbar.rc b/plugins/searchbar/searchbar.rc new file mode 100644 index 0000000..e98791b --- /dev/null +++ b/plugins/searchbar/searchbar.rc @@ -0,0 +1,6 @@ + + +Search Toolbar + + + diff --git a/plugins/shellcmdplugin/CMakeLists.txt b/plugins/shellcmdplugin/CMakeLists.txt new file mode 100644 index 0000000..5702b1c --- /dev/null +++ b/plugins/shellcmdplugin/CMakeLists.txt @@ -0,0 +1,17 @@ + +########### next target ############### +find_package(KF5 REQUIRED Su) +add_definitions(-DTRANSLATION_DOMAIN=\"kshellcmdplugin\") +set(konq_shellcmdplugin_PART_SRCS kshellcmdexecutor.cpp kshellcmddialog.cpp kshellcmdplugin.cpp ) + + +add_library(konq_shellcmdplugin MODULE ${konq_shellcmdplugin_PART_SRCS}) + + +target_link_libraries(konq_shellcmdplugin KF5::Parts KF5::Su KF5::KDELibs4Support) + +install(TARGETS konq_shellcmdplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### +install( FILES kshellcmdplugin.rc kshellcmdplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/dolphinpart/kpartplugins ) diff --git a/plugins/shellcmdplugin/Messages.sh b/plugins/shellcmdplugin/Messages.sh new file mode 100644 index 0000000..8cd9afa --- /dev/null +++ b/plugins/shellcmdplugin/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc *.ui *.kcfg >> rc.cpp +$XGETTEXT *.cpp -o $podir/kshellcmdplugin.pot diff --git a/plugins/shellcmdplugin/kshellcmddialog.cpp b/plugins/shellcmdplugin/kshellcmddialog.cpp new file mode 100644 index 0000000..32a04a8 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmddialog.cpp @@ -0,0 +1,102 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Alexander Neundorf + + 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. +*/ + +// Own +#include "kshellcmddialog.h" + +// Qt +#include +#include +#include + +// KDE +#include +#include + +// Local +#include "kshellcmdexecutor.h" + +KShellCommandDialog::KShellCommandDialog(const QString &title, const QString &command, QWidget *parent, bool modal) + : KDialog(parent) +{ + setModal(modal); + setButtons(KDialog::None); + QWidget *w = new QWidget(this); + QVBoxLayout *box = new QVBoxLayout; + w->setLayout(box); + setMainWidget(w); + + QLabel *label = new QLabel(title, this); + m_shell = new KShellCommandExecutor(command, this); + + cancelButton = new QPushButton(this); + KGuiItem::assign(cancelButton, KStandardGuiItem::cancel()); + closeButton = new QPushButton(this); + KGuiItem::assign(closeButton, KStandardGuiItem::close()); + closeButton->setDefault(true); + + label->resize(label->sizeHint()); + m_shell->resize(m_shell->sizeHint()); + closeButton->setFixedSize(closeButton->sizeHint()); + cancelButton->setFixedSize(cancelButton->sizeHint()); + + box->addWidget(label, 0); + box->addWidget(m_shell, 1); + + QHBoxLayout *hlayout = new QHBoxLayout(); + box->addLayout(hlayout); + hlayout->addWidget(cancelButton); + hlayout->addWidget(closeButton); + + m_shell->setFocus(); + + connect(cancelButton, &QAbstractButton::clicked, m_shell, &KShellCommandExecutor::slotFinished); + connect(m_shell, &KShellCommandExecutor::finished, this, &KShellCommandDialog::disableStopButton); + connect(closeButton, &QAbstractButton::clicked, this, &KShellCommandDialog::slotClose); +} + +KShellCommandDialog::~KShellCommandDialog() +{ + delete m_shell; + m_shell = nullptr; +} + +void KShellCommandDialog::disableStopButton() +{ + cancelButton->setEnabled(false); +} + +void KShellCommandDialog::slotClose() +{ + delete m_shell; + m_shell = nullptr; + accept(); +} + +//blocking +int KShellCommandDialog::executeCommand() +{ + if (m_shell == nullptr) { + return 0; + } + //kDebug()<<"---------- KShellCommandDialog::executeCommand()"; + m_shell->exec(); + return exec(); +} + diff --git a/plugins/shellcmdplugin/kshellcmddialog.h b/plugins/shellcmdplugin/kshellcmddialog.h new file mode 100644 index 0000000..b4860b0 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmddialog.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Alexander Neundorf + + 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 KSHELLCMDDIALOG_H +#define KSHELLCMDDIALOG_H + +#include + +class KShellCommandExecutor; +class QPushButton; + +class KShellCommandDialog: public KDialog +{ + Q_OBJECT +public: + KShellCommandDialog(const QString &title, const QString &command, QWidget *parent = nullptr, bool modal = false); + ~KShellCommandDialog() override; + //blocking + int executeCommand(); +protected: + + KShellCommandExecutor *m_shell; + QPushButton *cancelButton; + QPushButton *closeButton; +protected Q_SLOTS: + void disableStopButton(); + void slotClose(); +}; + +#endif // KSHELLCMDDIALOG_H diff --git a/plugins/shellcmdplugin/kshellcmdexecutor.cpp b/plugins/shellcmdplugin/kshellcmdexecutor.cpp new file mode 100644 index 0000000..032cd3c --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdexecutor.cpp @@ -0,0 +1,150 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Alexander Neundorf + + 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. +*/ +#include "kshellcmdexecutor.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace KDESu; + +KShellCommandExecutor::KShellCommandExecutor(const QString &command, QWidget *parent) + : QTextEdit(parent) + , m_shellProcess(nullptr) + , m_command(command) + , m_readNotifier(nullptr) + , m_writeNotifier(nullptr) +{ + setAcceptRichText(false); + setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + setReadOnly(true); +} + +KShellCommandExecutor::~KShellCommandExecutor() +{ + if (m_shellProcess != nullptr) { + ::kill(m_shellProcess->pid() + 1, SIGTERM); + delete m_shellProcess; + }; +} + +int KShellCommandExecutor::exec() +{ + //kDebug()<<"---------- KShellCommandExecutor::exec()"; + setText(QLatin1String("")); + if (m_shellProcess != nullptr) { + ::kill(m_shellProcess->pid(), SIGTERM); + delete m_shellProcess; + }; + delete m_readNotifier; + delete m_writeNotifier; + + m_shellProcess = new PtyProcess(); + m_shellProcess->setTerminal(true); + + QList args; + args += "-c"; + args += m_command.toLocal8Bit(); + //kDebug()<<"------- executing: "<exec(shell, args); + if (ret < 0) { + //kDebug()<<"could not execute"; + delete m_shellProcess; + m_shellProcess = nullptr; + return 0; + } + + m_readNotifier = new QSocketNotifier(m_shellProcess->fd(), QSocketNotifier::Read, this); + m_writeNotifier = new QSocketNotifier(m_shellProcess->fd(), QSocketNotifier::Write, this); + m_writeNotifier->setEnabled(false); + connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readDataFromShell())); + connect(m_writeNotifier, SIGNAL(activated(int)), this, SLOT(writeDataToShell())); + + return 1; +} + +void KShellCommandExecutor::readDataFromShell() +{ + //kDebug()<<"--------- reading ------------"; + char buffer[16 * 1024]; + int bytesRead =::read(m_shellProcess->fd(), buffer, 16 * 1024 - 1); + //0-terminate the buffer + //process exited + if (bytesRead <= 0) { + slotFinished(); + } else if (bytesRead > 0) { + //kDebug()<<"***********************\n"<append(QString::fromLocal8Bit(buffer)); + setAcceptRichText(false); + }; +} + +void KShellCommandExecutor::writeDataToShell() +{ + //kDebug()<<"--------- writing ------------"; + bool ok; + QString str = KInputDialog::getText(QString(), + i18n("Input Required:"), QString(), &ok, this); + if (ok) { + QByteArray input = str.toLocal8Bit(); + ::write(m_shellProcess->fd(), input, input.length()); + ::write(m_shellProcess->fd(), "\n", 1); + } else { + slotFinished(); + } + + if (m_writeNotifier) { + m_writeNotifier->setEnabled(false); + } +} + +void KShellCommandExecutor::slotFinished() +{ + setAcceptRichText(false); + if (m_shellProcess != nullptr) { + delete m_readNotifier; + m_readNotifier = nullptr; + delete m_writeNotifier; + m_writeNotifier = nullptr; + + //kDebug()<<"slotFinished: pid: "<pid(); + ::kill(m_shellProcess->pid() + 1, SIGTERM); + ::kill(m_shellProcess->pid(), SIGTERM); + }; + delete m_shellProcess; + m_shellProcess = nullptr; + emit finished(); +} + diff --git a/plugins/shellcmdplugin/kshellcmdexecutor.h b/plugins/shellcmdplugin/kshellcmdexecutor.h new file mode 100644 index 0000000..8487d54 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdexecutor.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Alexander Neundorf + + 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 KSHELLCMDEXECUTOR_H +#define KSHELLCMDEXECUTOR_H + +#include + +namespace KDESu +{ +class PtyProcess; +} +class QSocketNotifier; + +class KShellCommandExecutor: public QTextEdit +{ + Q_OBJECT +public: + explicit KShellCommandExecutor(const QString &command, QWidget *parent = nullptr); + ~KShellCommandExecutor() override; + int exec(); +Q_SIGNALS: + void finished(); +public Q_SLOTS: + void slotFinished(); +protected: + KDESu::PtyProcess *m_shellProcess; + QString m_command; + QSocketNotifier *m_readNotifier; + QSocketNotifier *m_writeNotifier; +protected Q_SLOTS: + void readDataFromShell(); + void writeDataToShell(); +}; + +#endif // KSHELLCMDEXECUTOR_H diff --git a/plugins/shellcmdplugin/kshellcmdplugin.cpp b/plugins/shellcmdplugin/kshellcmdplugin.cpp new file mode 100644 index 0000000..5e21206 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdplugin.cpp @@ -0,0 +1,99 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure + + 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 "kshellcmdplugin.h" +#include "kshellcmddialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +KShellCmdPlugin::KShellCmdPlugin(QObject *parent, const QVariantList &) + : KParts::Plugin(parent) +{ + if (!KAuthorized::authorize(QStringLiteral("shell_access"))) { + return; + } + + QAction *action = actionCollection()->addAction(QStringLiteral("executeshellcommand")); + action->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); + action->setText(i18n("&Execute Shell Command...")); + connect(action, &QAction::triggered, this, &KShellCmdPlugin::slotExecuteShellCommand); + actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_E)); +} + +void KShellCmdPlugin::slotExecuteShellCommand() +{ + KParts::ReadOnlyPart *part = qobject_cast(parent()); + if (!part) { + KMessageBox::sorry(nullptr, i18n("KShellCmdPlugin::slotExecuteShellCommand: Program error, please report a bug.")); + return; + } + + QUrl url = KIO::NetAccess::mostLocalUrl(part->url(), nullptr); + if (!url.isLocalFile()) { + KMessageBox::sorry(part->widget(), i18n("Executing shell commands works only on local directories.")); + return; + } + + QString path; + KParts::FileInfoExtension *ext = KParts::FileInfoExtension::childObject(part); + + if (ext && ext->hasSelection() && (ext->supportedQueryModes() & KParts::FileInfoExtension::SelectedItems)) { + KFileItemList list = ext->queryFor(KParts::FileInfoExtension::SelectedItems); + QStringList fileNames; + Q_FOREACH (const KFileItem &item, list) { + fileNames << item.name(); + } + path = KShell::joinArgs(fileNames); + } + + if (path.isEmpty()) { + path = KShell::quoteArg(url.toLocalFile()); + } + + bool ok; + QString cmd = KInputDialog::getText(i18nc("@title:window", "Execute Shell Command"), + i18n("Execute shell command in current directory:"), + path, &ok, part->widget()); + if (ok) { + QString exeCmd; + exeCmd = QStringLiteral("cd "); + exeCmd += KShell::quoteArg(part->url().path()); + exeCmd += QLatin1String("; "); + exeCmd += cmd; + + KShellCommandDialog *dlg = new KShellCommandDialog(i18n("Output from command: \"%1\"", cmd), exeCmd, part->widget(), true); + dlg->resize(500, 300); + dlg->executeCommand(); + delete dlg; + } +} + +K_PLUGIN_FACTORY(KonqShellCmdPluginFactory, registerPlugin();) + +#include "kshellcmdplugin.moc" + diff --git a/plugins/shellcmdplugin/kshellcmdplugin.desktop b/plugins/shellcmdplugin/kshellcmdplugin.desktop new file mode 100644 index 0000000..5e48afa --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdplugin.desktop @@ -0,0 +1,187 @@ +[Desktop Entry] +Type=Service +X-KDE-PluginInfo-Author=Alexander Neundorf +X-KDE-PluginInfo-Email=neundorf@kde.org +X-KDE-PluginInfo-Name=kshellcmdplugin +X-KDE-PluginInfo-Version=3.4 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-ParentApp=konqueror +Icon=run +Name=Shell Command Plugin +Name[af]=Opdrag tolk inprop module +Name[ar]=ملحق أمر الصدَفة +Name[as]=শ্বেল আদেশৰ প্লাগ-ইন +Name[ast]=Complementu de comandos de la shell +Name[be]=Утулка выканання каманды ў абалонцы +Name[be@latin]=Plugin zahadaŭ abałonki +Name[bg]=Изпълнение на команда +Name[bn]=শেল কমান্ড প্লাগ-ইন +Name[bn_IN]=শেল কমান্ডের প্লাগ-ইন +Name[bs]=Priključak za naredbe školjke +Name[ca]=Connector d'ordres +Name[ca@valencia]=Connector d'ordres +Name[cs]=Modul shellového příkazu +Name[csb]=Wtëkôcz pòlétu pòwłoczi +Name[da]=Plugin for skalkommando +Name[de]=Shell-Befehl-Erweiterung +Name[el]=Πρόσθετο εντολών κελύφους +Name[en_GB]=Shell Command Plugin +Name[eo]=Ŝelkomanda kromaĵo +Name[es]=Complemento para ejecutar órdenes +Name[et]=Shellikäsu plugin +Name[eu]=Shell-eko komandoentzako plugina +Name[fa]=وصله فرمان پوسته +Name[fi]=Komentoriviliitännäinen +Name[fr]=Module externe de ligne de commandes +Name[fy]=Flueslkommando-plugin +Name[ga]=Breiseán Ordaithe Blaoisce +Name[gl]=Complemento de orde de intérprete de ordes +Name[gu]=શેલ આદેશ પ્લગઇન +Name[he]=תוסף פקודות מעטפת +Name[hi]=शेल कमांड प्लगइन +Name[hne]=सेल कमांड प्लगइन +Name[hr]=Dodatak za naredbe u ljuski +Name[hsb]=zašćěpka za terminalowe přikazy +Name[hu]=Parancsvégrehajtó modul +Name[ia]=Plugin de Commando Shell +Name[id]=Plugin Perintah Shell +Name[is]=Skeljarskipunar íforrit +Name[it]=Estensione per i comandi da shell +Name[ja]=シェルコマンドプラグイン +Name[ka]=გარსისს ბრძანების მოდული +Name[kk]=Команда жолы +Name[km]=កម្មវិធី​ជំនួយ​ពាក្យ​បញ្ជា​សែល +Name[kn]=ಆದೇಶಗ್ರಾಹಿ (ಶೆಲ್) ಆದೇಶ ಮಿಳಿತಾನ್ವಯ (ಪ್ಲಗಿನ್) +Name[ko]=셸 명령 플러그인 +Name[ku]=Pêveka Fermanên Shell +Name[lt]=Apvalkalo komandų priedas +Name[lv]=Čaulas komandas spraudnis +Name[mai]=शेल कमांड प्लगइन +Name[mk]=Приклучок за команда за школка +Name[ml]=ഷെല്‍ ആജ്ഞാ സംയോജകം +Name[mr]=शेल आदेश प्लगइन +Name[ms]=Plugin Arahan Shell +Name[nb]=Programtillegg for skallkommandoer +Name[nds]=Moduul för Konsoolbefehlen +Name[ne]=शेल आदेश प्लगइन +Name[nl]=Shellcommando-plugin +Name[nn]=Programtillegg for skalkommandoar +Name[or]=Shell ନିର୍ଦ୍ଦେଶ ପ୍ଲଗଇନ +Name[pa]=ਸੈੱਲ ਕਮਾਂਡ ਪਲੱਗਇਨ +Name[pl]=Wtyczka polecenia powłoki +Name[pt]='Plugin' de Execução de Comandos +Name[pt_BR]=Plugin de comandos do shell +Name[ro]=Plugin shell pentru comenzi +Name[ru]=Выполнение команды +Name[se]=Skálžogohččunlassemodula +Name[si]=ශෙල් විධාන ප්ලගින +Name[sk]=Modul pre príkazy shellu +Name[sl]=Lupinski ukazi +Name[sr]=Прикључак за наредбе шкољке +Name[sr@ijekavian]=Прикључак за наредбе шкољке +Name[sr@ijekavianlatin]=Priključak za naredbe školjke +Name[sr@latin]=Priključak za naredbe školjke +Name[sv]=Insticksprogram för skalkommando +Name[ta]=முனைய ஆணை செருகி +Name[te]=షెల్ ఆదేశం ప్లగ్ఇన్ +Name[tg]=Плагини иҷрои фармон +Name[th]=ส่วนเสริมสำหรับป้อนคำสั่งเชลล์ +Name[tr]=Uçbirim Komut Eklentisi +Name[ug]=Shell بۇيرۇق قىستۇرمىسى +Name[uk]=Додаток командної оболонки +Name[vi]=Bổ sung lệnh trình bao +Name[wa]=Tchôke-divins roye di comande +Name[x-test]=xxShell Command Pluginxx +Name[zh_CN]=Shell 命令插件 +Name[zh_TW]=Shell 命令外掛程式 +Comment=Shell Command Plugin for Konqueror +Comment[af]=Opdrag tolk inprop module vir Konqueror +Comment[ar]=ملحق أمر الصدَفة لكونكيورر +Comment[as]=Konqueror ৰ কাৰণে শ্বেল আদেশৰ প্লাগ-ইন +Comment[ast]=Complementu de comandos de la shell pa Konqueror +Comment[be]=Утулка выканання каманды ў абалонцы для Konqueror +Comment[be@latin]=Plugin zahadaŭ abałonki dla prahramy „Konqueror” +Comment[bg]=Приставка за изпълнение на команда на браузъра +Comment[bn]=কনকরার-এর জন্য শেল কমান্ড প্লাগ-ইন +Comment[bn_IN]=Konqueror-র সাথে ব্যবহারযোগ্য শেল কমান্ড প্লাগ-ইন +Comment[bs]=Priključak za naredbe školjke za K‑osvajač +Comment[ca]=Connector d'ordres per al Konqueror +Comment[ca@valencia]=Connector d'ordres per al Konqueror +Comment[cs]=Modul shellového příkazu pro Konqueror +Comment[csb]=Wtëkôcz pòlétu pòwłoczi dlô Konquerora +Comment[da]=Plugin for skalkommandon i Konqueror +Comment[de]=Eine Shell-Befehl-Erweiterung für Konqueror +Comment[el]=Πρόσθετο εντολών κελύφους για τον Konqueror +Comment[en_GB]=Shell Command Plugin for Konqueror +Comment[eo]=Ŝelkomanda kromaĵo por Konkeranto +Comment[es]=Complemento para ejecutar órdenes desde Konqueror +Comment[et]=Konquerori shellikäsu plugin +Comment[eu]=Shell-eko komandoentzako plugina Konqueror-entzako +Comment[fa]=وصله فرمان پوسته برای Konqueror +Comment[fi]=Konquerorin komentoriviliitännäinen +Comment[fr]=Module externe de lignes de commande pour Konqueror +Comment[fy]=In flueskommando-plugin foar Konqueror +Comment[ga]=Breiseán Ordaithe Blaoisce le haghaidh Konqueror +Comment[gl]=Complemento de orde de intérprete de ordes para Konqueror +Comment[gu]=કોન્કરર માટે શેલ આદેશ પ્લગઇન +Comment[he]=תוסף פקודות מעטפת ל־Konqueror +Comment[hi]=कॉन्करर के लिए शेल कमांड प्लगइन +Comment[hne]=कान्करर बर सेल कमांड प्लगइन +Comment[hr]=Dodatak za naredbe u ljuski namijenjen Konqueroru +Comment[hsb]=zašćěpka konquerora za terminalowe přikazy +Comment[hu]=Parancsvégrehajtó modul a Konqueror böngészőhöz +Comment[ia]=Plugin de Commando Shell pro Konqueror +Comment[id]=Plugin Perintah Shell Untuk Konqueror +Comment[is]=Skeljarskipunar íforrit fyrir Konqueror +Comment[it]=Estensione per i comandi da shell di Konqueror +Comment[ja]=Konqueror 用シェルコマンドプラグイン +Comment[ka]=გარსისს ბრძანების მოდული Konqueror-ისთვის +Comment[kk]=Команда жолы модулі +Comment[km]=កម្មវិធី​ជំនួយ​ពាក្យ​បញ្ជា​សែល​សម្រាប់ Konqueror +Comment[kn]=ಕಾಂಕರರ್ ಗೆ ಆದೇಶಗ್ರಾಹಿ (ಶೆಲ್) ಆದೇಶ ಮಿಳಿತಾನ್ವಯ (ಪ್ಲಗಿನ್) +Comment[ko]=Konqueror 셸 명령 플러그인 +Comment[ku]=Pêveka Fermanên Shell ji bo Konqueror +Comment[lt]=Apvalkalo komandų priedas Konqueror +Comment[lv]=Čaulas komandas Konqueror spraudnis +Comment[mai]=कान्करर क' लेल शेल कमांड प्लगइन +Comment[mk]=Приклучок за команда за школка за Konqueror +Comment[ml]=കോണ്‍ക്വററിനുള്ള ഷെല്‍ ആജ്ഞാ സംയോജകം +Comment[mr]=कॉन्करर करिता शेल आदेश प्लगइन +Comment[ms]=Plugin Arahan Shell untuk Konqueror +Comment[nb]=Programtillegg for skallkommandoer i Konqueror +Comment[nds]=Konsoolbefehl-Moduul för Konqueror +Comment[ne]=कन्क्वेररका लागि शेल आदेश प्लगइन +Comment[nl]=Een shellcommando-plugin voor Konqueror +Comment[nn]=Programtillegg for skalkommandoar i Konqueror +Comment[or]=Konqueror ପାଇଁ Shell ନିର୍ଦ୍ଦେଶ ପ୍ଲଗଇନ +Comment[pa]=ਕੋਨਕਿਉਰੋਰ ਲਈ ਸ਼ੈਲ ਕਮਾਂਡ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka polecenia powłoki dla Konquerora +Comment[pt]=Um 'Plugin' para Executar Comandos no Konqueror +Comment[pt_BR]=Plugin de comandos do shell para o Konqueror +Comment[ro]=Plugin shell pentru comenzi pentru Konqueror +Comment[ru]=Выполнение команды из Konqueror +Comment[se]=Skálžogohččunlassemodula Konquerora várás +Comment[si]=Konqueror සඳහා ශෙල් විධාන ප්ලගිනය +Comment[sk]=Modul pre príkazy shellu pre Konqueror +Comment[sl]=Vstavek za izvajanje lupinskih ukazov +Comment[sr]=Прикључак за наредбе шкољке за К‑освајач +Comment[sr@ijekavian]=Прикључак за наредбе шкољке за К‑освајач +Comment[sr@ijekavianlatin]=Priključak za naredbe školjke za K‑osvajač +Comment[sr@latin]=Priključak za naredbe školjke za K‑osvajač +Comment[sv]=Insticksprogram för skalkommandon i Konqueror +Comment[ta]=கான்கொயரருக்கான முனைய ஆணை செருகி +Comment[te]=Konqueror కొరకు షెల్ ఆదేశం ప్లగ్ఇన్ +Comment[tg]=Плагини иҷрои фармон барои Konqueror +Comment[th]=ส่วนเสริมป้อนคำสั่งเชลล์สำหรับของคอนเควอร์เรอร์ +Comment[tr]=Konqueror için Uçbirim Komut Eklentisi +Comment[ug]=Konqueror نىڭ Shell بۇيرۇق قىستۇرمىسى +Comment[uk]=Додаток командної оболонки для Konqueror +Comment[vi]=Trình bổ sung khả năng dòng lệnh cho trình duyệt Konqueror +Comment[wa]=Tchôke-divins roye di comande po Konqueror +Comment[x-test]=xxShell Command Plugin for Konquerorxx +Comment[zh_CN]=Konqueror 的 Shell 命令插件 +Comment[zh_TW]=Konqueror 的 Shell 指令外掛程式 diff --git a/plugins/shellcmdplugin/kshellcmdplugin.h b/plugins/shellcmdplugin/kshellcmdplugin.h new file mode 100644 index 0000000..527f559 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdplugin.h @@ -0,0 +1,35 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure + + 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 kshellcmdplugin_h +#define kshellcmdplugin_h + +#include + +class KShellCmdPlugin : public KParts::Plugin +{ + Q_OBJECT +public: + KShellCmdPlugin(QObject *parent, const QVariantList &); + ~KShellCmdPlugin() override {} + +public Q_SLOTS: + void slotExecuteShellCommand(); +}; + +#endif diff --git a/plugins/shellcmdplugin/kshellcmdplugin.rc b/plugins/shellcmdplugin/kshellcmdplugin.rc new file mode 100644 index 0000000..a143db6 --- /dev/null +++ b/plugins/shellcmdplugin/kshellcmdplugin.rc @@ -0,0 +1,8 @@ + + + + &Tools + + + + diff --git a/plugins/ttsplugin/CMakeLists.txt b/plugins/ttsplugin/CMakeLists.txt new file mode 100644 index 0000000..a47fbe8 --- /dev/null +++ b/plugins/ttsplugin/CMakeLists.txt @@ -0,0 +1,17 @@ +########### khtmlttsplugin ############### +add_definitions(-DTRANSLATION_DOMAIN=\"khtmltts\") +set(khtmlttsplugin_PART_SRCS khtmltts.cpp ) + +add_library(khtmlttsplugin MODULE ${khtmlttsplugin_PART_SRCS}) + +target_link_libraries(khtmlttsplugin KF5::Parts Qt5::TextToSpeech) + +install(TARGETS khtmlttsplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + + +########### install files ############### + +install( FILES khtmltts.rc khtmltts.desktop DESTINATION ${KDE_INSTALL_DATADIR}/khtml/kpartplugins ) +install( FILES khtmltts.rc khtmltts.desktop DESTINATION ${KDE_INSTALL_DATADIR}/kwebkitpart/kpartplugins ) +install( FILES khtmltts.rc khtmltts.desktop DESTINATION ${KDE_INSTALL_DATADIR}/webenginepart/kpartplugins ) + diff --git a/plugins/ttsplugin/Messages.sh b/plugins/ttsplugin/Messages.sh new file mode 100644 index 0000000..54832a1 --- /dev/null +++ b/plugins/ttsplugin/Messages.sh @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/khtmltts.pot diff --git a/plugins/ttsplugin/khtmltts.cpp b/plugins/ttsplugin/khtmltts.cpp new file mode 100644 index 0000000..a7ce40d --- /dev/null +++ b/plugins/ttsplugin/khtmltts.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + Copyright (C) 2002 by George Russell + Copyright (C) 2003-2004 by Olaf Schmidt + Copyright (C) 2015 Jeremy Whiting + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// Own +#include "khtmltts.h" + +// Qt +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include + +KHTMLPluginTTS::KHTMLPluginTTS(QObject *parent, const QVariantList &) + : Plugin(parent) +{ + KParts::TextExtension *textExt = KParts::TextExtension::childObject(parent); + if (textExt && qobject_cast(parent)) { + QAction *action = actionCollection()->addAction(QStringLiteral("tools_tts")); + action->setIcon(QIcon::fromTheme(QStringLiteral("text-speak"))); + action->setText(i18n("&Speak Text")); + connect(action, SIGNAL(triggered(bool)), SLOT(slotReadOut())); + } +} + +KHTMLPluginTTS::~KHTMLPluginTTS() +{ +} + +void KHTMLPluginTTS::slotReadOut() +{ + KParts::TextExtension *textExt = KParts::TextExtension::childObject(parent()); + QString query; + const KParts::TextExtension::Format format = KParts::TextExtension::PlainText; + if (textExt->hasSelection()) { + query = textExt->selectedText(format); + } else { + query = textExt->completeText(format); + } + + QTextToSpeech tts; + tts.say(query); +} + +K_PLUGIN_FACTORY(KHTMLPluginTTSFactory, registerPlugin();) + +#include "khtmltts.moc" diff --git a/plugins/ttsplugin/khtmltts.desktop b/plugins/ttsplugin/khtmltts.desktop new file mode 100644 index 0000000..1b1741e --- /dev/null +++ b/plugins/ttsplugin/khtmltts.desktop @@ -0,0 +1,185 @@ +[Desktop Entry] +Icon=preferences-desktop-text-to-speech +X-KDE-Library=libkhtmlttsplugin +X-KDE-PluginInfo-Author=Olaf Schmidt +X-KDE-PluginInfo-Email=ojschmidt@kde.org +X-KDE-PluginInfo-Name=khtmlttsplugin +X-KDE-PluginInfo-Version=4.0 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-ParentApp=konqueror +Name=Text-to-Speech +Name[af]=Text-to-Speech +Name[ar]=نص-إلى-صوت +Name[as]=Text-to-Speech +Name[ast]=Testu a voz +Name[be]=Прагаворванне тэксту +Name[be@latin]=Ahałošvańnie tekstu +Name[bg]=Приставка за синтез на глас +Name[bn]=লেখা-থেকে-কথা +Name[bn_IN]=টেক্সট-থেকে-ধ্বনি +Name[bs]=Tekst‑u‑govor +Name[ca]=Text a veu +Name[ca@valencia]=Text a veu +Name[cs]=Hlasová syntéza +Name[csb]=Czëtôrz tekstu +Name[da]=Tekst-til-tale +Name[de]=Sprachausgabe +Name[el]=Κείμενο-σε-ομιλία +Name[en_GB]=Text-to-Speech +Name[eo]=Teksto-al-Parolo +Name[es]=Texto-a-Voz +Name[et]=Teksti ettelugemine +Name[eu]=Testu-ahotsa +Name[fa]=متن به گفتار +Name[fi]=Puhesyntetisaattori +Name[fr]=Synthèse vocale +Name[fy]=Tekst-ta-spraak +Name[ga]=Téacs-go-Caint +Name[gl]=Texto-para-fala +Name[gu]=લખાણ-થી-બોલી +Name[he]=הקראת טקסט +Name[hi]=पाठ-से-वार्ता +Name[hne]=पाठ-से-गोठ +Name[hr]=Pretvaranje teksta u govor +Name[hsb]=Tekst-na-reč +Name[hu]=Szövegfelolvasó +Name[ia]=Texto-a-Discurso (TextToSpeech) +Name[id]=Teks-ke-Bicara +Name[is]=Texti-í-tal +Name[it]=Pronuncia +Name[ja]=テキスト読み上げ +Name[kk]=Мәтінді дыбыстап оқу +Name[km]=អត្ថបទ​ទៅ​ជា​សំដី +Name[kn]=ಪಠ್ಯದಿಂದ ವಾಚನ +Name[ko]=Text-to-Speech +Name[ku]=Pêveka Ji Deqê-bo-Dengî +Name[lt]=Teksto vertimas kalba +Name[lv]=Teksta izrunāšana +Name[mai]=पाठ-सँ-वार्ता +Name[mk]=Текст-во-говор +Name[ml]=ഗദ്യ-ശബ്ദ പരിവര്‍ത്തനം +Name[mr]=पाठ्य-ते-भाष्य +Name[ms]=Teks-ke-Tutur +Name[nb]=Tekst til tale +Name[nds]=Vörleser +Name[ne]=पाठबाट वाक्य +Name[nl]=Tekst-naar-spraak +Name[nn]=Tekst til tale +Name[or]=Text-to-Speech +Name[pa]=ਟੈਕਸਟ ਤੋਂ ਬੋਲੀ +Name[pl]=Odczytywanie tekstu +Name[pt]=Texto-para-Fala +Name[pt_BR]=Texto-em-fala +Name[ro]=Text-în-vorbire +Name[ru]=Синтез речи +Name[se]=Hupmejuvvon teaksta +Name[si]=පෙළ-හඩට-පෙරලුම +Name[sk]=Text na reč +Name[sl]=Besedilo v govor +Name[sr]=Текст‑у‑говор +Name[sr@ijekavian]=Текст‑у‑говор +Name[sr@ijekavianlatin]=Tekst‑u‑govor +Name[sr@latin]=Tekst‑u‑govor +Name[sv]=Text till tal +Name[ta]=உரையிலிருந்து ஒலி +Name[te]=పాఠ్యము-నుండి-మాట్లాడుట +Name[tg]=Талаффузи матн +Name[th]=เปลี่ยนข้อความเป็นเสียงพูด +Name[tr]=Text-to-Speech +Name[ug]=تېكىستتىن ئاۋازغا +Name[uk]=Синтез мовлення з тексту +Name[vi]=Văn bản sang Tiếng nói +Name[wa]=Tecse-viè-vwès +Name[x-test]=xxText-to-Speechxx +Name[zh_CN]=文本到语音 +Name[zh_TW]=文字轉語音 +Comment=Produces audio output for text in the current page +Comment[af]=Produseer klankafvoer vir die teks in die huidige bladsy +Comment[ar]=قراءة الصفحة الحالية +Comment[as]=বৰ্ত্তমানৰ পৃষ্ঠাৰ লিপিৰ বিষয়ে অ'ডিঅ' নিৰ্গম সৃষ্টি কৰে +Comment[ast]=Xenera una salida d'audiu del testu de la páxina actual +Comment[be]=Робіць аўдыёвывад для тэкту на бягучай старонцы +Comment[be@latin]=Ahučvaje tekst z hetaj staronki +Comment[bg]=Аудио за текст в текущата страница +Comment[bn]=বর্তমান পাতার লেখা পড়ে শোনায় +Comment[bn_IN]=বর্তমান পৃষ্ঠায় উপস্থিত টেক্সট থেকে ধ্বনি আউটপুট নির্মাণ করা হয় +Comment[bs]=Proizvodi audio izlaz od teksta na tekućoj stranici +Comment[ca]=Produeix una sortida d'àudio pel text de la pàgina actual +Comment[ca@valencia]=Produeix una eixida d'àudio pel text de la pàgina actual +Comment[cs]=Vytvoří zvukový výstup textu na aktuální stránce +Comment[csb]=Przetwôrzô tekst akùratny starnë w zwãk +Comment[da]=Producerer lyd-output af tekst i aktuel side +Comment[de]=Erzeugt Sprachausgabe für Text der aktuellen Seite +Comment[el]=Εκφωνεί το κείμενο της τρέχουσας σελίδας +Comment[en_GB]=Produces audio output for text in the current page +Comment[eo]=Generas parolaĵon el la teksto en la nuna paĝo +Comment[es]=Genera una salida de audio a partir del texto de la página actual +Comment[et]=Aktiivse lehekülje teksti ettelugemine +Comment[eu]=Testuaren audio irteera sortzen du uneko orrian +Comment[fa]=خروجی صوتی را برای متن در صفحه جاری تولید می‌کند +Comment[fi]=Muuttaa sivun sisältämän tekstin ääneksi +Comment[fr]=Produit des sorties audio pour le texte de la page courante +Comment[fy]=Produsearret audio útfier foar tekst yn de aktive side +Comment[ga]=Léigh an téacs atá ar an leathanach reatha +Comment[gl]=Produce saída de son para o texto da páxina actual +Comment[gu]=હાલનાં પાનાંનાં લખાણને બોલી સંભળાવે છે +Comment[he]=הקראת הטקסט בדף הנוכחי +Comment[hi]=वर्तमान पृष्ठ पर उपलब्ध पाठ के लिए ऑडियो आउटपुट तैयार करता है. +Comment[hne]=अभी हाल के पेज मं मिलत पाठ बर आडियो आउटपुट तैयार करथे. +Comment[hr]=Proizvodi zvučni izlaz za tekst na trenutnoj stranici +Comment[hsb]=Produkuje awdijo-output za tekst na aktualnej stronje +Comment[hu]=Felolvassa az aktuális oldal tartalmát +Comment[ia]=Il produce resultato audio pro texto in le pagina currente +Comment[id]=Menghasilkan output audio untuk teks di halaman saat ini +Comment[is]=Býr til tal úr textanum á núverandi síðu +Comment[it]=Genera una riproduzione vocale del testo della pagina attuale +Comment[ja]=現在のページのテキストを音声として出力します +Comment[kk]=Назардағы беттегі мәтінді дауыстап оқып беру +Comment[km]=បង្កើត​លទ្ធផល​​អូឌីយ៉ូ​សម្រាប់​អត្ថបទ​នៅ​ក្នុង​ទំព័រ​បច្ចុប្បន្ន +Comment[kn]=ಪ್ರಸ್ತುತ ಹಾಳೆಯಲ್ಲಿನ ಪಠ್ಯಕ್ಕೆ ಧ್ವನ್ಯಾಂಶವನ್ನು ಉತ್ಪಾದಿಸುತ್ತದೆ +Comment[ko]=현재 페이지의 텍스트를 읽어줍니다 +Comment[ku]=Ji bo deqên di pelê derbasdar de hilberînên deranên audîo +Comment[lt]=Perskaito balsu tekstą dabartiniame puslapyje +Comment[lv]=Izveido skaņas izvadu no teksta aktīvajā lapā +Comment[mai]=वर्तमान पृष्ठ पर उपलब्ध पाठ क' लेल आडिओ आउटपुट तैआर करैत अछि. +Comment[mk]=Произведува аудиоизлез за текстот на тековната страница +Comment[ml]=ഈ താള്‍ വായിച്ചു തരുന്നു. +Comment[mr]=वर्तमान पानावर उपलब्ध पाठ्य करिता ऑडिओ आउटपुट तैयार करतो +Comment[nb]=Teksten på gjeldende side kommer som tale i lyd-utgangen +Comment[nds]=Leest den Text op de aktuelle Siet vör +Comment[ne]=हालको पृष्ठमा पाठका लागि अडियो निर्गत उत्पादन गर्दछ +Comment[nl]=Spreekt de tekst uit van de huidige pagina +Comment[nn]=Les opp teksten på gjeldande side +Comment[or]=ଏହି ପୃଷ୍ଠାରେ ପାଠ୍ଯ ପାଇଁ ଧ୍ୱନି ନିର୍ଗମ ହୋଇଥାଏ +Comment[pa]=ਮੌਜੂਦਾ ਪੇਜ਼ ਵਿੱਚ ਟੈਕਸਟ ਲਈ ਆਡੀਓ ਆਉਟਪੁੱਟ ਬਣਾਉਦਾ ਹੈ +Comment[pl]=Odczytuje na głos tekst z bieżącej strony +Comment[pt]=Produz uma saída de áudio para o texto da página actual +Comment[pt_BR]=Produz uma saída de áudio para o texto da página atual +Comment[ro]=Produce ieșire sonoră pentru textul din pagina curentă +Comment[ru]=Проговаривает текст текущей страницы +Comment[se]=Lohka dán siiddu teavstta +Comment[si]=වත්මන් පිටුවේ පවතින පෙළහි ශ්‍රව්‍ය ප්‍රතිදානයක් ජනනය කරයි +Comment[sk]=Vytvorí zvukový výstup pre text na aktuálnej stránke +Comment[sl]=Besedilo na trenutni strani pretvori v govor +Comment[sr]=Производи аудио излаз од текста на текућој страници +Comment[sr@ijekavian]=Производи аудио излаз од текста на текућој страници +Comment[sr@ijekavianlatin]=Proizvodi audio izlaz od teksta na tekućoj stranici +Comment[sr@latin]=Proizvodi audio izlaz od teksta na tekućoj stranici +Comment[sv]=Matar ut text som ljud på nuvarande sida +Comment[ta]=தற்போதைய பக்கத்தில் இருக்கும் உரைக்கான ஒலி வெளியீட்டை தரும் +Comment[te]=ప్రస్తుత పుటలోని పాఠ్యముకొరకు ఆడియోను ఉత్పత్తిచేస్తుంది +Comment[tg]=Талаффузи матн дар саҳифаи ҷорӣ +Comment[th]=เปลี่ยนตัวหนังสือในหน้าปัจจุบันเป็นเสียง +Comment[tr]=Geçerli sayfadaki metni okur +Comment[ug]=نۆۋەتتىكى بەتتىكى تېكىستتىن ئاۋاز چىقىرىشى ھاسىل قىلىدۇ +Comment[uk]=Озвучує текст на поточній сторінці +Comment[vi]=Trình nói văn bản trên trang hiện thời +Comment[wa]=Prodût on son pol tecse el pådje do moumint +Comment[x-test]=xxProduces audio output for text in the current pagexx +Comment[zh_CN]=将当前页面中的文本生成为语音输出 +Comment[zh_TW]=產生目前頁面中的文字的語音輸出 + diff --git a/plugins/ttsplugin/khtmltts.h b/plugins/ttsplugin/khtmltts.h new file mode 100644 index 0000000..49d8629 --- /dev/null +++ b/plugins/ttsplugin/khtmltts.h @@ -0,0 +1,42 @@ +/*************************************************************************** + Copyright (C) 2002 by George Russell + Copyright (C) 2003-2004 by Olaf Schmidt + Copyright (C) 2015 by Jeremy Whiting + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 KHTMLTTS_H +#define KHTMLTTS_H + +#include + +/** + * KHTML KParts Plugin + */ +class KHTMLPluginTTS : public KParts::Plugin +{ + Q_OBJECT +public: + + /** + * Construct a new KParts plugin. + */ + KHTMLPluginTTS(QObject *parent, const QVariantList &); + + /** + * Destructor. + */ + ~KHTMLPluginTTS() override; +public Q_SLOTS: + void slotReadOut(); +}; + +#endif diff --git a/plugins/ttsplugin/khtmltts.rc b/plugins/ttsplugin/khtmltts.rc new file mode 100644 index 0000000..c8c5eb8 --- /dev/null +++ b/plugins/ttsplugin/khtmltts.rc @@ -0,0 +1,14 @@ + + + + + &Tools + + + + + + diff --git a/plugins/uachanger/CMakeLists.txt b/plugins/uachanger/CMakeLists.txt new file mode 100644 index 0000000..6678c07 --- /dev/null +++ b/plugins/uachanger/CMakeLists.txt @@ -0,0 +1,14 @@ +########### next target ############### +add_definitions(-DTRANSLATION_DOMAIN=\"uachangerplugin\") +set(uachangerplugin_PART_SRCS uachangerplugin.cpp ) + +add_library(uachangerplugin MODULE ${uachangerplugin_PART_SRCS}) + +target_link_libraries(uachangerplugin KF5::Parts ) + +install(TARGETS uachangerplugin DESTINATION ${KDE_INSTALL_PLUGINDIR} ) + +########### install files ############### + +install( FILES uachangerplugin.rc uachangerplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/khtml/kpartplugins ) +install( FILES uachangerplugin.rc uachangerplugin.desktop DESTINATION ${KDE_INSTALL_DATADIR}/kwebkitpart/kpartplugins ) diff --git a/plugins/uachanger/Messages.sh b/plugins/uachanger/Messages.sh new file mode 100644 index 0000000..fe0dec1 --- /dev/null +++ b/plugins/uachanger/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/uachangerplugin.pot diff --git a/plugins/uachanger/uachangerplugin.cpp b/plugins/uachanger/uachangerplugin.cpp new file mode 100644 index 0000000..705e8cd --- /dev/null +++ b/plugins/uachanger/uachangerplugin.cpp @@ -0,0 +1,463 @@ +/* + Copyright (c) 2001 Dawit Alemayehu + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) 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. +*/ + +#include "uachangerplugin.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const KAboutData aboutdata("uachangerplugin", 0, ki18n("Change Browser Identification"), "1.0"); +K_PLUGIN_FACTORY(UAChangerPluginFactory, registerPlugin();) +K_EXPORT_PLUGIN(UAChangerPluginFactory(aboutdata)) + +#define UA_PTOS(x) (*it)->property(x).toString() +#define QFL1(x) QLatin1String(x) + +UAChangerPlugin::UAChangerPlugin(QObject *parent, + const QVariantList &) + : KParts::Plugin(parent), + m_bSettingsLoaded(false), m_part(0L), m_config(0L) +{ + setComponentData(UAChangerPlugin::componentData()); + + m_pUAMenu = new KActionMenu(KIcon("preferences-web-browser-identification"), i18n("Change Browser &Identification"), + actionCollection()); + actionCollection()->addAction("changeuseragent", m_pUAMenu); + m_pUAMenu->setDelayed(false); + connect(m_pUAMenu->menu(), SIGNAL(aboutToShow()), + this, SLOT(slotAboutToShow())); + + if (parent) { + m_part = qobject_cast(parent); + connect(m_part, SIGNAL(started(KIO::Job*)), this, + SLOT(slotEnableMenu())); + connect(m_part, SIGNAL(completed()), this, + SLOT(slotEnableMenu())); + connect(m_part, SIGNAL(completed(bool)), this, + SLOT(slotEnableMenu())); + } +} + +UAChangerPlugin::~UAChangerPlugin() +{ + saveSettings(); + slotReloadDescriptions(); +} + +void UAChangerPlugin::slotReloadDescriptions() +{ + delete m_config; + m_config = 0L; +} + +void UAChangerPlugin::parseDescFiles() +{ + const KService::List list = KServiceTypeTrader::self()->query("UserAgentStrings"); + if (list.isEmpty()) { + return; + } + + m_mapAlias.clear(); + m_lstAlias.clear(); + m_lstIdentity.clear(); + + struct utsname utsn; + uname(&utsn); + + QStringList languageList = KLocale::global()->languageList(); + if (!languageList.isEmpty()) { + const int index = languageList.indexOf(QFL1("C")); + if (index > -1) { + if (languageList.contains(QFL1("en"))) { + languageList.removeAt(index); + } else { + languageList[index] = QFL1("en"); + } + } + } + + KService::List::ConstIterator it = list.constBegin(); + KService::List::ConstIterator lastItem = list.constEnd(); + + for (; it != lastItem; ++it) { + QString ua = UA_PTOS("X-KDE-UA-FULL"); + QString tag = UA_PTOS("X-KDE-UA-TAG"); + + // The menu groups thing by tag, with the menu name being the X-KDE-UA-NAME by default. We make groups for + // IE, NS, Firefox, Safari, and Opera, and put everything else into "Other" + QString menuName; + MenuGroupSortKey menuKey; // key for the group.. + if (tag != "IE" && tag != "NN" && tag != "FF" && tag != "SAF" && tag != "OPR") { + tag = "OTHER"; + menuName = i18n("Other"); + menuKey = MenuGroupSortKey(tag, true); + } else { + menuName = UA_PTOS("X-KDE-UA-NAME"); + menuKey = MenuGroupSortKey(tag, false); + } + + if ((*it)->property("X-KDE-UA-DYNAMIC-ENTRY").toBool()) { + ua.replace(QFL1("appSysName"), QFL1(utsn.sysname)); + ua.replace(QFL1("appSysRelease"), QFL1(utsn.release)); + ua.replace(QFL1("appMachineType"), QFL1(utsn.machine)); + ua.replace(QFL1("appLanguage"), languageList.join(QFL1(", "))); + ua.replace(QFL1("appPlatform"), QFL1("X11")); + } + + if (m_lstIdentity.contains(ua)) { + continue; // Ignore dups! + } + + m_lstIdentity << ua; + + // Compute what to display for our menu entry --- including platform name if it's available, + // and avoiding repeating the browser name in categories other than 'other'. + QString platform = QString("%1 %2").arg(UA_PTOS("X-KDE-UA-SYSNAME")).arg(UA_PTOS("X-KDE-UA-SYSRELEASE")); + + QString alias; + if (platform.trimmed().isEmpty()) { + if (!menuKey.isOther) { + alias = i18nc("%1 = browser version (e.g. 2.0)", "Version %1", UA_PTOS("X-KDE-UA-VERSION")); + } else + alias = i18nc("%1 = browser name, %2 = browser version (e.g. Firefox, 2.0)", + "%1 %2", UA_PTOS("X-KDE-UA-NAME"), UA_PTOS("X-KDE-UA-VERSION")); + } else { + if (!menuKey.isOther) + alias = i18nc("%1 = browser version, %2 = platform (e.g. 2.0, Windows XP)", + "Version %1 on %2", UA_PTOS("X-KDE-UA-VERSION"), platform); + else + alias = i18nc("%1 = browser name, %2 = browser version, %3 = platform (e.g. Firefox, 2.0, Windows XP)", + "%1 %2 on %3", UA_PTOS("X-KDE-UA-NAME"), UA_PTOS("X-KDE-UA-VERSION"), platform); + } + + m_lstAlias << alias; + + /* sort in this UA Alias alphabetically */ + BrowserGroup ualist = m_mapAlias[menuKey]; + BrowserGroup::Iterator e = ualist.begin(); + while (!alias.isEmpty() && e != ualist.end()) { + if (m_lstAlias[(*e)] > alias) { + ualist.insert(e, m_lstAlias.count() - 1); + alias.clear(); + } + ++e; + } + + if (!alias.isEmpty()) { + ualist.append(m_lstAlias.count() - 1); + } + + m_mapAlias[menuKey] = ualist; + m_mapBrowser[menuKey] = menuName; + } +} + +void UAChangerPlugin::slotEnableMenu() +{ + m_currentURL = m_part->url(); + + // This plugin works on local files, http[s], and webdav[s]. + QString proto = m_currentURL.protocol(); + if (m_currentURL.isLocalFile() || + proto.startsWith("http") || proto.startsWith("webdav")) { + if (!m_pUAMenu->isEnabled()) { + m_pUAMenu->setEnabled(true); + } + } else { + m_pUAMenu->setEnabled(false); + } +} + +void UAChangerPlugin::slotAboutToShow() +{ + if (!m_config) { + m_config = new KConfig("kio_httprc"); + parseDescFiles(); + } + + if (!m_bSettingsLoaded) { + loadSettings(); + } + + if (m_pUAMenu->menu()->actions().isEmpty()) { // need to create the actions + m_pUAMenu->menu()->addTitle(i18n("Identify As")); // imho title doesn't need colon.. + + m_defaultAction = new QAction(i18n("Default Identification"), this); + m_defaultAction->setCheckable(true); + connect(m_defaultAction, SIGNAL(triggered()), this, SLOT(slotDefault())); + m_pUAMenu->menu()->addAction(m_defaultAction); + + m_pUAMenu->menu()->addSeparator(); + + m_actionGroup = new QActionGroup(m_pUAMenu->menu()); + AliasConstIterator map = m_mapAlias.constBegin(); + for (; map != m_mapAlias.constEnd(); ++map) { + QMenu *browserMenu = m_pUAMenu->menu()->addMenu(m_mapBrowser.value(map.key())); + BrowserGroup::ConstIterator e = map.value().begin(); + for (; e != map.value().end(); ++e) { + QAction *action = new QAction(m_lstAlias[*e], m_actionGroup); + action->setCheckable(true); + action->setData(*e); + browserMenu->addAction(action); + } + } + connect(m_actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotItemSelected(QAction*))); + + m_pUAMenu->menu()->addSeparator(); + + /* useless here, imho.. + m_pUAMenu->menu()->insertItem( i18n("Reload Identifications"), this, + SLOT(slotReloadDescriptions()), + 0, ++count );*/ + + m_applyEntireSiteAction = new QAction(i18n("Apply to Entire Site"), this); + m_applyEntireSiteAction->setCheckable(true); + connect(m_applyEntireSiteAction, SIGNAL(triggered()), this, SLOT(slotApplyToDomain())); + m_pUAMenu->menu()->addAction(i18n("Apply to Entire Site")); + + m_pUAMenu->menu()->addAction(i18n("Configure..."), this, + SLOT(slotConfigure())); + } + + // Reflect current settings in the actions + + QString host = m_currentURL.isLocalFile() ? QFL1("localhost") : m_currentURL.host(); + m_currentUserAgent = KProtocolManager::userAgentForHost(host); + //kDebug(90130) << "User Agent: " << m_currentUserAgent; + m_defaultAction->setChecked(m_currentUserAgent == KProtocolManager::defaultUserAgent()); + + m_applyEntireSiteAction->setChecked(m_bApplyToDomain); + Q_FOREACH (QAction *action, m_actionGroup->actions()) { + const int id = action->data().toInt(); + action->setChecked(m_lstIdentity[id] == m_currentUserAgent); + } + +} + +void UAChangerPlugin::slotConfigure() +{ + KService::Ptr service = KService::serviceByDesktopName("useragent"); + if (service) { + KRun::runCommand(service->exec(), m_part->widget()); + } +} + +void UAChangerPlugin::slotItemSelected(QAction *action) +{ + const int id = action->data().toInt(); + if (m_lstIdentity[id] == m_currentUserAgent) { + return; + } + + m_currentUserAgent = m_lstIdentity[id]; + QString host = m_currentURL.isLocalFile() ? QFL1("localhost") : filterHost(m_currentURL.host()); + + KConfigGroup grp = m_config->group(host.toLower()); + grp.writeEntry("UserAgent", m_currentUserAgent); + //kDebug(90130) << "Writing out UserAgent=" << m_currentUserAgent << "for host=" << host; + grp.sync(); + + // Reload the page with the new user-agent string + reloadPage(); +} + +void UAChangerPlugin::slotDefault() +{ + if (m_currentUserAgent == KProtocolManager::defaultUserAgent()) { + return; // don't flicker! + } + // We have no choice but delete all higher domain level settings here since it + // affects what will be matched. + QStringList partList = m_currentURL.host().split(' ', QString::SkipEmptyParts); + if (!partList.isEmpty()) { + partList.removeFirst(); + + QStringList domains; + // Remove the exact name match... + domains << m_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(QFL1(".")); + partList.removeFirst(); + } + + KConfigGroup grp(m_config, QString()); + for (QStringList::Iterator it = domains.begin(); it != domains.end(); it++) { + //kDebug () << "Domain to remove: " << *it; + if (grp.hasGroup(*it)) { + grp.deleteGroup(*it); + } else if (grp.hasKey(*it)) { + grp.deleteEntry(*it); + } + } + } else if (m_currentURL.isLocalFile() && m_config->hasGroup("localhost")) { + m_config->deleteGroup("localhost"); + } + + m_config->sync(); + + // Reset some internal variables and inform the http io-slaves of the changes. + m_currentUserAgent = KProtocolManager::defaultUserAgent(); + + // Reload the page with the default user-agent + reloadPage(); +} + +void UAChangerPlugin::reloadPage() +{ + // Inform running http(s) io-slaves about the change... + KIO::Scheduler::emitReparseSlaveConfiguration(); + + KParts::OpenUrlArguments args = m_part->arguments(); + args.setReload(true); + m_part->setArguments(args); + m_part->openUrl(m_currentURL); +} + +QString UAChangerPlugin::filterHost(const QString &hostname) +{ + QRegExp rx; + + // Check for IPv4 address + rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + if (rx.exactMatch(hostname)) { + return hostname; + } + + // Check for IPv6 address here... + rx.setPattern("^\\[.*\\]$"); + if (rx.exactMatch(hostname)) { + return hostname; + } + + // Return the TLD if apply to domain or + return (m_bApplyToDomain ? findTLD(hostname) : hostname); +} + +QString UAChangerPlugin::findTLD(const QString &hostname) +{ + QStringList domains; + QStringList partList = hostname.split(' ', QString::SkipEmptyParts); + + if (partList.count()) { + partList.removeFirst(); // Remove hostname + } + + while (partList.count()) { + // We only have a TLD left. + if (partList.count() == 1) { + break; + } + + if (partList.count() == 2) { + // The .name domain uses ..name + // Although the TLD is striclty speaking .name, for our purpose + // it should be .name since people should not be able + // to set cookies for everyone with the same surname. + // Matches .name + if (partList[1].toLower() == QFL1("name")) { + break; + } else if (partList[1].length() == 2) { + // If this is a TLD, we should stop. (e.g. co.uk) + // We assume this is a TLD if it ends with .xx.yy or .x.yy + if (partList[0].length() <= 2) { + break; // This is a TLD. + } + + // Catch some TLDs that we miss with the previous check + // e.g. com.au, org.uk, mil.co + QByteArray t = partList[0].toLower().toUtf8(); + if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || + (t == "edu") || (t == "mil") || (t == "int")) { + break; + } + } + } + + domains.append(partList.join(QFL1("."))); + partList.removeFirst(); // Remove part + } + + if (domains.isEmpty()) { + return hostname; + } + + return domains[0]; +} + +void UAChangerPlugin::saveSettings() +{ + if (!m_bSettingsLoaded) { + return; + } + + KConfig cfg("uachangerrc", KConfig::NoGlobals); + KConfigGroup grp = cfg.group("General"); + + grp.writeEntry("applyToDomain", m_bApplyToDomain); +} + +void UAChangerPlugin::loadSettings() +{ + KConfig cfg("uachangerrc", KConfig::NoGlobals); + KConfigGroup grp = cfg.group("General"); + + m_bApplyToDomain = grp.readEntry("applyToDomain", true); + m_bSettingsLoaded = true; +} + +void UAChangerPlugin::slotApplyToDomain() +{ + m_bApplyToDomain = !m_bApplyToDomain; +} + +#include "uachangerplugin.moc" diff --git a/plugins/uachanger/uachangerplugin.desktop b/plugins/uachanger/uachangerplugin.desktop new file mode 100644 index 0000000..6ce399f --- /dev/null +++ b/plugins/uachanger/uachangerplugin.desktop @@ -0,0 +1,136 @@ +[Desktop Entry] +X-KDE-Library=UserAgentChanger +X-KDE-PluginInfo-Author=Dawit Alemayehu +X-KDE-PluginInfo-Email=adawit@kde.org +X-KDE-PluginInfo-Name=UserAgentChanger +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=UserAgent Changer +Name[ar]=مغير معرف المتصفح +Name[ast]=Cambéu d'axente d'usuariu +Name[bg]=Смяна на UserAgent +Name[bs]=Izmjenjivač korisničkog agenta +Name[ca]=Commutador d'agent d'usuari +Name[ca@valencia]=Commutador d'agent d'usuari +Name[cs]=Editor uživatelského agenta +Name[da]=Skift brugeragent +Name[de]=Browserkennung ändern +Name[el]=Αλλαγή πράκτορα χρήστη +Name[en_GB]=UserAgent Changer +Name[es]=Cambiar agente de usuario +Name[et]=Identifikaatori muutja +Name[eu]=Erabiltzaile-agente aldatzailea +Name[fi]=Käyttäjäagentin vaihtaja +Name[fr]=Modificateur d'agent utilisateur +Name[ga]=Clár Athraithe UserAgent +Name[gl]=Cambiador de UserAgent +Name[he]=משנה מחרוזות זיהוי דפדפן +Name[hne]=यूजरएजेंट बदलइया +Name[hr]=Mijenjač UserAgenta +Name[hu]=Böngészőazonosító-váltó +Name[ia]=Cambiator de Agente de usator (UserAgent) +Name[id]=Pengubah UserAgent +Name[is]=Breyta UserAgent +Name[it]=Modificatore di UserAgent +Name[ja]=ユーザエージェントチェンジャー +Name[kk]=UserAgent ауыстырғышы +Name[km]=កម្មវិធី​ផ្លាស់ប្ដូរ​ភ្នាក់ងារ​អ្នក​ប្រើ +Name[ko]=사용자 에이전트 변경 도구 +Name[ku]=Guherkerê UserAgent +Name[lt]=Naudotojo agento keitiklis +Name[lv]=Lietotāja aģenta mainītājs +Name[mr]=वापरकर्ता प्रतिनिधी बदलणारा +Name[nb]=Endrer brukeragent +Name[nds]=Nettkieker-Kennen ännern +Name[nl]=Gebruikersagent wijzigen +Name[nn]=Endra brukaragent-tekst +Name[pa]=ਯੂਜ਼ਰ-ਏਜੰਟ ਚੇਜ਼ਰ +Name[pl]=Zmieniacz UserAgenta +Name[pt]=Mudança de Agente do Utilizador +Name[pt_BR]=Modificador do agente de usuário +Name[ro]=Schimbă UserAgent +Name[ru]=Строка UserAgent +Name[sk]=Editor užívateľského agenta +Name[sl]=Uporabniški posredniki +Name[sr]=Измењивач корисничког агента +Name[sr@ijekavian]=Измјењивач корисничког агента +Name[sr@ijekavianlatin]=Izmjenjivač korisničkog agenta +Name[sr@latin]=Izmenjivač korisničkog agenta +Name[sv]=Ändring av användaragent +Name[tg]=Табдилгари корбари агентӣ +Name[th]=เครื่องมือเปลี่ยนการแสดงตัวของเบราว์เซอร์ +Name[tr]=Kullanıcı Uygulaması Değiştirici +Name[ug]=ئىشلەتكۈچى ۋاكالەتچى ئۆزگەرتكۈچ +Name[uk]=Зміна UserAgent +Name[wa]=Candjeu d' idintifiaedje do betchteu (« User Agent ») +Name[x-test]=xxUserAgent Changerxx +Name[zh_CN]=UserAgent 变更器 +Name[zh_TW]=使用者代理程式變更器 +Comment=Allows the detected UserAgent to be modified +Comment[ar]=تسمح بتغير معرف المتصفح +Comment[ast]=Permite que se modifique l'axente d'usuariu deteutáu +Comment[bg]=Позволява промяната на UserAgent, с който програмата се представя пред сървърите +Comment[bs]=Omogućava izmjenu odaslatog korisničkog agenta +Comment[ca]=Permet de modificar l'agent d'usuari (UserAgent) detectat +Comment[ca@valencia]=Permet de modificar l'agent d'usuari (UserAgent) detectat +Comment[cs]=Umožňuje upravení vybraného uživatelského agenta +Comment[da]=Tillader at ændre hvilken browser Konqueror udgiver sig for at være +Comment[de]=Ermöglicht die Änderung der erkannten Browserkennung +Comment[el]=Επιτρέπει την αλλαγή του πράκτορα χρήστη +Comment[en_GB]=Allows the detected UserAgent to be modified +Comment[es]=Permite modificar el agente de usuario detectado +Comment[et]=Võimaldab muuta brauseri tuvastatavat identifikaatorit +Comment[eu]=Detektatutako erabiltzaile-agentea aldatzeko aukera eskaintzen du +Comment[fi]=Sallii käyttäjäagentin muutoksen havaitsemisen +Comment[fr]=Permet à l'agent utilisateur détecté d'être modifié +Comment[ga]=Ceadaíonn sé seo duit an UserAgent a athrú +Comment[gl]=Permite modificar o UserAgent detectado +Comment[he]=מאפשר את שינוי מחרוזת מזהה־המשתמש +Comment[hne]=यूजरएजेंट ल सुधारे बर स्वीकारथे +Comment[hr]=Dozvoliti da otkriveni UserAgent bude promijenjen +Comment[hu]=Lehetővé teszi az észlelt böngészőazonosító módosítását +Comment[ia]=Il permitte de relevar Agente de Usator que debe esser modificate +Comment[id]=Memungkinkan UserAgent terdeteksi untuk dimodifikasi +Comment[is]=Gerir kleift að breyta þeim UserAgent streng sem fannst +Comment[it]=Permette di modificare l'UserAgent rilevato +Comment[ja]=検出されるユーザエージェントの編集を可能にします +Comment[kk]=UserAgent-ті өзгертуге көмектесу +Comment[km]=អនុញ្ញាត​ភ្នាក់ងារ​អ្នក​ប្រើ​ដែល​រក​ឃើញ​ឲ្យ​កែប្រែ +Comment[ko]=사용자 에이전트를 바꿀 수 있도록 하기 +Comment[ku]=Dihêle ku UserAgent ên hatine dîtin bên guherandin +Comment[lt]=Leidžia keisti aptiktą NaudotojoAgentą +Comment[lv]=Ļauj mainīt pārlūka sūtīto lietotāja aģenta tekstu +Comment[mr]=सापडलेला वापरकर्ता प्रतिनिधी बदलण्यासाठी परवानगी देतो +Comment[nb]=Gjør at brukeragentstrengen kan endres +Comment[nds]=Lett Di de Nettkieker-Kennen ännern +Comment[nl]=Maakt het mogelijk om de browseragent te wijzigen +Comment[nn]=Gjer det mogleg å endra brukaragent-teksten +Comment[pa]=ਖੋਜੇ ਯੂਜ਼ਰ-ਏਜੰਟ ਨੂੰ ਸੋਧਣਾ ਮਨਜ਼ੂਰ ਕਰੋ +Comment[pl]=Pozwala na modyfikację rozpoznanych UserAgentów +Comment[pt]=Permite modificar o Agente de Utilizador detectado +Comment[pt_BR]=Permite alterar o agente de usuário detectado +Comment[ro]=Permite schimbare UserAgent-ului detectat +Comment[ru]=Позволяет менять значение строки UserAgent +Comment[sk]=Umožní upravovanie vybranému užívateľskému agentovi +Comment[sl]=Omogoča spremembo zaznanega uporabniškega posrednika +Comment[sr]=Омогућава измену одаслатог корисничког агента +Comment[sr@ijekavian]=Омогућава измјену одаслатог корисничког агента +Comment[sr@ijekavianlatin]=Omogućava izmjenu odaslatog korisničkog agenta +Comment[sr@latin]=Omogućava izmenu odaslatog korisničkog agenta +Comment[sv]=Gör det möjligt att ändra detekterad användaragent +Comment[tg]=Иҷозат медиҳад, ки Корбари агентии муайяншударо тағйир диҳед +Comment[th]=อนุญาตให้ทำการปรับเปลี่ยนการแสดงตัวของเบราว์เซอร์ได้ +Comment[tr]=Belirlenen Kullanıcı Uygulamasının değiştirilmesini sağlar +Comment[ug]=بايقالغان ئىشلەتكۈچى ۋاكالەتچىسىنى ئۆزگەرتىشكە يول قويىدۇ +Comment[uk]=Дає змогу міняти UserAgent +Comment[wa]=Permete di candjî l' idintifiaedje do betchteu trové +Comment[x-test]=xxAllows the detected UserAgent to be modifiedxx +Comment[zh_CN]=允许用户修改被检测的 UserAgent +Comment[zh_TW]=允許變更自動偵測到的使用者代理程式 +X-KDE-ParentApp=konqueror +Icon=preferences-web-browser-identification +DocPath=konq-plugins/uachanger/index.html diff --git a/plugins/uachanger/uachangerplugin.h b/plugins/uachanger/uachangerplugin.h new file mode 100644 index 0000000..099fbd8 --- /dev/null +++ b/plugins/uachanger/uachangerplugin.h @@ -0,0 +1,115 @@ +/* + Copyright (c) 2001 Dawit Alemayehu + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) 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 __UACHANGER_PLUGIN_H +#define __UACHANGER_PLUGIN_H + +#include +#include + +#include +#include +#include + +class KActionMenu; +class QAction; +class QActionGroup; +class KConfig; + +namespace KIO +{ +} + +class UAChangerPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + explicit UAChangerPlugin(QObject *parent, + const QVariantList &); + ~UAChangerPlugin(); + +protected slots: + void slotDefault(); + void parseDescFiles(); + + void slotConfigure(); + void slotAboutToShow(); + void slotApplyToDomain(); + void slotEnableMenu(); + void slotItemSelected(QAction *); + void slotReloadDescriptions(); + +protected: + QString findTLD(const QString &hostname); + QString filterHost(const QString &hostname); + +private: + void reloadPage(); + void loadSettings(); + void saveSettings(); + + int m_selectedItem; + bool m_bApplyToDomain; + bool m_bSettingsLoaded; + + KParts::ReadOnlyPart *m_part; + KActionMenu *m_pUAMenu; + KConfig *m_config; + QAction *m_applyEntireSiteAction; + QAction *m_defaultAction; + QActionGroup *m_actionGroup; + + KUrl m_currentURL; + QString m_currentUserAgent; + + QStringList m_lstAlias; // menu entry names + QStringList m_lstIdentity; // UA strings + + // A little wrapper around tag names so that other always goes to the end. + struct MenuGroupSortKey { + QString tag; + bool isOther; + MenuGroupSortKey(): isOther(false) {} + MenuGroupSortKey(const QString &t, bool oth): tag(t), isOther(oth) {} + + bool operator==(const MenuGroupSortKey &o) const + { + return tag == o.tag && isOther == o.isOther; + } + + bool operator<(const MenuGroupSortKey &o) const + { + return (!isOther && o.isOther) || (tag < o.tag); + } + }; + + typedef QList BrowserGroup; + typedef QMap AliasMap; + typedef QMap BrowserMap; + + typedef AliasMap::Iterator AliasIterator; + typedef AliasMap::ConstIterator AliasConstIterator; + + BrowserMap m_mapBrowser; // tag -> menu name + AliasMap m_mapAlias; // tag -> UA string/menu entry name indices. +}; + +#endif diff --git a/plugins/uachanger/uachangerplugin.rc b/plugins/uachanger/uachangerplugin.rc new file mode 100644 index 0000000..445d6d1 --- /dev/null +++ b/plugins/uachanger/uachangerplugin.rc @@ -0,0 +1,11 @@ + + + + &Tools + + + +Extra Toolbar + + + diff --git a/plugins/uninstall.desktop b/plugins/uninstall.desktop new file mode 100644 index 0000000..e1e3e17 --- /dev/null +++ b/plugins/uninstall.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/po/ar/akregator_konqplugin.po b/po/ar/akregator_konqplugin.po new file mode 100644 index 0000000..aae3b8d --- /dev/null +++ b/po/ar/akregator_konqplugin.po @@ -0,0 +1,69 @@ +# translation of akregator_konqplugin.po to Arabic +# translation of akregator_konqplugin.po to +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2008, 2012. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: akregator_konqplugin\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-11-29 02:33+0100\n" +"PO-Revision-Date: 2014-07-15 17:58+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#: akregatorplugin.cpp:74 +#, fuzzy, kde-format +#| msgid "Add Feed to Akregator" +msgctxt "@action:inmenu" +msgid "Add Feed to Akregator" +msgstr "أضف تلقيمًا إلى أكريغاتور" + +#: konqfeedicon.cpp:144 +#, kde-format +msgid "Add Feed to Akregator" +msgstr "أضف تلقيمًا إلى أكريغاتور" + +#: konqfeedicon.cpp:146 +#, kde-format +msgid "Add Feeds to Akregator" +msgstr "أضف تلقيمات إلى أكريغاتور" + +#: konqfeedicon.cpp:155 +#, kde-format +msgid "Add All Found Feeds to Akregator" +msgstr "أضف كلّ التلقيمات التي عُثر عليها إلى أكريغاتور" + +#: konqfeedicon.cpp:179 +#, kde-format +msgid "Subscribe to site updates (using news feed)" +msgstr "اشترك في تحديثات الموقع (باستخدام تلقيمة الأخبار)" + +#: pluginutil.cpp:52 pluginutil.cpp:62 +#, kde-format +msgid "Imported Feeds" +msgstr "التقيمات المُستورَدة" + +#: pluginutil.cpp:54 +#, kde-format +msgid "Unable to contact Akregator via D-Bus" +msgstr "" + +#: pluginutil.cpp:55 +#, fuzzy, kde-format +#| msgctxt "@title:window" +#| msgid "The DBus call addFeedToGroup failed" +msgctxt "@title:window" +msgid "D-Bus call failed" +msgstr "فشل نداء DBus لـ addFeedToGroup" + +#~ msgid "Akregator feed icon - DBus Call failed" +#~ msgstr "أيقونة أكريغاتور - فشل نداء DBus" diff --git a/po/ar/autorefresh.po b/po/ar/autorefresh.po new file mode 100644 index 0000000..191c5cb --- /dev/null +++ b/po/ar/autorefresh.po @@ -0,0 +1,102 @@ +# translation of autorefresh.po to Arabic +# translation of autorefresh.po to +# Copyright (C) 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +# Ahmad M. Zawawi , 2004. +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2008, 2012. +# Abdalrahim G. Fakhouri , 2012. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: autorefresh\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-07-15 18:05+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" +"X-Project-Style: kde\n" + +#: autorefresh.cpp:41 +#, kde-format +msgid "&Auto Refresh" +msgstr "إ&نعاش آلي" + +#: autorefresh.cpp:45 +#, kde-format +msgid "None" +msgstr "بلا" + +#: autorefresh.cpp:46 +#, kde-format +msgid "Every 15 Seconds" +msgstr "كلّ 15 ثانية" + +#: autorefresh.cpp:47 +#, kde-format +msgid "Every 30 Seconds" +msgstr "كلّ 30 ثانية" + +#: autorefresh.cpp:48 +#, kde-format +msgid "Every Minute" +msgstr "كلّ دقيقة" + +#: autorefresh.cpp:49 +#, kde-format +msgid "Every 5 Minutes" +msgstr "كلّ 5 دقائق" + +#: autorefresh.cpp:50 +#, kde-format +msgid "Every 10 Minutes" +msgstr "كلّ 10 دقائق" + +#: autorefresh.cpp:51 +#, kde-format +msgid "Every 15 Minutes" +msgstr "كلّ 15 دقيقة" + +#: autorefresh.cpp:52 +#, kde-format +msgid "Every 30 Minutes" +msgstr "كلّ 30 دقيقة" + +#: autorefresh.cpp:53 +#, kde-format +msgid "Every 60 Minutes" +msgstr "كلّ 60 دقيقة" + +#: autorefresh.cpp:54 +#, kde-format +msgid "Every 2 Hours" +msgstr "كلّ ساعتين" + +#: autorefresh.cpp:55 +#, kde-format +msgid "Every 6 Hours" +msgstr "كلّ 6 ساعات" + +#: autorefresh.cpp:113 +#, kde-format +msgctxt "@title:window" +msgid "Cannot Refresh Source" +msgstr "تعذّر إنعاش المصدر" + +#: autorefresh.cpp:114 +#, kde-format +msgid "This plugin cannot auto-refresh the current part." +msgstr "تعذّر على هذه الملحقة إنعاش الجزء الحالي آليًا.." + +#. i18n: ectx: Menu (tools) +#: autorefresh.rc:5 +#, kde-format +msgid "&Tools" +msgstr "أ&دوات" diff --git a/po/ar/babelfish.po b/po/ar/babelfish.po new file mode 100644 index 0000000..1922c49 --- /dev/null +++ b/po/ar/babelfish.po @@ -0,0 +1,250 @@ +# translation of babelfish.po to Arabic +# translation of babelfish.po to +# Copyright (C) 2001,2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +# Mohammed Gamal , 2001. +# Isam Bayazidi , 2002. +# Ahmad M. Zawawi , 2004. +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2008, 2012. +# Abdalrahim G. Fakhouri , 2012. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: babelfish\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-07-15 18:25+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" +"X-Project-Style: kde\n" +"X-POOTLE-MTIME: 1381911090.0\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "محمد سعد" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "metehyi@free.fr" + +#: plugin_babelfish.cpp:44 +#, kde-format +msgid "Translate Web Page" +msgstr "ترجم صفحة الوِب" + +#: plugin_babelfish.cpp:52 +#, kde-format +msgid "Translate Web &Page" +msgstr "ترجم &صفحة الوِب" + +#: plugin_babelfish.cpp:89 +#, kde-format +msgid "&English To" +msgstr "من الإن&جليزية إلى" + +#: plugin_babelfish.cpp:92 +#, kde-format +msgid "&French To" +msgstr "من ال&فرنسية إلى" + +#: plugin_babelfish.cpp:95 +#, kde-format +msgid "&German To" +msgstr "من الأل&مانية إلى" + +#: plugin_babelfish.cpp:98 +#, kde-format +msgid "&Greek To" +msgstr "من ال&يونانية إلى" + +#: plugin_babelfish.cpp:101 +#, kde-format +msgid "&Spanish To" +msgstr "من الإ&سبانية إلى" + +#: plugin_babelfish.cpp:104 +#, kde-format +msgid "&Portuguese To" +msgstr "من ال&برتغالية إلى" + +#: plugin_babelfish.cpp:107 +#, kde-format +msgid "&Italian To" +msgstr "من الإي&طالية إلى" + +#: plugin_babelfish.cpp:110 +#, kde-format +msgid "&Dutch To" +msgstr "من ال&هولندية إلى" + +#: plugin_babelfish.cpp:113 +#, kde-format +msgid "&Russian To" +msgstr "من ال&روسية إلى" + +#: plugin_babelfish.cpp:129 +#, kde-format +msgid "&Chinese (Simplified)" +msgstr "من ال&صينية (المبسّطة)" + +#: plugin_babelfish.cpp:130 +#, kde-format +msgid "Chinese (&Traditional)" +msgstr "من الصينية (ال&تقليدية)" + +#: plugin_babelfish.cpp:131 plugin_babelfish.cpp:144 +#, kde-format +msgid "&Dutch" +msgstr "ال&هولندية" + +#: plugin_babelfish.cpp:132 plugin_babelfish.cpp:153 plugin_babelfish.cpp:155 +#: plugin_babelfish.cpp:157 plugin_babelfish.cpp:159 plugin_babelfish.cpp:161 +#: plugin_babelfish.cpp:163 plugin_babelfish.cpp:165 +#, kde-format +msgid "&French" +msgstr "ال&فرنسية" + +#: plugin_babelfish.cpp:133 plugin_babelfish.cpp:146 +#, kde-format +msgid "&German" +msgstr "ال&إلمانية" + +#: plugin_babelfish.cpp:134 plugin_babelfish.cpp:147 +#, kde-format +msgid "&Greek" +msgstr "ال&يونانية" + +#: plugin_babelfish.cpp:135 plugin_babelfish.cpp:148 +#, kde-format +msgid "&Italian" +msgstr "الإي&طالية" + +#: plugin_babelfish.cpp:136 +#, kde-format +msgid "&Japanese" +msgstr "ال&يابانية" + +#: plugin_babelfish.cpp:137 +#, kde-format +msgid "&Korean" +msgstr "ال&كورية" + +#: plugin_babelfish.cpp:138 +#, kde-format +msgid "&Norwegian" +msgstr "ال&نروجية" + +#: plugin_babelfish.cpp:139 plugin_babelfish.cpp:149 +#, kde-format +msgid "&Portuguese" +msgstr "ال&برتغالية" + +#: plugin_babelfish.cpp:140 plugin_babelfish.cpp:151 +#, kde-format +msgid "&Russian" +msgstr "ال&روسية" + +#: plugin_babelfish.cpp:141 plugin_babelfish.cpp:150 +#, kde-format +msgid "&Spanish" +msgstr "الإس&بانية" + +#: plugin_babelfish.cpp:142 +#, kde-format +msgid "T&hai" +msgstr "الت&ايلندية" + +#: plugin_babelfish.cpp:143 +#, kde-format +msgid "&Arabic" +msgstr "ال&عربية" + +#: plugin_babelfish.cpp:145 plugin_babelfish.cpp:152 plugin_babelfish.cpp:154 +#: plugin_babelfish.cpp:156 plugin_babelfish.cpp:158 plugin_babelfish.cpp:160 +#: plugin_babelfish.cpp:162 plugin_babelfish.cpp:164 +#, kde-format +msgid "&English" +msgstr "الإن&جليزية" + +#: plugin_babelfish.cpp:187 +#, kde-format +msgid "&Chinese (Simplified) to English" +msgstr "من ال&صينية (المبسّطة) إلى الإنجليزية" + +#: plugin_babelfish.cpp:188 +#, kde-format +msgid "Chinese (&Traditional) to English" +msgstr "من الصينية (الت&قليدية) إلى الإنجليزية" + +#: plugin_babelfish.cpp:197 +#, kde-format +msgid "&Japanese to English" +msgstr "من ال&يابانية إلى الإنجليزية" + +#: plugin_babelfish.cpp:198 +#, kde-format +msgid "&Korean to English" +msgstr "من من ال&كورية إلى الإنجليزية" + +#: plugin_babelfish.cpp:266 +#, kde-format +msgctxt "@title:window" +msgid "Malformed URL" +msgstr "عنوان مشوَّه" + +#: plugin_babelfish.cpp:267 +#, kde-format +msgid "The URL you entered is not valid, please correct it and try again." +msgstr "العنوان الذي أدخلته غير صالح، فضلًا صحّحه وحاول مجدّدًا." + +#: plugin_babelfish.cpp:277 +#, kde-kuit-format +msgctxt "@info" +msgid "" +"You are viewing this page over a secure connection.The URL of the " +"page will sent to the online translation service, which may fetch the " +"insecure version of the page." +msgstr "" + +#: plugin_babelfish.cpp:281 +#, kde-format +msgctxt "@title:window" +msgid "Security Warning" +msgstr "" + +#. i18n: ectx: Menu (tools) +#: plugin_babelfish.rc:4 +#, kde-format +msgid "&Tools" +msgstr "أ&دوات" + +#. i18n: ectx: ToolBar (extraToolBar) +#: plugin_babelfish.rc:8 +#, kde-format +msgid "Extra Toolbar" +msgstr "شريط أدوات إضافي" + +#~ msgid "&Russian to English" +#~ msgstr "من ال&روسية إلى الإنجليزية" + +#~ msgid "Cannot Translate Source" +#~ msgstr "لا أستطيع ترجمة المصدر" + +#~ msgid "Only web pages can be translated using this plugin." +#~ msgstr "فقط صفحات الشبكة يمكن ترجمتها بهذا القابس." + +#~ msgid "Only full webpages can be translated for this language pair." +#~ msgstr "فقط صفحات الشبكة الكاملة يمكن ترجمتها لزوج اللغات هذا." + +#~ msgid "Translation Error" +#~ msgstr "خطأ الترجمة" diff --git a/po/ar/dirfilterplugin.po b/po/ar/dirfilterplugin.po new file mode 100644 index 0000000..31796c8 --- /dev/null +++ b/po/ar/dirfilterplugin.po @@ -0,0 +1,90 @@ +# translation of dirfilterplugin.po to Arabic +# translation of dirfilterplugin.po to +# Copyright (C) 2001,2002, 2006, 2007, 2008 Free Software Foundation, Inc. +# Mohammed Gamal , 2001. +# Isam Bayazidi , 2002. +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2008. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: dirfilterplugin\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-07-15 21:17+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#: dirfilterplugin.cpp:133 +#, kde-format +msgctxt "@info:tooltip" +msgid "Hide Filter Bar" +msgstr "أخفِ شريط المرشّح" + +#: dirfilterplugin.cpp:137 +#, kde-format +msgctxt "@label:textbox" +msgid "F&ilter:" +msgstr "المر&شّح:" + +#: dirfilterplugin.cpp:149 +#, kde-format +msgctxt "@label:button" +msgid "Filter by t&ype" +msgstr "رشّح بال&نوع" + +#: dirfilterplugin.cpp:150 +#, kde-format +msgctxt "@info:tooltip" +msgid "Filter items by file type." +msgstr "رشّح العناصر بنوع الملفات." + +#: dirfilterplugin.cpp:241 +#, kde-format +msgctxt "@action:inmenu Tools" +msgid "Show Filter Bar" +msgstr "أظهر شريط المرشّح" + +#: dirfilterplugin.cpp:335 +#, kde-format +msgid "Use Multiple Filters" +msgstr "استخدم عدّة مرشّحات" + +#: dirfilterplugin.cpp:341 +#, kde-format +msgid "Show Count" +msgstr "أظهر العدد" + +#: dirfilterplugin.cpp:346 +#, kde-format +msgid "Reset" +msgstr "صفّر" + +#. i18n: ectx: Menu (tools) +#: dirfilterplugin.rc:4 +#, kde-format +msgid "&Tools" +msgstr "أ&دوات" + +#. i18n: ectx: ToolBar (extraToolBar) +#: dirfilterplugin.rc:8 +#, kde-format +msgid "Extra Toolbar" +msgstr "شريط أدوات إضافي" + +#~ msgid "Allow to filter the currently displayed items by filetype." +#~ msgstr "اسمح بترشيح البنود المعروضة حالياً حسب نوع الملف." + +#~ msgid "Only Show Items of Type" +#~ msgstr "أعرض فقط البنود من النوع" + +#~ msgid "Filter Field" +#~ msgstr "حقل المرشح" diff --git a/po/ar/fsview.po b/po/ar/fsview.po new file mode 100644 index 0000000..a731e4f --- /dev/null +++ b/po/ar/fsview.po @@ -0,0 +1,449 @@ +# translation of fsview.po to Arabic +# translation of fsview.po to +# Copyright (C) 2003, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. +# Nuriddin Aminagha , 2003. +# Ahmad M. Zawawi , 2004. +# Mohammed Gamal , 2004. +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2009, 2012. +# Abdalrahim G. Fakhouri , 2012. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: fsview\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-08-23 22:50+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" +"X-Project-Style: kde\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "نورالدين شكري أمين آغا,أحمد محمد زواوي,محمد جمال" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "nuriddin@eminaga.de,azawawi@emirates.net.ae,f2c2001@yahoo.com" + +#: fsview.cpp:46 fsview.cpp:425 +#, kde-format +msgid "Name" +msgstr "الاسم" + +#: fsview.cpp:47 +#, kde-format +msgid "Size" +msgstr "الحجم" + +#: fsview.cpp:48 +#, kde-format +msgid "File Count" +msgstr "عدد الملفات" + +#: fsview.cpp:49 +#, kde-format +msgid "Directory Count" +msgstr "عدد الأدلة" + +#: fsview.cpp:50 +#, kde-format +msgid "Last Modified" +msgstr "آخر تعديل" + +#: fsview.cpp:51 fsview.cpp:426 +#, kde-format +msgid "Owner" +msgstr "المالك" + +#: fsview.cpp:52 fsview.cpp:427 +#, kde-format +msgid "Group" +msgstr "المجموعة" + +#: fsview.cpp:53 fsview.cpp:428 +#, kde-format +msgid "Mime Type" +msgstr "نوع Mime" + +#: fsview.cpp:294 +#, kde-format +msgid "Go To" +msgstr "اذهب إلى" + +#: fsview.cpp:295 fsview_part.cpp:121 +#, kde-format +msgid "Stop at Depth" +msgstr "توقّف عند العمق" + +#: fsview.cpp:296 fsview_part.cpp:118 +#, kde-format +msgid "Stop at Area" +msgstr "توقّف عند المساحة" + +#: fsview.cpp:297 +#, kde-format +msgid "Stop at Name" +msgstr "توقّف عند الاسم" + +#: fsview.cpp:303 +#, kde-format +msgid "Go Up" +msgstr "اذهب إلى الأعلى" + +#: fsview.cpp:305 +#, kde-format +msgid "Stop Refresh" +msgstr "أوقف الإنعاش" + +#: fsview.cpp:307 +#, kde-format +msgid "Refresh" +msgstr "أنعش" + +#: fsview.cpp:312 +#, kde-format +msgid "Refresh '%1'" +msgstr "أنعش '%1'" + +#: fsview.cpp:324 fsview_part.cpp:128 +#, kde-format +msgid "Color Mode" +msgstr "نمط الألوان" + +#: fsview.cpp:327 fsview_part.cpp:124 +#, kde-format +msgid "Visualization" +msgstr "مرئي" + +#: fsview.cpp:423 +#, kde-format +msgid "None" +msgstr "بلا" + +#: fsview.cpp:424 +#, kde-format +msgid "Depth" +msgstr "عمق" + +#: fsview_part.cpp:80 +#, kde-format +msgid "Read 1 folder, in %2" +msgid_plural "Read %1 folders, in %2" +msgstr[0] "لا تقرأ مجلدات في %1" +msgstr[1] "اقرأ مجلدًا واحدًا في %1" +msgstr[2] "اقرأ مجلدين في %1" +msgstr[3] "اقرأ %1 مجلدات في %2" +msgstr[4] "اقرأ %1 مجلدًا في %2" +msgstr[5] "اقرأ %1 مجلد في %2" + +#: fsview_part.cpp:84 +#, kde-format +msgid "1 folder" +msgid_plural "%1 folders" +msgstr[0] "لا مجلدات" +msgstr[1] "مجلد واحد" +msgstr[2] "مجلدان" +msgstr[3] "%1 مجلدات" +msgstr[4] "%1 مجلدًا" +msgstr[5] "%1 مجلد" + +#: fsview_part.cpp:95 main.cpp:22 +#, fuzzy, kde-format +msgid "FSView" +msgstr "برنامج FSView" + +#: fsview_part.cpp:96 main.cpp:23 +#, kde-format +msgid "Filesystem Viewer" +msgstr "عارض لنظام الملفات" + +#: fsview_part.cpp:98 main.cpp:25 +#, kde-format +msgid "(c) 2002, Josef Weidendorfer" +msgstr "(c) 2002, Josef Weidendorfer" + +#: fsview_part.cpp:102 +#, fuzzy, kde-format +msgid "" +"

This is the FSView plugin, a graphical browsing mode showing filesystem " +"utilization by using a tree map visualization.

Note that in this mode, " +"automatic updating when filesystem changes are made is intentionally not done.

For details on usage and options available, see the online " +"help under menu 'Help/FSView Manual'.

" +msgstr "" +"

هذا ملحق FSView, و هو أداة لعرض نظم الملفات على نمط شجري.

يرجى " +"ملاحظة أنه في هذا النمط لا يتم التحديث الآلي لنظام الملفات في حال أي تغيير و " +"ذلك عن عمد.

لمزيد من التفاصيل حول طريقة الاستخدام و الخيارات " +"المتوفرة يرجى قراءة دليل مستخدم FSView.

" + +#: fsview_part.cpp:134 +#, fuzzy, kde-format +msgid "&FSView Manual" +msgstr "&دليل FSView يدوي" + +#: fsview_part.cpp:136 +#, fuzzy, kde-format +msgid "Show FSView manual" +msgstr "إظهار دليل FSView" + +#: fsview_part.cpp:137 +#, fuzzy, kde-format +msgid "Opens the help browser with the FSView documentation" +msgstr "يفتح متصفح المساعدة ل FSView" + +#: fsview_part.cpp:177 +#, kde-format +msgctxt "@action:inmenu File" +msgid "Move to Trash" +msgstr "انقل إلى المهملات" + +#: fsview_part.cpp:185 +#, kde-format +msgctxt "@action:inmenu File" +msgid "Delete" +msgstr "احذف" + +#: fsview_part.cpp:190 +#, kde-format +msgctxt "@action:inmenu Edit" +msgid "&Edit File Type..." +msgstr "&حرّر نوع الملف..." + +#: fsview_part.cpp:194 +#, kde-format +msgctxt "@action:inmenu File" +msgid "Properties" +msgstr "خصائص" + +#: fsview_part.cpp:236 +#, fuzzy, kde-format +msgid "" +"FSView intentionally does not support automatic updates when changes are " +"made to files or directories, currently visible in FSView, from the " +"outside.\n" +"For details, see the 'Help/FSView Manual'." +msgstr "" +"لا يدعم FSView التحديثات الآلية عندما يتم القيام بتغييرات في الملفات و " +"الأدلة التي يمكن رؤيتها في FSView, من الخارج.\n" +"لمزيد من التفاصيل, اقرأ دليل المساعدة الخاص بـ FSView." + +#. i18n: ectx: Menu (edit) +#: fsview_part.rc:4 +#, kde-format +msgid "&Edit" +msgstr "&حرّر" + +#. i18n: ectx: Menu (view) +#: fsview_part.rc:13 +#, kde-format +msgid "&View" +msgstr "من&ظور" + +#. i18n: ectx: Menu (help) +#: fsview_part.rc:20 +#, kde-format +msgid "&Help" +msgstr "م&ساعدة" + +#: main.cpp:33 +#, kde-format +msgid "View filesystem starting from this folder" +msgstr "اعرض نظام الملفات بداية من هذا المجلد" + +#: treemap.cpp:1453 +#, fuzzy, kde-format +msgid "Text %1" +msgstr "نص %1" + +#: treemap.cpp:3181 +#, kde-format +msgid "Recursive Bisection" +msgstr "التَصنيف التَكراري" + +#: treemap.cpp:3183 +#, kde-format +msgid "Columns" +msgstr "أعمدة" + +#: treemap.cpp:3185 +#, kde-format +msgid "Rows" +msgstr "صفوف" + +#: treemap.cpp:3187 +#, kde-format +msgid "Always Best" +msgstr "دائمًا الأفضل" + +#: treemap.cpp:3189 +#, kde-format +msgid "Best" +msgstr "الأفضل" + +#: treemap.cpp:3191 +#, kde-format +msgid "Alternate (V)" +msgstr "بديل (V)" + +#: treemap.cpp:3193 +#, kde-format +msgid "Alternate (H)" +msgstr "بديل (H)" + +#: treemap.cpp:3195 +#, kde-format +msgid "Horizontal" +msgstr "أفقي" + +#: treemap.cpp:3197 +#, kde-format +msgid "Vertical" +msgstr "رأسي" + +#: treemap.cpp:3250 +#, kde-format +msgid "Nesting" +msgstr "متداخل ببعض" + +#: treemap.cpp:3254 +#, kde-format +msgid "Border" +msgstr "حد" + +#: treemap.cpp:3257 +#, kde-format +msgid "Correct Borders Only" +msgstr "صلّح الإطارات فقط" + +#: treemap.cpp:3260 +#, kde-format +msgid "Width %1" +msgstr "العرض %1" + +#: treemap.cpp:3263 +#, kde-format +msgid "Allow Rotation" +msgstr "اسمح بالدوران" + +#: treemap.cpp:3264 +#, kde-format +msgid "Shading" +msgstr "تظليل" + +#: treemap.cpp:3275 +#, kde-format +msgid "Visible" +msgstr "ظاهر" + +#: treemap.cpp:3276 +#, kde-format +msgid "Take Space From Children" +msgstr "خذ مسافة من الأولاد" + +#: treemap.cpp:3280 +#, kde-format +msgid "Top Left" +msgstr "أعلى اليسار" + +#: treemap.cpp:3283 +#, kde-format +msgid "Top Center" +msgstr "أعلى الوسط" + +#: treemap.cpp:3286 +#, kde-format +msgid "Top Right" +msgstr "أعلى اليمين" + +#: treemap.cpp:3289 +#, kde-format +msgid "Bottom Left" +msgstr "أسفل اليسار" + +#: treemap.cpp:3292 +#, kde-format +msgid "Bottom Center" +msgstr "أسفل الوسط" + +#: treemap.cpp:3295 +#, kde-format +msgid "Bottom Right" +msgstr "أسفل اليمين" + +#: treemap.cpp:3364 +#, kde-format +msgid "No %1 Limit" +msgstr "لا %1 حدود" + +#: treemap.cpp:3424 +#, kde-format +msgid "No Area Limit" +msgstr "لا حدود للمنطقة" + +#: treemap.cpp:3430 +#, kde-format +msgid "Area of '%1' (%2)" +msgstr "منطقة لـ '%1' (%2)" + +#: treemap.cpp:3442 treemap.cpp:3455 +#, kde-format +msgid "1 Pixel" +msgid_plural "%1 Pixels" +msgstr[0] "بكسل واحد" +msgstr[1] "بكسل واحد" +msgstr[2] "بكسلان" +msgstr[3] "%1 بكسلات" +msgstr[4] "%1 بكسلا" +msgstr[5] "%1 بكسل" + +#: treemap.cpp:3459 +#, kde-format +msgid "Double Area Limit (to %1)" +msgstr "ضعف حدود المساحة (إلى %1)" + +#: treemap.cpp:3461 +#, kde-format +msgid "Halve Area Limit (to %1)" +msgstr "اقسم حدود المساحة الى النصف (حتى %1)" + +#: treemap.cpp:3498 +#, kde-format +msgid "No Depth Limit" +msgstr "لا حدود للعمق" + +#: treemap.cpp:3504 +#, kde-format +msgid "Depth of '%1' (%2)" +msgstr "العمق لـ '%1' (%2)" + +#: treemap.cpp:3516 treemap.cpp:3529 +#, kde-format +msgid "Depth %1" +msgstr "العمق %1" + +#: treemap.cpp:3533 +#, kde-format +msgid "Decrement (to %1)" +msgstr "التناقص (إلى %1)" + +#: treemap.cpp:3535 +#, kde-format +msgid "Increment (to %1)" +msgstr "الزيادة إلى (إلى %1)" + +#~ msgid "Filesystem Utilization Viewer" +#~ msgstr "عارض استخدام نظام الملفات" + +#~ msgid "(c) 2003-2005, Josef Weidendorfer" +#~ msgstr "(c) 2003-2005, Josef Weidendorfer" diff --git a/po/ar/imgalleryplugin.po b/po/ar/imgalleryplugin.po new file mode 100644 index 0000000..dfdcf6d --- /dev/null +++ b/po/ar/imgalleryplugin.po @@ -0,0 +1,288 @@ +# translation of imgalleryplugin.po to Arabic +# translation of imgalleryplugin.po to +# Copyright (C) 2001,2002, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# Mohammed Gamal , 2001, 2004. +# Isam Bayazidi , 2002. +# Ahmad M. Zawawi , 2004. +# محمد سعد Mohamed SAAD , 2006. +# Youssef Chahibi , 2007. +# zayed , 2008, 2009, 2012. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: imgalleryplugin\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-07-30 23:48+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#: imgallerydialog.cpp:53 +#, kde-format +msgctxt "@title:window" +msgid "Create Image Gallery" +msgstr "أنشئ معرضًا للصور" + +#: imgallerydialog.cpp:54 +#, kde-format +msgid "Create" +msgstr "أنشئ" + +#: imgallerydialog.cpp:64 imgallerydialog.cpp:104 +#, kde-format +msgid "Image Gallery for %1" +msgstr "معرض صور لِـ ‎%1" + +#: imgallerydialog.cpp:92 +#, kde-format +msgid "Look" +msgstr "المظهر" + +#: imgallerydialog.cpp:93 +#, kde-format +msgid "Page Look" +msgstr "مظهر الصفحة" + +#: imgallerydialog.cpp:101 +#, kde-format +msgid "&Page title:" +msgstr "عنوان ال&صفحة:" + +#: imgallerydialog.cpp:111 +#, kde-format +msgid "I&mages per row:" +msgstr "الص&ور لكلّ صف:" + +#: imgallerydialog.cpp:119 +#, kde-format +msgid "Show image file &name" +msgstr "أظهر ا&سم ملف الصورة" + +#: imgallerydialog.cpp:123 +#, kde-format +msgid "Show image file &size" +msgstr "أظهر &حجم ملف الصورة" + +#: imgallerydialog.cpp:127 +#, kde-format +msgid "Show image &dimensions" +msgstr "أظهر أب&عاد الصورة" + +#: imgallerydialog.cpp:140 +#, kde-format +msgid "Fon&t name:" +msgstr "اسم ال&خط:" + +#: imgallerydialog.cpp:155 +#, kde-format +msgid "Font si&ze:" +msgstr "ح&جم الخط:" + +#: imgallerydialog.cpp:167 +#, kde-format +msgid "&Foreground color:" +msgstr "لون الأ&مامية:" + +#: imgallerydialog.cpp:179 +#, kde-format +msgid "&Background color:" +msgstr "لون ال&خلفية:" + +#: imgallerydialog.cpp:191 imgallerydialog.cpp:192 +#, kde-format +msgid "Folders" +msgstr "المجلدات" + +#: imgallerydialog.cpp:201 +#, kde-format +msgid "&Save to HTML file:" +msgstr "ا&حفظ إلى ملف HTML:" + +#: imgallerydialog.cpp:204 +#, kde-format +msgid "

The name of the HTML file this gallery will be saved to.

" +msgstr "

اسم ملف HTML الذي سيُحفظ به اسم هذا المعرض.

" + +#: imgallerydialog.cpp:215 +#, fuzzy, kde-format +msgid "&Recurse subfolders" +msgstr "&ضمن الملفات الفرعية عوديا" + +#: imgallerydialog.cpp:217 +#, fuzzy, kde-format +msgid "" +"

Whether subfolders should be included for the image gallery creation or " +"not.

" +msgstr "

إذا ما كان يجب تضمين الملفات الفرعية لإنشاء معرض الصور أم لا

" + +#: imgallerydialog.cpp:225 +#, fuzzy, kde-format +msgid "Rec&ursion depth:" +msgstr "عمق ال&تضمين العودي:" + +#: imgallerydialog.cpp:227 +#, fuzzy, kde-format +msgid "Endless" +msgstr "بلا نهاية" + +#: imgallerydialog.cpp:230 +#, fuzzy, kde-format +msgid "" +"

You can limit the number of folders the image gallery creator will " +"traverse to by setting an upper bound for the recursion depth.

" +msgstr "" +"

You can limit the number of folders the image gallery creator will " +"traverse to by setting an upper bound for the recursion depth.

" + +#: imgallerydialog.cpp:241 +#, kde-format +msgid "Copy or&iginal files" +msgstr "انسخ الملفات الأ&صلية" + +#: imgallerydialog.cpp:244 +#, fuzzy, kde-format +msgid "" +"

This makes a copy of all images and the gallery will refer to these " +"copies instead of the original images.

" +msgstr "" +"

سيصنع هذا نسخ من الصور ، وسيجعل المعرض يشير إلى هذه النسخ عوضا عن الصور " +"الأصلية.

" + +#: imgallerydialog.cpp:249 +#, kde-format +msgid "Use &comment file" +msgstr "استخدم ملف الت&عليق" + +#: imgallerydialog.cpp:253 +#, fuzzy, kde-format +msgid "" +"

If you enable this option you can specify a comment file which will be " +"used for generating subtitles for the images.

For details about the " +"file format please see the \"What's This?\" help below.

" +msgstr "" +"

إذا فعلت هذا الخيار ، فبإمكانك أن تحد ملف تعليق بحيث سيستعمللإنشاء عناوين " +"فرعية للصورة.

لمزيد من التفاصيل عن تنسيق الملف انظر مساعدة \"ما هذا؟" +"\" في الأسفل.

" + +#: imgallerydialog.cpp:260 +#, kde-format +msgid "Comments &file:" +msgstr "م&لف التعليقات:" + +#: imgallerydialog.cpp:263 +#, fuzzy, kde-format +msgid "" +"

You can specify the name of the comment file here. The comment file " +"contains the subtitles for the images. The format of this file is:

FILENAME1:
Description

FILENAME2:
Description

and so on

" +msgstr "" +"

يمكن تحديد اسم ملف التعليق هنا. ملف التعليق يحويالعناوين الفرعية للصور. " +"تنسيق هذا الملف هو :

الصور1
الوصف

الصورة2:
الوصف

وهكذا

" + +#: imgallerydialog.cpp:294 imgallerydialog.cpp:295 +#, kde-format +msgid "Thumbnails" +msgstr "المصغّرات" + +#: imgallerydialog.cpp:314 +#, kde-format +msgid "Image format f&or the thumbnails:" +msgstr "هيئة صور الم&صغّرات:" + +#: imgallerydialog.cpp:322 +#, kde-format +msgid "Thumbnail size:" +msgstr "حجم المصغّرة:" + +#: imgallerydialog.cpp:334 +#, kde-format +msgid "&Set different color depth:" +msgstr "&عيّن عمق ألوان مختلف:" + +#: imgalleryplugin.cpp:64 +#, kde-format +msgid "&Create Image Gallery..." +msgstr "أ&نشئ معرضًا للصور..." + +#: imgalleryplugin.cpp:74 +#, kde-format +msgid "Could not create the plugin, please report a bug." +msgstr "تعذّر إنشاء الملحقة، فضلًا أبلغ عن علة." + +#: imgalleryplugin.cpp:80 +#, kde-format +msgid "Creating an image gallery works only on local folders." +msgstr "إنشاء معرض الصور يعمل فقط على المجلدات المحلية." + +#: imgalleryplugin.cpp:100 +#, kde-format +msgid "Creating thumbnails" +msgstr "ينشئ المصغّرات" + +#: imgalleryplugin.cpp:123 imgalleryplugin.cpp:290 +#, kde-format +msgid "Could not create folder: %1" +msgstr "تعذّر إنشاء المجلد: %1" + +#: imgalleryplugin.cpp:185 +#, kde-format +msgid "Number of images: %1" +msgstr "عدد الصور: %1" + +#: imgalleryplugin.cpp:186 +#, kde-format +msgid "Created on: %1" +msgstr "أُنشئت في: %1" + +#: imgalleryplugin.cpp:191 +#, kde-format +msgid "Subfolders:" +msgstr "المجلدات الفرعية:" + +#: imgalleryplugin.cpp:224 +#, kde-format +msgid "" +"Created thumbnail for: \n" +"%1" +msgstr "" +"أُنشئت مصغّرة لِــ : \n" +"%1" + +#: imgalleryplugin.cpp:227 +#, kde-format +msgid "" +"Creating thumbnail for: \n" +"%1\n" +" failed" +msgstr "" +"فضل إنشاء مصغّرة لِــ: \n" +"%1" + +#: imgalleryplugin.cpp:245 +#, kde-format +msgid "KiB" +msgstr "ك.بايت" + +#: imgalleryplugin.cpp:352 imgalleryplugin.cpp:447 +#, kde-format +msgid "Could not open file: %1" +msgstr "تعذّر فتح الملف %1" + +#. i18n: ectx: Menu (tools) +#: kimgalleryplugin.rc:4 +#, kde-format +msgid "&Tools" +msgstr "أ&دوات" + +#~ msgctxt "@title:window" +#~ msgid "Configure" +#~ msgstr "اضبط" diff --git a/po/ar/kcmbookmarks.po b/po/ar/kcmbookmarks.po new file mode 100644 index 0000000..a835ca8 --- /dev/null +++ b/po/ar/kcmbookmarks.po @@ -0,0 +1,1421 @@ +# translation of kcmkio.po to Arabic +# translation of kcmkio.po to +# Copyright (C) 2001,2002,2003, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# Mohammed Yousif , 2001. +# Isam Bayazidi , 2002. +# Ammar Tabbaa , 2004. +# محمد سعد Mohamed SAAD , 2006. +# AbdulAziz AlSharif , 2007. +# عبدالعزيز الشريف , 2007. +# Youssef Chahibi , 2007. +# zayed , 2008, 2009. +# Zayed Al-Saidi , 2010. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kcmkio\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-08-18 16:14+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#: bookmarks.cpp:104 +#, kde-format +msgid "" +"

My Bookmarks

This module lets you configure the bookmarks home " +"page.

The bookmarks home page is accessible at bookmarks:/.

" +msgstr "" +"

علاماتي

تسمح لك هذه الوحدة بضبط صفحة العلامات.

يمكنك " +"الوصول إلى صفحة العلامات من bookmarks:/.

" + +#. i18n: ectx: property (title), widget (QGroupBox, groupBox) +#: bookmarks.ui:16 +#, kde-format +msgid "Bookmarks" +msgstr "العلامات" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, cbShowRoot) +#: bookmarks.ui:23 +#, kde-format +msgid "" +"If this option is unchecked, bookmarks at the root of the hierarchy (not in " +"a folder) are not displayed.\n" +"If checked, they are gathered in a \"root\" folder." +msgstr "" +"إن لم يُعلَّم ها الخيار، لن تُعرض العلامات التي في جذر الهرم (ليست في مجلد).\n" +"إذا عُلِّم، ستُجمع في مجلد \"الجذر\"." + +#. i18n: ectx: property (text), widget (QCheckBox, cbShowRoot) +#: bookmarks.ui:26 +#, kde-format +msgid "&Show bookmarks without folder" +msgstr "أ&ظهر العلامات بلا مجلد" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, cbFlattenTree) +#: bookmarks.ui:37 +#, kde-format +msgid "" +"Sub-folders are shown within their parent by default. If you activate this " +"option, sub-folders are displayed on their own.\n" +"It looks less nice but it may help if you have a very big folder you want to " +"spread in two columns." +msgstr "" +"تُعرض المجلدات الفرعية في أبواتها افتراضيًا. إن فعّلت هذا الخيار، ستُعرض " +"المجلدات الفرعية منفصلة.\n" +"قد يبدو هذا أقل جمالًا ولكن قد يكون مفيدًا إذا كنت تملك مجلد ضخم وتريد عرضه في " +"عمودين منفصلين." + +#. i18n: ectx: property (text), widget (QCheckBox, cbFlattenTree) +#: bookmarks.ui:40 +#, kde-format +msgid "&Flatten bookmarks tree" +msgstr "س&طّح شجرة العلامات" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, cbShowPlaces) +#: bookmarks.ui:47 +#, kde-format +msgid "" +"Show a box with KDE places (Home, Network, ...). Useful if you use konqueror " +"as a file manager." +msgstr "" +"يُظهر مربعًا بأماكن كدي (المنزل، الشبكة، ...). مفيد إن كنت تستخدم كنكر كمدير " +"للملفات." + +#. i18n: ectx: property (text), widget (QCheckBox, cbShowPlaces) +#: bookmarks.ui:50 +#, kde-format +msgid "Show system &places" +msgstr "أظهر أ&ماكن النظام" + +#. i18n: ectx: property (title), widget (QGroupBox, groupBox_2) +#: bookmarks.ui:63 +#, kde-format +msgid "General Settings" +msgstr "إعدادات عامة" + +#. i18n: ectx: property (whatsThis), widget (QLabel, label) +#: bookmarks.ui:71 +#, kde-format +msgid "" +"Folders are automatically distributed in several columns. The optimal number " +"of columns depends on the width of the konqueror window and the number of " +"bookmarks you have." +msgstr "" +"تتوزع المجلدات آليًا في عدّة أعمدة. عدد الأعمدة المثالي يعتمد على عرض نافذة " +"كنكر وعدد العلامات التي فيها." + +#. i18n: ectx: property (text), widget (QLabel, label) +#: bookmarks.ui:74 +#, kde-format +msgid "Number of columns to show:" +msgstr "عدد الأعمدة لعرضها:" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, cbShowBackgrounds) +#: bookmarks.ui:109 +#, kde-format +msgid "Disable it on slow system to disable background images." +msgstr "عطلّه في الأنظمة البطيئة أو عطّل صور الخلفية." + +#. i18n: ectx: property (text), widget (QCheckBox, cbShowBackgrounds) +#: bookmarks.ui:112 +#, kde-format +msgid "Show folder &backgrounds" +msgstr "أظهر &خلفيات المجلدات" + +#. i18n: ectx: property (whatsThis), widget (QGroupBox, groupBox_3) +#: bookmarks.ui:138 +#, fuzzy, kde-format +msgid "How much disk space is used to cache the pixmaps" +msgstr "كمية مساحة القرص لاستخدامها في خبيئة الصور النقطية" + +#. i18n: ectx: property (title), widget (QGroupBox, groupBox_3) +#: bookmarks.ui:141 +#, fuzzy, kde-format +msgid "Pixmap Cache" +msgstr "خبيئة الصور النقطية" + +#. i18n: ectx: property (text), widget (QLabel, lbMaxCacheSize) +#: bookmarks.ui:150 +#, kde-format +msgid "Disk cache size:" +msgstr "حجم خبيئة القرص:" + +#. i18n: ectx: property (suffix), widget (QSpinBox, sbCacheSize) +#: bookmarks.ui:163 +#, kde-format +msgid " kB" +msgstr " ك.بايت" + +#. i18n: ectx: property (whatsThis), widget (QPushButton, clearCacheButton) +#: bookmarks.ui:173 +#, fuzzy, kde-format +msgid "Clear the pixmap cache" +msgstr "امحُ خبيئة الصور النقطية" + +#. i18n: ectx: property (text), widget (QPushButton, clearCacheButton) +#: bookmarks.ui:176 +#, kde-format +msgid "&Clear Cache" +msgstr "امحُ ال&خبيئة" + +#~ msgid "" +#~ "

Cache

This module lets you configure your cache settings.

The cache is an internal memory in Konqueror where recently read web " +#~ "pages are stored. If you want to retrieve a web page again that you have " +#~ "recently read, it will not be downloaded from the Internet, but rather " +#~ "retrieved from the cache, which is a lot faster.

" +#~ msgstr "" +#~ "

الخبيئة

تسمح لك هذه الوحدة بضبط إعدادات الخبيئة.

الخبيئة " +#~ "هي ذاكرة داخلية في كنكر تُخزَّن فيها بصفحات الوِب التي قرأتها حديثًا. إذا رغبت " +#~ "في جلب صفحة الوِب مجدّدًا؛ لن تُنزَّل من الإنترنت من جديد، بل ستُجلب من الخبيئة، " +#~ "وهذا أسرع بكثير من تنزيلها.

" + +#~ msgid "" +#~ "Check this box if you want the web pages you visit to be stored on your " +#~ "hard disk for quicker access. The stored pages will only be updated as " +#~ "needed instead of on every visit to that site. This is especially useful " +#~ "if you have a slow connection to the Internet." +#~ msgstr "" +#~ "علّم هذا إذا كنت ترغب في تخزين صفحات الوِب التي زرتها على القرص الصلب وهذا " +#~ "للوصول السريع إليها. ستُحدَّث الصفحات المُخزَّنة فقط عند الحاجة، بدلاً من كلّ " +#~ "زيارة لذاك الموقع. هذه الميزة مفيدة بشكل خاص إذا كان لديك اتصال بطيء " +#~ "بالإنترنت." + +#~ msgid "&Use cache" +#~ msgstr "اس&تخدم الخبيئة" + +#~ msgid "Policy" +#~ msgstr "السياسة" + +#~ msgid "" +#~ "Verify whether the cached web page is valid before attempting to fetch " +#~ "the web page again." +#~ msgstr "" +#~ "تحقّق فيما إذا كانت صفحة الوِب المُخبَّئة صالحة قبل محاولة جلب صفحة الوِب مجدّدًا." + +#~ msgid "&Keep cache in sync" +#~ msgstr "&حافظ على مزامنة الخبيئة" + +#~ msgid "" +#~ "Always use documents from the cache when available. You can still use the " +#~ "reload button to synchronize the cache with the remote host." +#~ msgstr "" +#~ "استخدم المستندات من الخبيئة عندما تكون متوفّرة. ما زال يمكنك استخدام زرّ " +#~ "إعادة التحميل لمزامنة الخبيئة مع المضيف البعيد." + +#~ msgid "Use cache whenever &possible" +#~ msgstr "استخدم الخبيئة كلّما أم&كن" + +#~ msgid "" +#~ "Do not fetch web pages that are not already stored in the cache. Offline " +#~ "mode prevents you from viewing pages that you have not previously visited." +#~ msgstr "" +#~ "لا تجلب صفحات الوِب غير المخزّنة في الخبيئة. يمنعك وضع عدم الاتصال من عرض " +#~ "صفحات لم تزرها من قبل." + +#~ msgid "O&ffline browsing mode" +#~ msgstr "وضع التصفّح ب&دون اتصال" + +#~ msgid "Disk cache &size:" +#~ msgstr "ح&جم خبيئة القرص:" + +#~ msgid " KiB" +#~ msgstr " ك.بايت" + +#~ msgid "C&lear Cache" +#~ msgstr "ا&محُ الخبيئة" + +#~ msgid "" +#~ "Unable to start the cookie handler service.\n" +#~ "You will not be able to manage the cookies that are stored on your " +#~ "computer." +#~ msgstr "" +#~ "تعذّر بدأ خدمة التعامل مع الكعكات.\n" +#~ "لن تستطيع إدارة الكعكات المخزّنة على الحاسوب." + +#~ msgid "&Policy" +#~ msgstr "ال&سياسة" + +#~ msgid "&Management" +#~ msgstr "ال&إدارة" + +#~ msgid "" +#~ "

Cookies

Cookies contain information that Konqueror (or other " +#~ "KDE applications using the HTTP protocol) stores on your computer, " +#~ "initiated by a remote Internet server. This means that a web server can " +#~ "store information about you and your browsing activities on your machine " +#~ "for later use. You might consider this an invasion of privacy.

" +#~ "However, cookies are useful in certain situations. For example, they are " +#~ "often used by Internet shops, so you can 'put things into a shopping " +#~ "basket'. Some sites require you have a browser that supports cookies.

Because most people want a compromise between privacy and the " +#~ "benefits cookies offer, KDE offers you the ability to customize the way " +#~ "it handles cookies. So you might want to set KDE's default policy to ask " +#~ "you whenever a server wants to set a cookie, allowing you to decide. For " +#~ "your favorite shopping web sites that you trust, you might want to set " +#~ "the policy to accept, then you can access the web sites without being " +#~ "prompted every time KDE receives a cookie.

" +#~ msgstr "" +#~ "

الكعكات

تحوي الكعكات معلومات يخزّنها كنكر (أو أيّ تطبيق كدي أخر " +#~ "يستخدم ميفاق HTTP )على الحاسوب، وهي تبدأ بطلب من خادوم الإنترنت البعيد. " +#~ "هذا يعني أنّ خادوم الوِب يمكنه تخزين معلومات عنك وعن نشاطات المتصفّح في " +#~ "الحاسوب لكي يستخدمها في وقت لاحق، قد تعتبر هذا انتهاكًا لخصوصيتك.

" +#~ "على أيّ حال، قد تكون الكعكات مفيدة في بعض الأحيان. فعلى سبيل المثال، " +#~ "تُستخدم الكعكات في المتاجر الإلكترونية لتُنشئ سلة مشتريات. بعض المواقع تطلب " +#~ "أن يكون المتصفّح داعمًا للكعكات.

وبسبب أنّ أغلب الناس تريد أن توازن " +#~ "بين الخصوصية ومنافع الكعكات، فإنّ كدي توفّر لك إمكانية تخصيص طريقة التعامل " +#~ "مع الكعكات. فقد ترغب أن تعيّن سياسة كدي الافتراضية لسؤالك فيما كان الخادوم " +#~ "يودّ تعيين كعكة، سامحًا لك بأن ترفض. قد ترغب بتعيين السياسة للسماح بكعكات " +#~ "مواقع الوِب للشراء المفضّلة لديك والتي تثق بها، فيمكنك الوصول إلى الموقع " +#~ "دون الحاجة إلى تأكيدك لاستقبال كدي الكعكة في كلّ مرة.

" + +#~ msgid "D-Bus Communication Error" +#~ msgstr "خطأ تواصل مع D-Bus" + +#~ msgid "Unable to delete all the cookies as requested." +#~ msgstr "تعذّر حذف كلّ الكعكات كما طُلِب." + +#~ msgid "Unable to delete cookies as requested." +#~ msgstr "تعذّر حذف الكعكات كما طُلِب." + +#~ msgid "

Cookie Management Quick Help

" +#~ msgstr "

المساعدة السريعة لإدارة الكعكات

" + +#~ msgid "Information Lookup Failure" +#~ msgstr "فشل في البحث عن المعلومات" + +#~ msgid "" +#~ "Unable to retrieve information about the cookies stored on your computer." +#~ msgstr "تعذّر استرجاع معلومات حول الكعكات المخزّنة على الحاسوب." + +#~ msgid "End of session" +#~ msgstr "نهاية الجلسة" + +#~ msgid "Yes" +#~ msgstr "نعم" + +#~ msgid "Search" +#~ msgstr "ابحث عن" + +#~ msgid "Search interactively for domains and hosts" +#~ msgstr "ابحث بشكل تفاعلي عن المجالات والمضيفين" + +#~ msgid "Site" +#~ msgstr "الموقع" + +#~ msgid "Cookie Name" +#~ msgstr "اسم الكعكة" + +#~ msgid "D&elete" +#~ msgstr "ا&حذف" + +#~ msgid "Delete A&ll" +#~ msgstr "احذف ال&كلّ" + +#~ msgid "Configure &Policy..." +#~ msgstr "اضبط ال&سياسة..." + +#~ msgid "&Reload List" +#~ msgstr "أ&عد تحميل القائمة" + +#~ msgid "Details" +#~ msgstr "تفاصيل" + +#~ msgid "Name:" +#~ msgstr "الاسم:" + +#~ msgid "Value:" +#~ msgstr "القيمة:" + +#~ msgid "Domain:" +#~ msgstr "المجال:" + +#~ msgid "Path:" +#~ msgstr "المسار:" + +#~ msgid "Expires:" +#~ msgstr "تنتهي في:" + +#~ msgid "Secure:" +#~ msgstr "آمن:" + +#~ msgctxt "@title:window" +#~ msgid "Change Cookie Policy" +#~ msgstr "غيّر سياسة الكعكات" + +#~ msgctxt "@title:window" +#~ msgid "New Cookie Policy" +#~ msgstr "سياسة كعكات جديدة" + +#~ msgid "" +#~ "A policy already exists for
%1
Do you want to " +#~ "replace it?
" +#~ msgstr "" +#~ "هناك سياسة موجودة بالفعل لِـ
%1
أتريد استبدالها؟" +#~ "
" + +#~ msgctxt "@title:window" +#~ msgid "Duplicate Policy" +#~ msgstr "سياسة مكرّرة" + +#~ msgid "Replace" +#~ msgstr "استبدل" + +#~ msgid "" +#~ "Unable to communicate with the cookie handler service.\n" +#~ "Any changes you made will not take effect until the service is restarted." +#~ msgstr "" +#~ "تعذّر التواصل مع خدمة التعامل مع الكعكات.\n" +#~ "أيّ تعديلات قمت بها لن تُطبَّق حتّى يُعاد تشغيل الخدمة." + +#, fuzzy +#~ msgid "" +#~ "

Cookies

Cookies contain information that Konqueror (or any " +#~ "other KDE application using the HTTP protocol) stores on your computer " +#~ "from a remote Internet server. This means that a web server can store " +#~ "information about you and your browsing activities on your machine for " +#~ "later use. You might consider this an invasion of privacy.

However, " +#~ "cookies are useful in certain situations. For example, they are often " +#~ "used by Internet shops, so you can 'put things into a shopping basket'. " +#~ "Some sites require you have a browser that supports cookies.

Because most people want a compromise between privacy and the " +#~ "benefits cookies offer, KDE offers you the ability to customize the way " +#~ "it handles cookies. You might, for example want to set KDE's default " +#~ "policy to ask you whenever a server wants to set a cookie or simply " +#~ "reject or accept everything. For example, you might choose to accept all " +#~ "cookies from your favorite shopping web site. For this all you have to do " +#~ "is either browse to that particular site and when you are presented with " +#~ "the cookie dialog box, click on This domain under the 'apply to' " +#~ "tab and choose accept or simply specify the name of the site in the " +#~ "Domain Specific Policy tab and set it to accept. This enables you to " +#~ "receive cookies from trusted web sites without being asked every time KDE " +#~ "receives a cookie.

" +#~ msgstr "" +#~ "

الكعك

يحوي الكعك على معلومات يخزنها الكونكيور (أو أي تطبيق كدي " +#~ "أخر يستعمل بروتوكول HTTP )على جهازك ، وهي تنشئ بطلب من خادم الإنترنت " +#~ "البعيد. هذا يعني أن خادم الويب يستطيع تخزين معلومات عنك وعن نشاطات متصفحك " +#~ "في حاسوبك لكي يستخدمها في وقت لاحق ، ربما قد تعتبر هذا انتهاكا لخصوصيتك.

على كل حال قد تكون الكعك مفيدة في بعض الأحيان ، فعلى سبيل المثال ، " +#~ "تستخدم الكعك في المتاجر الإلكتروني لتنشئ سلة مشتريات . بعض المواقع تطلب " +#~ "أن يكون المتصفح داعما للكعك.

و بسبب أن أغلب الناس تريد أن توازن " +#~ "بين الخصوصية و المنافع الكعك ؛ فإن كيدي توفر لك القدرة على تخصيص طريقة " +#~ "التعامل مع الكعك . فقد ترغب أن تجعل سياسة كيدي هي طلب الإذن لأي خادم يريد " +#~ "أن ينشئ كعك ، وقد ترغب في السماح للمتاجرك الإلكترونية المفضلة التي تثق " +#~ "فيها أن تنشئ كعك كما تريد ، فيمكنك وضع سياسة قبول الكعك بدون طلب الإذن " +#~ "لهذه المواقع.

كل ما عليك هو أن تذهب إلى ذاك الموقع و عندما يظهر لك " +#~ "مربع حوار الكعك ، انقر على هذا المجال تحت لسان 'طبق على' و اختر " +#~ "اسمح أو حدد بكل بساطة اسم الموقع في لسان سياسة المجالات الخاصة " +#~ "ثم وافق على قبولها ، هذا يمكنك من استقبال كعك من المواقع الموثوقة بدون " +#~ "الحاجة إلى سؤالك كل مرة تستقبل فيها الكعك." + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "

Enable cookie support. Normally you will want to have cookie support " +#~ "enabled and customize it to suit your privacy needs.

\n" +#~ "Please note that disabling cookie support might make many web sites " +#~ "unbrowsable.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "

مكّن دعم الكعكات. عادة سترغب في تمكين دعم الكعكات وتخصيصها لتلائم حاجتك " +#~ "للخصوصية.

\n" +#~ "من فضلك لاحظ أن تعطيل دعم الكعكات سيجعلك غير قادر على تصفح الكثير من " +#~ "مواقع الشبكة .

\n" +#~ "
" + +#~ msgid "Enable coo&kies" +#~ msgstr "مكّن ال&كعكات" + +#~ msgid "Only acce&pt cookies from originating server" +#~ msgstr "ا&قبل الكعكات من الخادم الأصلي فقط" + +#~ msgid "Automaticall&y accept session cookies" +#~ msgstr "اقبل كعكات الجلسة آ&ليًا" + +#~ msgid "Default Policy" +#~ msgstr "السياسة الافتراضية" + +#~ msgid "Accep&t all cookies" +#~ msgstr "ا&قبل كلّ الكعكات" + +#~ msgid "Accept &until end of session" +#~ msgstr "اقبل حتّى ن&هاية الجلسة" + +#~ msgid "Ask &for confirmation" +#~ msgstr "اطلب ال&تأكيد" + +#~ msgid "Re&ject all cookies" +#~ msgstr "ارف&ض كلّ الكعكات" + +#~ msgid "" +#~ "\n" +#~ "To add a new policy, simply click on the Add... button and supply " +#~ "the necessary information. To change an existing policy, use the " +#~ "Change... button and choose the new policy from the policy dialog " +#~ "box. Clicking on the Delete button will remove the currently " +#~ "selected policy causing the default policy setting to be used for that " +#~ "domain, whereas Delete All will remove all the site specific " +#~ "policies.\n" +#~ "" +#~ msgstr "" +#~ "ع\n" +#~ "لإضافة سياسة جديدة، ببساطة انقر زرّ أضف... وأدخِل المعلومات " +#~ "الضرورية. ولتغيير سياسة موجودة، استخدم زرّ غيّر... واختر السياسة " +#~ "الجديدة من مربع حواري السياسات. نقر الزرّ احذف سيزيل السياسة " +#~ "المحدّدة حاليًا مسبّبًا استخدام السياسة الافتراضية لذاك المجال. بينما الزرّ " +#~ "احذف الكلّ يزيل كلّ السياسات الخاصّة بهذا المجال.\n" +#~ "" + +#~ msgid "Site Policy" +#~ msgstr "سياسة الموقع" + +#~ msgid "Search interactively for domains" +#~ msgstr "ابحث بشكل تفاعلي عن المجالات" + +#~ msgid "" +#~ "\n" +#~ "List of sites for which you have set a specific cookie policy. Specific " +#~ "policies override the default policy setting for these sites.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "قائمة المواقع التي وضعت لها سياسة كعكات محدّدة. السياسات المحدّدة ستتجاوز " +#~ "إعدادات السياسة الافتراضية لهذه المواقع.\n" +#~ "" + +#~ msgid "Domain" +#~ msgstr "المجال" + +#~ msgid "&New..." +#~ msgstr "&جديد..." + +#~ msgid "Chan&ge..." +#~ msgstr "&غيّر..." + +#~ msgid "" +#~ "\n" +#~ "Enter the host or domain to which this policy applies, e.g. www.kde." +#~ "org or .kde.org.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم المضيف أو المجال الذي ستُطبَّق السياسة عليه. مثلاً www.kde.org أو .kde.org.\n" +#~ "" + +#~ msgid "Site name:" +#~ msgstr "اسم الموقع:" + +#~ msgid "" +#~ "Enter the host or domain name, e.g. .kde.org, this policy applies to." +#~ msgstr "" +#~ "أدخِل اسم المضيف أو المجال، مثلًا \"‎.kde.org\"، التي ستُطبَّق السياسة عليه." + +#~ msgid "" +#~ "\n" +#~ "Select the desired policy:\n" +#~ "
    \n" +#~ "
  • Accept - Allows this site to set cookies
  • \n" +#~ "
  • Accept until end of session - Allows this site to set cookies " +#~ "but they will expire at the end of the session.
  • \n" +#~ "
  • Reject - Refuse all cookies sent from this site
  • \n" +#~ "
  • Ask - Prompt when cookies are received from this site
  • \n" +#~ "
\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "اختر السياسة التي ترغب بها:\n" +#~ "
    \n" +#~ "
  • اقبل - السماح لهذا الموقع بتعيين كعكات
  • \n" +#~ "
  • ارفض - رفض كلّ الكعكات التي يرسلها هذا الموقع
  • \n" +#~ "
  • اسألني - السؤال كلّما استُقبِلت كعكات من هذا الموقع
  • \n" +#~ "
\n" +#~ "
" + +#~ msgid "Policy:" +#~ msgstr "السياسة:" + +#~ msgid "Accept" +#~ msgstr "اقبل" + +#~ msgid "Accept until end of session" +#~ msgstr "اقبل حتّى نهاية الجلسة" + +#~ msgid "Reject" +#~ msgstr "ارفض" + +#~ msgid "Ask" +#~ msgstr "اسألني" + +#~ msgid "Disable Passive FTP" +#~ msgstr "عطّل FTP السلبي" + +#, fuzzy +#~ msgid "" +#~ "When FTP connections are passive the client connects to the server, " +#~ "instead of the other way round, so firewalls do not block the connection; " +#~ "old FTP servers may not support Passive FTP though." +#~ msgstr "" +#~ "في اتصال FTP السلبي، ، يقوم العميل بالاتصال بالخادم بدلا أن يتصل الخادم " +#~ "بالعميل ؛ لذا لا يستطيع الجدار الناري منع الاتصال ، ولكن قد لا تدعم خوادم " +#~ "FTP القديم الـ FTP السلبي." + +#~ msgid "Mark partially uploaded files" +#~ msgstr "علّم الملفات المرفوعة &جزئيًا" + +#~ msgid "" +#~ "While a file is being uploaded its extension is \".part\". When fully " +#~ "uploaded it is renamed to its real name." +#~ msgstr "" +#~ "أثناء رفع ملف سيكون امتداده \"‎\".part. عند انتهاء الرفع ستُعاد تسميته إلى " +#~ "اسمه الحقيقي." + +#, fuzzy +#~ msgid "" +#~ "

Proxy

A proxy server is an intermediate program that sits " +#~ "between your machine and the Internet and provides services such as web " +#~ "page caching and/or filtering.

Caching proxy servers give you " +#~ "faster access to sites you have already visited by locally storing or " +#~ "caching the content of those pages; filtering proxy servers, on the other " +#~ "hand, provide the ability to block out requests for ads, spam, or " +#~ "anything else you want to block.

Note: Some proxy servers " +#~ "provide both services.

" +#~ msgstr "" +#~ "ب

الوكيل

خادوم الوكيل هو برنامج يتوسّط بين الجهاز والإنترنت، " +#~ "ويقدّم خدمات مثل التخزين المؤقت لصفحات الإنترنت و/أو التنقية.

خوادم " +#~ "التخزين المؤقت تعطيك سرعة النفاذ عالية للمواقع التي زرتها من قبل بواسطة " +#~ "تخزين هذه محتويات هذه المواقع بشكل مؤقت ، أما خوادم التقنيةأو الترشيح فيه " +#~ "تعطيك القدرة على منع الإعلانات أو السخام أو أي شيء أخر تريد منعه.

ملاحظة: بعض خوادم التنقية تقدم كلا الخدمتين.

" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "Setup proxy configuration.\n" +#~ "

\n" +#~ "A proxy server is an intermediate machine that sits between your computer " +#~ "and the Internet and provides services such as web page caching and " +#~ "filtering. Caching proxy servers give you faster access to web sites you " +#~ "have already visited by locally storing or caching those pages; filtering " +#~ "proxy servers usually provide the ability to block out requests for ads, " +#~ "spam, or anything else you want to block.\n" +#~ "

\n" +#~ "If you are uncertain whether or not you need to use a proxy server to " +#~ "connect to the Internet, consult your Internet service provider's setup " +#~ "guide or your system administrator.\n" +#~ "" +#~ msgstr "" +#~ "

الوكيل

خادم الوكيل هو برنامج يتوسط بين جهازك و الإنترنت ، و " +#~ "يقوم بتقديم خدمات مثل التخزين المؤقت لصفحات الإنترنت و/أو التنقية.

خوادم التخزين المؤقت تعطيك سرعة النفاذ عالية للمواقع التي زرتها من " +#~ "قبل بواسطة تخزين هذه محتويات هذه المواقع بشكل مؤقت ، أما خوادم التقنيةأو " +#~ "الترشيح فيه تعطيك القدرة على منع الإعلانات أو السخام أو أي شيء أخر تريد " +#~ "منعه.

ملاحظة: بعض خوادم التنقية تقدم كلا الخدمتين.

" + +#~ msgid "Connect to the Internet directly." +#~ msgstr "اتصل بالإنترنت مباشرة." + +#~ msgid "No Proxy" +#~ msgstr "لا وكيل" + +#~ msgid "Detect proxy configuration automatically" +#~ msgstr "اكتشف تضبيط الوكيل آليًا" + +#~ msgid "Use the specified proxy script to configure the proxy settings." +#~ msgstr "استخدم سكرِبت الوكيل المحدّد لضبط إعدادات الوكيل." + +#, fuzzy +#~ msgid "Use proxy auto configuration URL:" +#~ msgstr "استخدم عنوان " + +#~ msgid "Enter the address for the proxy configuration script." +#~ msgstr "أدخِل عنوان سكرِبت ضبط الوكيل." + +#~ msgid "Use system proxy configuration:" +#~ msgstr "استخدم تضبيط وكيل النظام:" + +#~ msgid "" +#~ "Attempt automatic discovery of the environment variables used for " +#~ "setting system wide proxy information.

This feature works by searching " +#~ "for commonly used variable names such as HTTP_PROXY, FTP_PROXY and " +#~ "NO_PROXY." +#~ msgstr "" +#~ "محاولة اكتشاف متغيّر البيئة المُستخدَم لمعلومات الوسيط في كامل النظام " +#~ "آليًا.

تعمل هذه الميزة عبر بحث أسماء المتغيّرات المُستخدَمة بكثرة مثل " +#~ "HTTP_PROXY، و FTP_PROXY و NO_PROXY." + +#~ msgid "Auto D&etect" +#~ msgstr "ا&كتشف آليًا" + +#~ msgid "" +#~ "\n" +#~ "Enter the name of the environment variable, e.g. HTTP_PROXY, used " +#~ "to store the address of the HTTP proxy server.

\n" +#~ "Alternatively, you can click on the \"Auto Detect\" button to " +#~ "attempt automatic discovery of this variable.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم متغيّر البيئة، مثلًا HTTP_PROXY، ليُستخدم في تخزين عنوان " +#~ "خادوم وكيل HTTP.

\n" +#~ "بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر " +#~ "آليًا.

\n" +#~ "
" + +#~ msgid "HTTP Proxy:" +#~ msgstr "وكيل HTTP:" + +#~ msgid "" +#~ "\n" +#~ "Enter the name of the environment variable, e.g. HTTPS_PROXY, used " +#~ "to store the address of the HTTPS proxy server.

\n" +#~ "Alternatively, you can click on the \"Auto Detect\" button to " +#~ "attempt an automatic discovery of this variable.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم متغيّر البيئة، مثلًا HTTPS_PROXY، ليُستخدم في تخزين عنوان " +#~ "خادوم وكيل HTTPS.

\n" +#~ "بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر " +#~ "آليًا.

\n" +#~ "
" + +#~ msgid "SSL Proxy:" +#~ msgstr "وكيل SSL:" + +#~ msgid "" +#~ "\n" +#~ "Enter the name of the environment variable, e.g. FTP_PROXY, used " +#~ "to store the address of the FTP proxy server.

\n" +#~ "Alternatively, you can click on the \"Auto Detect\" button to " +#~ "attempt an automatic discovery of this variable.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم متغيّر البيئة، مثلًا FTP_PROXY، ليُستخدم في تخزين عنوان " +#~ "خادوم وكيل FTP.

\n" +#~ "بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر " +#~ "آليًا.

\n" +#~ "
" + +#~ msgid "FTP Proxy:" +#~ msgstr "وكيل FTP:" + +#~ msgid "" +#~ "\n" +#~ "Enter the name of the environment variable, e.g. SOCKS_PROXY, used " +#~ "to store the address of the SOCKS proxy server.

\n" +#~ "Alternatively, you can click on the \"Auto Detect\" button to " +#~ "attempt an automatic discovery of this variable.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم متغيّر البيئة، مثلًا SOCKS_PROXY، ليُستخدم في تخزين عنوان " +#~ "خادوم وكيل SOCKS.

\n" +#~ "بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر " +#~ "آليًا.

\n" +#~ "
" + +#~ msgid "SOCKS Proxy:" +#~ msgstr "وكيل SOCKS:" + +#~ msgid "" +#~ "Enter the name of the environment variable, e.g. SOCKS_PROXY, " +#~ "used to store the address of the SOCKS proxy server.

Alternatively, you " +#~ "can click on the \"Auto Detect\" button to attempt an automatic " +#~ "discovery of this variable.

" +#~ msgstr "" +#~ "أدخِل اسم متغيّر البيئة، مثلًا SOCKS_PROXY، ليُستخدم في تخزين " +#~ "عنوان خادوم وكيل SOCKS.

بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" " +#~ "لمحاولة اكتشاف هذا المتغيّر آليًا.

" + +#~ msgid "" +#~ "\n" +#~ "Enter the environment variable, e.g. NO_PROXY, used to store the " +#~ "addresses of sites for which the proxy server should not be used.

\n" +#~ "Alternatively, you can click on the \"Auto Detect\" button to " +#~ "attempt an automatic discovery of this variable.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم متغيّر البيئة، مثلًا NO_PROXY، ليُستخدم في تخزين عنوانين " +#~ "المواقع التي لا يجب استخدام خادوم وكيل فيها.

\n" +#~ "بشكل بديل، يمكنك نقر زرّ \"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر " +#~ "آليًا.

\n" +#~ "
" + +#~ msgid "Exceptions:" +#~ msgstr "الاستثناءات:" + +#~ msgid "" +#~ "Enter the environment variable, e.g. NO_PROXY, used to store " +#~ "the addresses of sites for which the above proxy settings should not be " +#~ "used.

Alternatively, you can click on the \"Auto Detect\" button " +#~ "to attempt an automatic discovery of this variable.

" +#~ msgstr "" +#~ "أدخِل اسم متغيّر البيئة، مثلًا NO_PROXY، ليُستخدم في تخزين عنوانين " +#~ "المواقع التي لا يجب استخدام خادوم وكيل فيها.

بشكل بديل، يمكنك نقر زرّ " +#~ "\"اكتشف آليًا\" لمحاولة اكتشاف هذا المتغيّر آليًا.

" + +#~ msgid "Show the &value of the environment variables" +#~ msgstr "أظهر قيم مت&غيّرات البيئية" + +#~ msgid "Manually enter proxy server configuration information." +#~ msgstr "أدخِل معلومات ضبط خادوم الوكيل يدويًا." + +#~ msgid "Use manually specified proxy configuration:" +#~ msgstr "استخدم ضبط الوكيل المحدّد يدويًا:" + +#~ msgid "Enter the address of the HTTP proxy server." +#~ msgstr "أدخِل عنوان خادوم وكيل HTTP." + +#~ msgid "Port:" +#~ msgstr "المنفذ:" + +#~ msgid "Enter the port number of the HTTP proxy server." +#~ msgstr "أدخِل رقم منفذ خادوم وكيل HTTP." + +#~ msgid "Use this proxy server for a&ll protocols" +#~ msgstr "استخدم خادوم الوكيل هذا ل&كلّ الموافيق" + +#~ msgid "Enter the address of the HTTPS proxy server." +#~ msgstr "أدخِل عنوان خادوم وكيل HTTPS." + +#~ msgid "Enter the port number of the HTTPS proxy server." +#~ msgstr "أدخِل رقم منفذ خادوم وكيل HTTPS." + +#~ msgid "Enter the address of the FTP proxy server." +#~ msgstr "أدخِل عنوان خادوم وكيل FTP." + +#~ msgid "Enter the port number of the FTP proxy server." +#~ msgstr "أدخِل رقم منفذ خادوم وكيل FTP." + +#~ msgid "Enter the address of the SOCKS proxy server." +#~ msgstr "أدخِل عنوان خادوم وكيل SOCKS." + +#~ msgid "Enter the port number of the SOCKS proxy server." +#~ msgstr "أدخِل رقم منفذ خادوم وكيل SOCKS." + +#~ msgid "" +#~ "\n" +#~ "Check this box if you want the above proxy settings to apply only to the " +#~ "addresses listed in the Exceptions list." +#~ msgstr "" +#~ "\n" +#~ "علّم هذا المربع إن أردت أن تُطبَّق إعدادات الوكيل أعلاه فقط إلى العناوين " +#~ "المسردة في قائمة الاستثناءات." + +#~ msgid "Use proxy settings only for addresses in the Exceptions list" +#~ msgstr "استخدم إعدادات الوكيل فقط مع العناوين في قائمة الاستثناءات" + +#~ msgid "" +#~ "You have to restart the running applications for these changes to take " +#~ "effect." +#~ msgstr "عليك إعادة تشغيل التطبيقات العاملة لتُطبَّق هذه التغييرات." + +#~ msgctxt "@title:window" +#~ msgid "Update Failed" +#~ msgstr "فشل التحديث" + +#~ msgid "You have to restart KDE for these changes to take effect." +#~ msgstr "عليك إعادة تشغيل كدي لتطبيق التغييرات." + +#~ msgid "Timeout Values" +#~ msgstr "قِيَم المهلة" + +#~ msgid "" +#~ "Here you can set timeout values. You might want to tweak them if your " +#~ "connection is very slow. The maximum allowed value is 1 second." +#~ msgid_plural "" +#~ "Here you can set timeout values. You might want to tweak them if your " +#~ "connection is very slow. The maximum allowed value is %1 seconds." +#~ msgstr[0] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي 0 ثانية." +#~ msgstr[1] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي ثانية واحدة." +#~ msgstr[2] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي ثانيتين." +#~ msgstr[3] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي %1 ثوان." +#~ msgstr[4] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي %1 ثانية." +#~ msgstr[5] "" +#~ "يمكنك من هنا تعيين قِيَم المهلة. قد ترغب بتغييرها إذا كان اتصالك بالإنترنت " +#~ "بطيء جدًا. أكبر قيمة ممكنة هي %1 ثانية." + +#~ msgid " second" +#~ msgid_plural " seconds" +#~ msgstr[0] " ث" +#~ msgstr[1] " ث" +#~ msgstr[2] " ث" +#~ msgstr[3] " ث" +#~ msgstr[4] " ث" +#~ msgstr[5] " ث" + +#~ msgid "Soc&ket read:" +#~ msgstr "&قراءة المقبس:" + +#~ msgid "Pro&xy connect:" +#~ msgstr "الاتصال بال&وكيل:" + +#~ msgid "Server co&nnect:" +#~ msgstr "الاتصال بال&خادوم:" + +#~ msgid "&Server response:" +#~ msgstr "ر&دّ الخادوم:" + +#~ msgid "FTP Options" +#~ msgstr "خيارات FTP" + +#~ msgid "Enable passive &mode (PASV)" +#~ msgstr "مكّن الو&ضع السلبي (PASV)" + +#~ msgid "" +#~ "Enables FTP's \"passive\" mode. This is required to allow FTP to work " +#~ "from behind firewalls." +#~ msgstr "" +#~ "مكّن وضع \"passive\" لِـ FTP. هذا ضروري للسماح لِ FTP بالعمل وراء جدار النار." + +#~ msgid "Mark &partially uploaded files" +#~ msgstr "علّم الملفات المرفوعة جزئيًا" + +#~ msgid "" +#~ "

Marks partially uploaded FTP files.

When this option is enabled, " +#~ "partially uploaded files will have a \".part\" extension. This extension " +#~ "will be removed once the transfer is complete.

" +#~ msgstr "" +#~ "

يعلّم ملفات FTP المرفوعة جزئيًا.

عند تمكين هذا الخيار، ستملك " +#~ "الملفات المرفوعة جزئيًا الامتداد ‎\".part\". هذا الامتداد سيُزال ما إن تكتمل " +#~ "عملية النقل.

" + +#~ msgid "" +#~ "

Network Preferences

Here you can define the behavior of KDE " +#~ "programs when using Internet and network connections. If you experience " +#~ "timeouts or use a modem to connect to the Internet, you might want to " +#~ "adjust these settings." +#~ msgstr "" +#~ "

تفضيلات الشبكة

يمكنك من هنا تعريف سلوك برامج كدي عند استخدام " +#~ "الإنترنت واتصالات الشبكة. إذا عانيت من مشاكل انتهاء المهلة أو كنت تستخدم " +#~ "مودمًا، قد ترغب بتغيير هذه القيم." + +#~ msgid "These settings apply to network browsing only." +#~ msgstr "تُطبَّق هذه الإعدادات فقط لتصفّح الشبكة." + +#~ msgid "Default user name:" +#~ msgstr "اسم المستخدم الافتراضي:" + +#~ msgid "Default password:" +#~ msgstr "كلمة المرور الافتراضية:" + +#~ msgctxt "@title:window" +#~ msgid "Add Identification" +#~ msgstr "أضف تعريفًا" + +#~ msgctxt "@title:window" +#~ msgid "Modify Identification" +#~ msgstr "عدّل التعريف" + +#~ msgid "" +#~ "
Found an existing identification for
%1
Do you " +#~ "want to replace it?
" +#~ msgstr "" +#~ "
عُثر على تعريف موجود لِـ
%1
أتريد استبداله؟" + +#~ msgctxt "@title:window" +#~ msgid "Duplicate Identification" +#~ msgstr "تعريف مكرّر" + +#~ msgid "" +#~ "\n" +#~ "Send the browser identification to web sites.

\n" +#~ "NOTE: Many sites rely on this information to display pages " +#~ "properly, hence, it is highly recommended that you do not totally disable " +#~ "this feature but rather customize it.

\n" +#~ "By default, only minimal identification information is sent to remote " +#~ "sites. The identification text that will be sent is shown below.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "أرسل تعريف المتصفّح إلى مواقع الوِب.

\n" +#~ "ملاحظة: تعتمد الكثير من المواقع على هذه المعلومات لعرض الصفحات " +#~ "بشكل صحيح، لذا من المستحسن بشدّة ألّا تعطّل هذه الميزة كليًّا بل تخصّصها.

\n" +#~ "افتراضيًا، فقط معلومات التعريف الدنيا ستُرسَل إلى المواقع البعيدة. نصّ " +#~ "التعريف الذي سيُرسَل ظاهر أدناه.\n" +#~ "" + +#~ msgid "&Send identification" +#~ msgstr "أ&رسل التعريف" + +#~ msgid "" +#~ "The browser identification text sent to the sites you visit. Use the " +#~ "provided options to customize it." +#~ msgstr "" +#~ "نصّ تعريف المتصفّح ليُرسَل إلى المواقع التي تزورها. استخدم الخيارات المُوفَّرة " +#~ "لتخصيصه." + +#~ msgid "Default Identification" +#~ msgstr "التعريف الافتراضي" + +#~ msgid "" +#~ "The browser identification text sent to the sites you visit. You can " +#~ "customize it using the options provided below." +#~ msgstr "" +#~ "نصّ تعريف المتصفّح ليُرسَل إلى المواقع التي تزورها. يمكنك تخصيصه باستخدام " +#~ "الخيارات المُوفَّرة أدناه." + +#~ msgid "" +#~ "Includes your operating system's name in the browser identification text." +#~ msgstr "يضمّن اسم نظام التشغيل في نصّ تعريف المتصفّح." + +#~ msgid "Add operating s&ystem name" +#~ msgstr "أضف اسم ن&ظام تشغيل" + +#~ msgid "" +#~ "Includes your operating system's version number in the browser " +#~ "identification text." +#~ msgstr "يضمّن رقم إصدار نظام التشغيل في نصّ تعريف المتصفّح." + +#~ msgid "Add operating system &version" +#~ msgstr "أضف إ&صدار نظام التشغيل" + +#~ msgid "Includes your machine's CPU type in the browser identification text." +#~ msgstr "يضمّن نوع معالج الآلة في نصّ تعريف المتصفّح." + +#~ msgid "Add &machine (processor) type" +#~ msgstr "أضف نوع ال&جهاز (المعالج)" + +#~ msgid "" +#~ "Includes your language settings in the browser identification text to " +#~ "obtain localized versions of the page." +#~ msgstr "" +#~ "يضمّن إعدادات اللغة في نصّ تعريف المتصفّح للحصول على إصدارات مُعرَّبة من الصفحة." + +#~ msgid "Add lang&uage information" +#~ msgstr "أضف معلومات الل&غة" + +#~ msgid "Site Specific Identification" +#~ msgstr "تعريف محدّد للمواقع" + +#~ msgid "Site Name" +#~ msgstr "اسم الموقع" + +#~ msgid "Identification" +#~ msgstr "التعريف" + +#~ msgid "User Agent" +#~ msgstr "وكيل المستخدم" + +#~ msgid "Add new identification text for a site." +#~ msgstr "أضف نصّ تعريف جديد لموقع ما." + +#~ msgid "Change the selected identifier text." +#~ msgstr "غيّر نصّ التعريف المحدّد." + +#~ msgid "Delete the selected identifier text." +#~ msgstr "احذف نصّ التعريف المحدّد." + +#~ msgid "Delete all identifiers." +#~ msgstr "احذف كلّ التعريفات." + +#~ msgid "" +#~ "\n" +#~ "Enter the site or domain name where a fake browser identification should " +#~ "be used.

\n" +#~ "NOTE: Wildcard syntax such as \\\"*,?\\\" is NOT allowed: instead, " +#~ "use the top level address of a site to make generic matches; for example, " +#~ "if you want all KDE sites to receive a fake browser identification, you " +#~ "would enter kde.org - the fake identity would then be sent " +#~ "to any KDE site that ends with kde.org.

\n" +#~ "
" +#~ msgstr "" +#~ "\n" +#~ "أدخِل اسم الموقع أو المجال الذي سيُستخدَم فيه تعريف زائف.

\n" +#~ "ملاحظة: أحرف البدل مثل \\\"*,?\\\" لا يُسمح باستخدامها. بدلاً من " +#~ "ذلك أدخِل عنوان المستوى الأعلى للموقع لعمل مطابقة عامّة لكلّ المواقع " +#~ "الموجودة تحته. على سبيل المثال، إذا أردت أن تستقبل كلّ مواقع كدي تعريفًا " +#~ "وهميًا، أدخِل kde.org. سيُرسَل التعريف الزائف عندها إلى أيّ موقع " +#~ "كدي ينتهي بِـ kde.org.

\n" +#~ "
" + +#~ msgid "&When browsing the following site:" +#~ msgstr "عند تصفّح ال&موقع التالي:" + +#~ msgid "" +#~ "\n" +#~ "Select the browser identification to use whenever contacting the site you " +#~ "specified above.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "اختر تعريف المتصفّح المُستخدَم متى ما اتّصلت بالموقع الذي حدّدته بالأعلى.\n" +#~ "" + +#~ msgid "&Use the following identification:" +#~ msgstr "استخدم ال&تعريف التالي:" + +#~ msgid "" +#~ "\n" +#~ "The actual browser identification text that will be sent to the remote " +#~ "machine.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "نصّ تعريف المتصفّح الحقيقي الذي سيُرسَل إلى الآلة البعيدة.\n" +#~ "" + +#~ msgid "Real identification:" +#~ msgstr "التعريف الحقيقي:" + +#~ msgid "Treat &all cookies as session cookies" +#~ msgstr "ا&عتبر كلّ الكعكات ككعكات الجلسة" + +#~ msgid "" +#~ "Enter the port number of the HTTP proxy server. Default is 8080. Another " +#~ "common value is 3128." +#~ msgstr "" +#~ "أدخل رقم المنفذ الخاص بخادم الوكيل الخاص بالـHTTP. الرقم الافتراضي هو " +#~ "8080. من الأرقام الأخرى الشائعة عادة 3128." + +#~ msgid "" +#~ "Enter the port number of the FTP proxy server. Default 8080. Another " +#~ "common value is 3128." +#~ msgstr "" +#~ "أدخل رقم المنفذ الخاص بخادم الوكيل الخاص بالـFTP. الرقم الافتراضي هو " +#~ "8080. من الأرقام الأخرى الشائعة عادة 3128." + +#, fuzzy +#~| msgid "Variable Proxy Configuration" +#~ msgctxt "@title:window" +#~ msgid "Variable Proxy Configuration" +#~ msgstr "تشكيل الوكيل المتغير" + +#~ msgid "You must specify at least one valid proxy environment variable." +#~ msgstr "يجب عليك تحديد وكيل بيئي متغير صالح على الأقل." + +#~ msgid "" +#~ "Make sure you entered the actual environment variable name rather " +#~ "than its value. For example, if the environment variable is
HTTP_PROXY=http://localhost:3128
you need to enter " +#~ "HTTP_PROXY here instead of the actual value http://localhost:3128." +#~ "
" +#~ msgstr "" +#~ "تأكد من أنك أدخلت اسم المتغير البيئة بدلا عن قيمته. على سبيل المثال " +#~ "إذا كان متغير البيئة هو
HTTP_PROXY=http://localhost:3128
فإنك بحاجة إلى إدخالHTTP_PROXY بدلا عن القيمة الحقيقية " +#~ "http://localhost:3128.
" + +#, fuzzy +#~| msgid "Invalid Proxy Setup" +#~ msgctxt "@title:window" +#~ msgid "Invalid Proxy Setup" +#~ msgstr "إعداد غير صالح للوكيل" + +#~ msgid "Successfully verified." +#~ msgstr "تم التحقق بنجاح" + +#, fuzzy +#~| msgid "Proxy Setup" +#~ msgctxt "@title:window" +#~ msgid "Proxy Setup" +#~ msgstr "إعداد الوكيل" + +#~ msgid "" +#~ "Did not detect any environment variables commonly used to set system wide " +#~ "proxy information." +#~ msgstr "" +#~ "لم يتم العثور على أي من أسماء المتغيرات البيئية شائعة الاستخدام لإعداد " +#~ "معلومات الوكيل الخاصة بالنظام ككل." + +#~ msgid "" +#~ "To learn about the variable names the automatic detection process " +#~ "searches for, press OK, click on the quick help button on the window " +#~ "title bar of the previous dialog and then click on the \"Auto Detect\" button." +#~ msgstr "" +#~ "لتتعرف على أسماء المتغيرات التي تبحث عنها عملية الاكتشاف التلقائي، " +#~ "اضغط على زر موافق، ثم إنقر على زر المساعدة السريعة الموجود في شريط عنوان " +#~ "النافذة من مربع الحوار \"تشكيل الوكيل المتغير\" ثم انقر على زر " +#~ "\"اكتشف تلقائياً\"." + +#, fuzzy +#~| msgid "Automatic Proxy Variable Detection" +#~ msgctxt "@title:window" +#~ msgid "Automatic Proxy Variable Detection" +#~ msgstr "تحديد متغير الوكيل آلياً." + +#, fuzzy +#~| msgid "Manual Proxy Configuration" +#~ msgctxt "@title:window" +#~ msgid "Manual Proxy Configuration" +#~ msgstr "تشكيل الوكيل يدوياً" + +#, fuzzy +#~| msgid "Invalid Proxy Setting" +#~ msgctxt "@title:window" +#~ msgid "Invalid Proxy Setting" +#~ msgstr "إعداد غير صالح للوكيل" + +#~ msgid "" +#~ "One or more of the specified proxy settings are invalid. The incorrect " +#~ "entries are highlighted." +#~ msgstr "" +#~ "واحد أو أكثر من إعدادات الوكيل المحددة غير صالحة. الخانات الغير صحيحة هي " +#~ "البارزة." + +#~ msgid "You entered a duplicate address. Please try again." +#~ msgstr "قمت بإدخال عنوان مكرر. من فضلك حاول مرة ثانية." + +#~ msgid "
%1
is already in the list.
" +#~ msgstr "
%1
موجود في القائمة.
" + +#, fuzzy +#~| msgid "Duplicate Entry" +#~ msgctxt "@title:window" +#~ msgid "Duplicate Entry" +#~ msgstr "مدخلة مكررة" + +#, fuzzy +#~| msgid "New Exception" +#~ msgctxt "@title:window" +#~ msgid "New Exception" +#~ msgstr "استثناء جديد" + +#, fuzzy +#~| msgid "Change Exception" +#~ msgctxt "@title:window" +#~ msgid "Change Exception" +#~ msgstr "غيّر استثناء" + +#, fuzzy +#~| msgid "Invalid Entry" +#~ msgctxt "@title:window" +#~ msgid "Invalid Entry" +#~ msgstr "مدخلة غير صالحة" + +#~ msgid "The address you have entered is not valid." +#~ msgstr "العنوان الذي قمت بإدخاله غير صالح" + +#~ msgid "" +#~ "Make sure none of the addresses or URLs you specified contain invalid " +#~ "or wildcard characters such as spaces, asterisks (*), or question " +#~ "marks(?).

Examples of VALID entries:
http://" +#~ "mycompany.com, 192.168.10.1, mycompany.com, localhost, http://localhost

Examples of INVALID entries:
http://my " +#~ "company.com, http:/mycompany,com file:/localhost
" +#~ msgstr "" +#~ "تأكد من أن العناوين التي تحددها لا تحتوي على محتويات غير صالحة أو " +#~ "محارف علامات مثل الفراغ ، و النجمة (*), أو علامة الاستفهام(؟).

أمثلة على مدخلات صحيحة:
http://mycompany.com, " +#~ "192.168.10.1, mycompany.com, localhost, http://localhost

أمثلة على مدخلات غير صحيحة:
http://my company.com, " +#~ "http:/mycompany,com file:/localhost
" + +#~ msgid "Enter the URL or address that should use the above proxy settings:" +#~ msgstr "أدخل العنوان الذي يجب أن يستخدم إعدادات الوكيل أعلاه:" + +#~ msgid "" +#~ "Enter the address or URL that should be excluded from using the above " +#~ "proxy settings:" +#~ msgstr "أدخل العنوان الذي يجب استثنائه من استخدام إعدادات الوكيل أعلاه:" + +#~ msgid "" +#~ "Enter a valid address or URL.

NOTE: Wildcard " +#~ "matching such as *.kde.org is not supported. If you want to " +#~ "match any host in the .kde.org domain, e.g. printing." +#~ "kde.org, then simply enter .kde.org.
" +#~ msgstr "" +#~ "أدخل عنوان صحيحا. .

ملاحظة: علاماتالمطابقة " +#~ "مثل*.kde.org غير مدعومة. إذا رغبت في مطابقة أي مستضيف في " +#~ "مجال .kde.org على سبيل المثال printing.kde.orgفعليك بكل بساطة إدخال .kde.org.
" + +#~ msgid "" +#~ "The address of the automatic proxy configuration script is invalid. " +#~ "Please correct this problem before proceeding. Otherwise, your changes " +#~ "will be ignored." +#~ msgstr "" +#~ "عنوان مخطوط تشكيلة الوكيل الآلية غير صحيحة. الرجاء تصحيح هذه المشكلة قبل " +#~ "المتابعة. وإلا فإن تغيراتك سوف ستُتجاهل." + +#~ msgid "" +#~ "The proxy settings you specified are invalid.

Please click " +#~ "on the Setup... button and correct the problem before proceeding; " +#~ "otherwise your changes will be ignored.
" +#~ msgstr "" +#~ "إعدادات الوكيل التي حدتتها غير صالحة.

رجاءا انقرعلى زر " +#~ "إعداد... وصحح المشكلة قبل المواصلة ؛ و إلا فإن تغيراتك ستُتجاهل. " + +#~ msgid "H&TTP:" +#~ msgstr "H&TTP" + +#~ msgid "HTTP&S:" +#~ msgstr "HTTP&S" + +#~ msgid "&FTP:" +#~ msgstr "&FTP" + +#~ msgid "NO &PROXY:" +#~ msgstr "بدون و&كيل" + +#~ msgid "" +#~ "Verify whether or not the environment variable names you supplied are " +#~ "valid. If an environment variable is not found, the associated labels " +#~ "will be highlighted to indicate that they are invalid." +#~ msgstr "" +#~ "التحقق من فيما إذا كانت أسماء المتغيرات البيئية التي أدخلتها صحيحة أم " +#~ "لا. إذا لم يتم العثور على متغير بيئي ما، فسيتم إبراز التسميات " +#~ "المقترنة به لبيان عدم صحتها." + +#~ msgid "&Verify" +#~ msgstr "&تحقق" + +#~ msgid "Connect to the &Internet directly" +#~ msgstr "اتصل بالإنترنت &مباشرة" + +#~ msgid "Use preset proxy environment &variables" +#~ msgstr "استخدم المت&غيرات البيئية المعدة مسبقاً للوكيل" + +#~ msgid "Show the proxy environment variable configuration dialog." +#~ msgstr "أظهر حوار تشكيل متغيرات بيئة الوكيل." + +#~ msgid "Setup..." +#~ msgstr "إعداد..." + +#~ msgid "&Manually specify the proxy settings" +#~ msgstr "حدّد إعدادات الوكيل يدو&ياً" + +#~ msgid "Show the manual proxy configuration dialog." +#~ msgstr "أظهر حوار الضبط اليدوي للوكيل ." + +#~ msgid "Authori&zation" +#~ msgstr "الت&رخيص" + +#~ msgid "Prompt for login information whenever it is required." +#~ msgstr "أطلب معلومات تسجيل الدخول كلما دعت الحاجة." + +#~ msgid "Prompt as &needed" +#~ msgstr "السؤال عند ال&حاجة" + +#~ msgid "Use this login information." +#~ msgstr "استخدم معلومات الود&لوج التالية." + +#~ msgid "" +#~ "Use information specified here to login into proxy servers as needed." +#~ msgstr "استخدم المعلومات أدناه للولوج إلى خوادم الوكيل عند الحاجة." + +#~ msgid "Username:" +#~ msgstr "اسم المستخدم:" + +#~ msgid "Login name." +#~ msgstr "اسم الدخول." + +#~ msgid "Login password." +#~ msgstr "كلمة سر الدخول." + +#~ msgid "Password:" +#~ msgstr "كلمة السر:" + +#~ msgid "O&ptions" +#~ msgstr "&خيارات " + +#~ msgid "" +#~ "\n" +#~ "Use persistent proxy connection.

\n" +#~ "Although a persistent proxy connection is faster, note that it only works " +#~ "correctly with proxies that are fully HTTP 1.1 compliant. Do not " +#~ "use this option in combination with non-HTTP 1.1 compliant proxy servers " +#~ "such as JunkBuster and WWWOfle.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "استخدم اتصال دائم مع الوكيل.

\n" +#~ "بالرغم من أن استخدام اتصال دائم مع الوكيل أسرع، غير أنه يعمل بشكل صحيح " +#~ "فقط مع خوادم الوكيل المتوافقة بشكل كامل مع HTTP 1.1. لا تقم " +#~ "باستخدام هذا الخيار مع خوادم الوكيل غير المتوافقة مع HTTP 1.1 مثل " +#~ "JunkBuster أو WWWOfle.\n" +#~ "" + +#~ msgid "Use persistent connections to proxy" +#~ msgstr "استخدم اتصالات دائمة مع الوكيل." + +#~ msgid "Ser&vers" +#~ msgstr "الخ&وادم" + +#~ msgid "" +#~ "\n" +#~ "Reverse the use of the exception list. Checking this box will result in " +#~ "the proxy servers being used only when the requested URL matches one of " +#~ "the addresses listed here.

This feature is useful if all you want or " +#~ "need is to use a proxy server for a few specific sites.

If you have " +#~ "more complex requirements you might want to use a configuration script.\n" +#~ "" +#~ msgstr "" +#~ "\n" +#~ "عكس استخدام قائمة الاستثناءات. وضع علامة على المربع سيجعل استخدام خوادم " +#~ "الوكيل قاصراً فقط على عناوين الـ URL التي تتطابق مع تلك الموجودة في هذه " +#~ "القائمة.

هذه الميزة مفيدة إذا كان كل ما تريده أو تحتاجه هو استخدام " +#~ "خادم الوكيل مع مواقع محدّدة قليلة العدد.

ربما ترغب باستخدام مخطوط تشكيل " +#~ "إذا كان لديك متطلبات معقدة.\n" +#~ "" + +#~ msgid "Remove all proxy exception addresses from the list." +#~ msgstr "أزل جميع عناوين إستثناء الوكيل من القائمة." + +#~ msgid "D&elete All" +#~ msgstr "ا&حذف الكل" + +#~ msgid "Remove the selected proxy exception address from the list." +#~ msgstr "أزل عنوان استثناء وكيل مُحدد من القائمة." + +#~ msgid "De&lete" +#~ msgstr "ا&حذف" + +#~ msgid "Add new proxy exception address to the list." +#~ msgstr "أضف عنوان استثناء وكيل إلى القائمة." + +#~ msgid "Change the selected proxy exception address." +#~ msgstr "غيّر عنوان إستثناء الوكيل المُحدد." + +#~ msgid "C&hange..." +#~ msgstr "غ&يّر..." + +#~ msgid "&Domain name:" +#~ msgstr "اسم الم&جال:" + +#~ msgid "Includes your platform type in the browser identification text" +#~ msgstr "إضافة نوع المنصة الخاصة بك لنص تعرّيف المتصفح" + +#~ msgid "Add &platform name" +#~ msgstr "أضف اسم م&نصة" + +#~ msgid "Domain [Group]" +#~ msgstr "المجال (المجموعة)" + +#~ msgid "Host [Set By]" +#~ msgstr "المضيف (إعداد بواسطة)" + +#~ msgid "&Windows Shares" +#~ msgstr "موارد ال&ويندوز المشاركة" + +#~ msgid "&LISa Daemon" +#~ msgstr "ر&قيب LISa" + +#~ msgid "lan:/ Iosla&ve" +#~ msgstr "lan:/ Iosla&ve" diff --git a/po/ar/kcmkonq.po b/po/ar/kcmkonq.po new file mode 100644 index 0000000..3d08fff --- /dev/null +++ b/po/ar/kcmkonq.po @@ -0,0 +1,335 @@ +# translation of kcmkonq.po to Arabic +# translation of kcmkonq.po to +# Konqueror Contol Module +# Copyright (C) 2001,2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +# Isam Bayazidi , 2001,2002. +# Sayed Jaffer Al-Mosawi , 2002. +# Ammar Tabbaa , 2004. +# محمد سعد Mohamed SAAD , 2006. +# AbdulAziz AlSharif , 2007. +# Youssef Chahibi , 2007. +# zayed , 2008. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kcmkonq\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-05-20 02:40+0200\n" +"PO-Revision-Date: 2014-07-17 22:56+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#: behaviour.cpp:48 +#, kde-format +msgid "" +"

Konqueror Behavior

You can configure how Konqueror behaves as a " +"file manager here." +msgstr "

سلوك كنكرر

تستطيع هنا ضبط كيفية تصرّف كنكرر كمدير ملفات." + +#: behaviour.cpp:52 +#, kde-format +msgid "Misc Options" +msgstr "خيارات متنوّعة" + +#: behaviour.cpp:61 +#, kde-format +msgid "Open folders in separate &windows" +msgstr "ا&فتح المجلدات في نوافذ منفصلة" + +#: behaviour.cpp:62 +#, kde-format +msgid "" +"If this option is checked, Konqueror will open a new window when you open a " +"folder, rather than showing that folder's contents in the current window." +msgstr "" +"إذا عُلِّم هذا الخيار، سيفتح كنكر نافذة جديدة عندما تفتح مجلدًا ما، بدلاً من عرض " +"محتويات المجلد في نفس النافذة الحالية." + +#: behaviour.cpp:85 +#, kde-format +msgid "Show 'Delete' me&nu entries which bypass the trashcan" +msgstr "أظهر مُدخلات القائ&مة 'احذف' التي تتجاوز المهملات" + +#: behaviour.cpp:89 +#, kde-format +msgid "" +"Check this if you want 'Delete' menu commands to be displayed on the desktop " +"and in the file manager's menus and context menus. You can always delete " +"files by holding the Shift key while calling 'Move to Trash'." +msgstr "" +"علّم هذا إن أردت أن يظهر أمر القائمة 'احذف' في قوائم وقوائم سياق سطح المكتب " +"ومدير الملفات. يمكنك دائمًا حذف الملفات بإبقاء الضغط على مفتاح Shift واستدعاء " +"'انقل إلى المهملات'." + +#: kcustommenueditor.cpp:95 +#, kde-format +msgctxt "@title:window" +msgid "Menu Editor" +msgstr "محرّر القوائم" + +#: kcustommenueditor.cpp:104 +#, kde-format +msgid "Menu" +msgstr "القوائم" + +#: kcustommenueditor.cpp:108 +#, kde-format +msgid "New..." +msgstr "جديد..." + +#: kcustommenueditor.cpp:109 +#, kde-format +msgid "Remove" +msgstr "أزل" + +#: kcustommenueditor.cpp:110 +#, kde-format +msgid "Move Up" +msgstr "انقل لأعلى" + +#: kcustommenueditor.cpp:111 +#, kde-format +msgid "Move Down" +msgstr "انقل لأسفل" + +#~ msgid "" +#~ "

Paths

\n" +#~ "This module allows you to choose where in the filesystem the files on " +#~ "your desktop should be stored.\n" +#~ "Use the \"Whats This?\" (Shift+F1) to get help on specific options." +#~ msgstr "" +#~ "

المسارات

\n" +#~ "هذه الوحدة تسمح لك باختيار المكان الذي سيتم فيه حفظ ملفات سطح المكتب على " +#~ "نظامك. \n" +#~ "استخدم خيار \"ما هذا؟\" (Shift+F1) للحصول على المساعدة حول الخيارات " +#~ "المحددة." + +#~ msgid "Desktop path:" +#~ msgstr "مسار سطح المكتب:" + +#~ msgid "" +#~ "This folder contains all the files which you see on your desktop. You can " +#~ "change the location of this folder if you want to, and the contents will " +#~ "move automatically to the new location as well." +#~ msgstr "" +#~ "يحتوي هذا المجلد كل الملفات التي تراها على سطح مكتبك. تستطيع تغيير موقع " +#~ "هذا المجلد إن أردت، تسنقل عندها كل المحتويات تلقائياً للموقع الجديد." + +#~ msgid "Autostart path:" +#~ msgstr "مسار البدء التلقائي:" + +#~ msgid "" +#~ "This folder contains applications or links to applications (shortcuts) " +#~ "that you want to have started automatically whenever KDE starts. You can " +#~ "change the location of this folder if you want to, and the contents will " +#~ "move automatically to the new location as well." +#~ msgstr "" +#~ "يحتوي هذا المجلد على تطبيقات أو وصلات للتطبيقات التي تود تشغيلها تلقائياً " +#~ "في كل مرة تشغل فيها كدي. تستطيع تغيير موقع هذا المجلد إذا أردت، ستنقل " +#~ "عندها كل المحتويات تلقائياً للموقع الجديد." + +#~ msgid "Documents path:" +#~ msgstr "مسار المستندات:" + +#~ msgid "" +#~ "This folder will be used by default to load or save documents from or to." +#~ msgstr "سيستخدم هذا المجلد افتراضيًا لتحميل المستندات منه أو حفظها فيه." + +#~ msgid "Downloads path:" +#~ msgstr "مسار التنزيلات:" + +#~ msgid "This folder will be used by default to save your downloaded items." +#~ msgstr "سيستخدم هذا المجلد افتراضياً لحفظ العناصر التي تنزلها من الإنترنت." + +#~ msgid "Movies path:" +#~ msgstr "مسار الأفلام:" + +#~ msgid "" +#~ "This folder will be used by default to load or save movies from or to." +#~ msgstr "سيستخدم هذا المجلد افتراضياً لتحميل الأفلام منه أو حفظها فيه." + +#~ msgid "Pictures path:" +#~ msgstr "مسار الصور:" + +#~ msgid "" +#~ "This folder will be used by default to load or save pictures from or to." +#~ msgstr "سيستخدم هذا المجلد افتراضياً لتحميل الصور منه أو حفظها فيه." + +#~ msgid "Music path:" +#~ msgstr "مسار الموسيقى:" + +#~ msgid "" +#~ "This folder will be used by default to load or save music from or to." +#~ msgstr "سيستخدم هذا المجلد افتراضياً لتحميل الموسيقى منه أو حفظها فيه." + +#~ msgid "Autostart" +#~ msgstr "البدء التلقائي" + +#~ msgid "Desktop" +#~ msgstr "سطح المكتب" + +#~ msgid "Documents" +#~ msgstr "المستندات" + +#~ msgid "Downloads" +#~ msgstr "التنزيلات" + +#~ msgid "Movies" +#~ msgstr "الأفلام" + +#~ msgid "Pictures" +#~ msgstr "الصور" + +#~ msgid "Music" +#~ msgstr "الموسيقى" + +#~ msgid "" +#~ "The path for '%1' has been changed.\n" +#~ "Do you want the files to be moved from '%2' to '%3'?" +#~ msgstr "" +#~ "غير المسار إلى '%1'.\n" +#~ "هل تريد نقل الملفات من '%2' إلى '%3'؟" + +#~ msgctxt "Move files from old to new place" +#~ msgid "Move" +#~ msgstr "انقل" + +#~ msgctxt "Use the new directory but do not move files" +#~ msgid "Do not Move" +#~ msgstr "لا تنقل" + +#, fuzzy +#~| msgid "" +#~| "The path for '%1' has been changed.\n" +#~| "Do you want the files to be moved from '%2' to '%3'?" +#~ msgid "" +#~ "The path for '%1' has been changed.\n" +#~ "Do you want to move the directory '%2' to '%3'?" +#~ msgstr "" +#~ "تم تغيير المسار لِــ '%1'.\n" +#~ "هل تريد نقل الملفات من '%2' إلى '%3' ؟" + +#, fuzzy +#~| msgctxt "Move desktop files from old to new place" +#~| msgid "Move" +#~ msgctxt "Move the directory" +#~ msgid "Move" +#~ msgstr "انقل" + +#~ msgid "Confirmation Required" +#~ msgstr "التأكيد مطلوب" + +#~ msgctxt "@title:group what to do when a file is deleted" +#~ msgid "Ask Confirmation For" +#~ msgstr "اطلب التأكيد لـِ" + +#~ msgid "" +#~ "This option tells Konqueror whether to ask for a confirmation when you " +#~ "\"delete\" a file.
  • Move To Trash: moves the file to your " +#~ "trash folder, from where it can be recovered very easily.
  • " +#~ "
  • Delete: simply deletes the file.
" +#~ msgstr "" +#~ "هذا الخيار يخبر الكونكيور إذا ما كان من اللازم سؤال عن التأكيد عند\"حذف\" " +#~ "ملف.
  • انقل إلى سلة المهملات: تنقل الملف إلى مجلد سلة " +#~ "المهملات ؛ حيث يمكن من هناك استعادته بسهولة.
  • احذف: " +#~ "ببساطة تحذف الملف.
" + +#~ msgctxt "@option:check Ask for confirmation when moving to trash" +#~ msgid "&Move to trash" +#~ msgstr "ان&قل إلى المهملات" + +#~ msgctxt "@option:check Ask for confirmation when deleting" +#~ msgid "D&elete" +#~ msgstr "اح&ذف" + +#~ msgid "&Behavior" +#~ msgstr "&السلوك" + +#~ msgid "&Previews && Meta-Data" +#~ msgstr "ال&معاينات وبيانات التعريف" + +#~ msgid "" +#~ "

Allow previews, \"Folder Icons Reflect Contents\", and retrieval of " +#~ "meta-data on protocols:

" +#~ msgstr "" +#~ "

اسمح بالمعاينات و \"أيقونات المجلدات تعكس المحتوى\" واستعادة بيانات " +#~ "تعريف البروتوكولات:

" + +#~ msgid "" +#~ "

Preview Options

Here you can modify the behavior of Konqueror " +#~ "when it shows the files in a folder.

The list of protocols:

check " +#~ "the protocols over which previews should be shown; uncheck those over " +#~ "which they should not. For instance, you might want to show previews over " +#~ "SMB if the local network is fast enough, but you might disable it for FTP " +#~ "if you often visit very slow FTP sites with large images.

Maximum File " +#~ "Size:

select the maximum file size for which previews should be " +#~ "generated. For instance, if set to 1 MB (the default), no preview will be " +#~ "generated for files bigger than 1 MB, for speed reasons." +#~ msgstr "" +#~ "

خيارات المعاينة

يمكنك هنا تعديد سلوك الكونكيور عندماالملفات في " +#~ "مجلد.

قائمة البروتوكلات:

اختر البروتوكلات التي تريد استخدام " +#~ "المعاينة معها والتي لا تريد استخدامها مع المعاينة. على سبيل المثال قد " +#~ "ترغب في عرض معاينة للملفات باستخدام SMB إذا كانت الشكبة سريعة بما فيها " +#~ "الكفاية ، ولكن قد تريد تعطيل المعاينة إذا كانت FTP إذا كنت غالبا تزور " +#~ "مواقع FTP بطيئة تحتوي على صور كبيرة الحجم.

أقصى حجم للملف:

انتق " +#~ "أقصى حجم للملف الذي تريد إنشاء معاينة له ، على سبيل المثال إذا وضعت 1 " +#~ "ميجابايت (المبدئي) فإنه لن تولد أي معاينة للملفات التي هي أكبر من واحد " +#~ "ميجابايت بسبب السرعة." + +#, fuzzy +#~| msgctxt "" +#~| "@title:column Header of a colum where the user has to select in which " +#~| "protocols he wants to see file previews" +#~| msgid "Select Protocols" +#~ msgctxt "" +#~ "@title:column Header of a column where the user has to select in which " +#~ "protocols he wants to see file previews" +#~ msgid "Select Protocols" +#~ msgstr "انتق البروتوكولات" + +#~ msgid "Local Protocols" +#~ msgstr "البروتوكولات المحلية" + +#~ msgid "Internet Protocols" +#~ msgstr "بروتوكولات الإنترنت" + +#~ msgid "" +#~ "This option makes it possible to choose when the file previews, smart " +#~ "folder icons, and meta-data in the File Manager should be activated.\n" +#~ "In the list of protocols that appear, select which ones are fast enough " +#~ "for you to allow previews to be generated." +#~ msgstr "" +#~ "يسمح هذا الخيار باختيار متى يجب أن يتم تفعيل معاينة الملف وأيقونات " +#~ "المجلدات الذكية وبيانات التعريف في مدير الملفات.\n" +#~ "في قائمة البروتوكولات التي تظهر، انتقي أيها سريعاً بما فيه الكفاية للسماح " +#~ "بتوليد المعاينة." + +#~ msgid "&Maximum file size:" +#~ msgstr "ال&حجم الأقصى للملف:" + +#~ msgid " MB" +#~ msgstr " م. بايت" + +#~ msgid "&Increase size of previews relative to icons" +#~ msgstr "&زيادة حجم المعاينات نسبياً إلى الأيقونات" + +#~ msgid "&Use thumbnails embedded in files" +#~ msgstr "&استخدم المصغرات المضمّنة في الملفات" + +#~ msgid "" +#~ "Select this to use thumbnails that are found inside some file types (e.g. " +#~ "JPEG). This will increase speed and reduce disk usage. Deselect it if you " +#~ "have files that have been processed by programs which create inaccurate " +#~ "thumbnails, such as ImageMagick." +#~ msgstr "" +#~ "انتقي هذا الخيار لعرض المصغرات لبعض أنواع الملفات (مثل JPEG). هذا سيزيد " +#~ "من السرعة و يقلل استعمال القرص الصلب. عدم انتقاء هذا الخيار إذا كانت " +#~ "لديك ملفات تم معالجتها بواسطة برامج تقوم بإنشاء مصغرات غير دقيقة, مثل " +#~ "ImageMagick." diff --git a/po/ar/kcmkonqhtml.po b/po/ar/kcmkonqhtml.po new file mode 100644 index 0000000..192a0b2 --- /dev/null +++ b/po/ar/kcmkonqhtml.po @@ -0,0 +1,2391 @@ +# translation of kcmkonqhtml.po to Arabic +# translation of kcmkonqhtml.po to +# Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. +# Isam Bayazidi , 2002. +# Munzir Taha , 2004. +# محمد سعد Mohamed SAAD , 2006. +# AbdulAziz AlSharif , 2007. +# Youssef Chahibi , 2007. +# zayed , 2008. +# Safa Alfulaij , 2014. +msgid "" +msgstr "" +"Project-Id-Version: kcmkonqhtml\n" +"Report-Msgid-Bugs-To: https://bugs.kde.org\n" +"POT-Creation-Date: 2019-11-04 02:30+0100\n" +"PO-Revision-Date: 2014-09-10 20:31+0300\n" +"Last-Translator: Safa Alfulaij \n" +"Language-Team: Arabic \n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" +"X-Generator: Lokalize 1.5\n" + +#, kde-format +msgctxt "NAME OF TRANSLATORS" +msgid "Your names" +msgstr "محمد سعد,زايد السعيدي,أسامة خالد" + +#, kde-format +msgctxt "EMAIL OF TRANSLATORS" +msgid "Your emails" +msgstr "metehyi@free.fr,zayed.alsaidi@gmail.com,osamak.wfm@gmail.com" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pShowMMBInTabs) +#: advancedTabOptions.ui:21 +#, kde-format +msgid "" +"This will open a new tab instead of a new window in various situations, such " +"as choosing a link or a folder with the middle mouse button." +msgstr "" +"سيفتح هذا لسانًا جديدًا بدلًا من فتح نافذة جديدة في عدّة حالات، مثل اختيار وصلة " +"أو مجلد بزرّ الفأرة الأوسط." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pShowMMBInTabs) +#: advancedTabOptions.ui:24 +#, kde-format +msgid "Open &links in new tab instead of in new window" +msgstr "افتح ال&وصلات في لسان جديد بدلًا من نافذة جديدة" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pPopupsWithinTabs) +#: advancedTabOptions.ui:31 +#, kde-format +msgid "" +"Whether or not JavaScript popups if allowed shall open in a new tab or in a " +"new window." +msgstr "" +"فيما إذا كانت منبثقات جافاسكرِبت (إن كانت مسموحة) ستفتح في لسان جديد أو نافذة " +"جديدة." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pPopupsWithinTabs) +#: advancedTabOptions.ui:34 +#, kde-format +msgid "Open pop&ups in new tab instead of in new window" +msgstr "افتح الم&نبثقات في لسان جديد بدلًا من نافذة جديدة" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pKonquerorTabforExternalURL) +#: advancedTabOptions.ui:41 +#, fuzzy, kde-format +msgid "" +"When you click a URL in another KDE program or call kfmclient to open a URL, " +"the current desktop will be searched for a non-minimized Konqueror and, if " +"found, the URL opened as a new tab within it. Otherwise a new Konqueror " +"window will be opened with the required URL." +msgstr "" +"عند النقر على عنوان في برنامج كدي آخر أو استدعاء kfmclient لفتح عنوان، فإنّ " +"سطح المكتب الحالي سيُبحَث فيه عن كنكرر غير مصغّر وإذا وُجِدَ فإن العنوان سيُفْتَح " +"كلسان جديد داخله. فيما عدا ذلك ستُفتَح نافذة كنكرر جديدة بالعنوان المطلوب." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pKonquerorTabforExternalURL) +#: advancedTabOptions.ui:44 +#, kde-format +msgid "Open as tab in existing Konqueror when URL is called externally" +msgstr "افتح كَلِسان في كنكر الموجود عند استدعاء العنوان خارجيًّا" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pNewTabsInBackground) +#: advancedTabOptions.ui:51 +#, kde-format +msgid "" +"This will open a new tab in the background, instead of in the foreground." +msgstr "سيفتح هذا لسانًا جديدًا في الخلفيّة بدلًا من الأماميّة." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pNewTabsInBackground) +#: advancedTabOptions.ui:54 +#, kde-format +msgid "O&pen new tabs in the background" +msgstr "ا&فتح الألسنة الجديدة في الخلفيّة" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pOpenAfterCurrentPage) +#: advancedTabOptions.ui:61 +#, kde-format +msgid "" +"This will open a new tab opened from a page after the current tab, instead " +"of after the last tab." +msgstr "" +"سيفتح هذا اللسان الجديد المفتوح من صفحة أخرى بعد اللسان الحاليّ، بدلًا من بعد " +"اللسان الأخير." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pOpenAfterCurrentPage) +#: advancedTabOptions.ui:64 +#, kde-format +msgid "Open &new tab after current tab" +msgstr "افتح الل&سان الجديد بعد اللسان الحالي" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pDynamicTabbarHide) +#: advancedTabOptions.ui:71 +#, kde-format +msgid "" +"This will display the tab bar only if there are two or more tabs. Otherwise " +"it will always be displayed." +msgstr "" +"سيعرض هذا شريط الألسنة فقط إن كان هناك لسانان أو أكثر. فيما عدا ذلك سيكون " +"معروضًا دائمًا." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pDynamicTabbarHide) +#: advancedTabOptions.ui:74 +#, kde-format +msgid "Hide the tab bar when only one tab is open" +msgstr "أخفِ شريط اللسان إن كان هناك فقط لسان واحد مفتوح" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pPermanentCloseButton) +#: advancedTabOptions.ui:81 +#, kde-format +msgid "This will display close buttons inside each tab." +msgstr "سيعرض هذا أزرار الإغلاق في كلّ لسان." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pPermanentCloseButton) +#: advancedTabOptions.ui:84 +#, kde-format +msgid "&Show close button on tabs" +msgstr "أ&ظهر زر الإغلاق في الألسنة" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pMiddleClickClose) +#: advancedTabOptions.ui:91 +#, kde-format +msgid "" +"When you click on a tab using the middle mouse button or mouse wheel, it " +"will close that tab." +msgstr "" +"عندما تنقر لسانًا باستخدام زرّ الفأرة الأوسط أو عجلة الفأرة، سيُغلَق ذاك اللسان." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pMiddleClickClose) +#: advancedTabOptions.ui:94 +#, kde-format +msgid "Middle-click on a tab to close it" +msgstr "النقر الأوسط على لسان يُغلقه" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pTabConfirm) +#: advancedTabOptions.ui:101 +#, kde-format +msgid "" +"This will ask you whether you are sure you want to close a window when it " +"has multiple tabs opened in it." +msgstr "" +"سيسألك هذا فيما إذا كنت متأكّد من إغلاق نافذة عند امتلاكها عدّة ألسنة مفتوحة " +"فيها." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pTabConfirm) +#: advancedTabOptions.ui:104 +#, kde-format +msgid "Confirm &when closing windows with multiple tabs" +msgstr "أكّد &عند إغلاق النوافذ بعدّة ألسنة" + +#. i18n: ectx: property (whatsThis), widget (QCheckBox, m_pTabCloseActivatePrevious) +#: advancedTabOptions.ui:111 +#, kde-format +msgid "" +"When checking this the previous used or opened tab will be activated when " +"you close the current active tab instead of the one right to the current tab." +msgstr "" +"عند تعليم هذا، اللسان المُستخدَم السابق أو المفتوح سيُنشَّط عندما تغلق اللسان " +"النشط حاليًا بدلًا من الذي على يمين اللسان الحالي." + +#. i18n: ectx: property (text), widget (QCheckBox, m_pTabCloseActivatePrevious) +#: advancedTabOptions.ui:114 +#, kde-format +msgid "Activate previously used tab when closing the current tab" +msgstr "نشّط اللسان المُستخدَم سابقًا عند إغلاق اللسان الحالي" + +#: appearance.cpp:44 +#, kde-format +msgctxt "@title:tab" +msgid "General" +msgstr "عامّ" + +#: appearance.cpp:45 +#, kde-format +msgctxt "@title:tab" +msgid "Fonts" +msgstr "الخطوط" + +#: appearance.cpp:46 +#, kde-format +msgctxt "@title:tab" +msgid "Stylesheets" +msgstr "أوراق الأنماط" + +#. i18n: ectx: property (title), widget (QGroupBox, GroupBox3_2) +#: appearance.cpp:54 css/csscustom.ui:296 +#, kde-format +msgid "Images" +msgstr "الصور" + +#: appearance.cpp:58 +#, kde-format +msgid "A&utomatically load images" +msgstr "&حمّل الصور آليًا" + +#: appearance.cpp:59 +#, kde-format +msgid "" +"If this box is checked, Konqueror will automatically load any images " +"that are embedded in a web page. Otherwise, it will display placeholders for " +"the images, and you can then manually load the images by clicking on the " +"image button.
Unless you have a very slow network connection, you will " +"probably want to check this box to enhance your browsing experience." +msgstr "" +"إن علّمت هذا المربّع، سيحمّل كنكر أيّة صور مُضمَّنة في صفحة الوِب آليًا. وإلّا " +"سيعرض ماسكات مكان للصور؛ ليمكنك تحميلها يدويًا بنقر زرّ الصورة.
إلّا إذا " +"كان لديك اتّصال شبكة بطيء للغاية، فقد تحتاج غالبًا إلى تعليم هذا المربّع لتحسين " +"تجربة التصفّح." + +#: appearance.cpp:69 +#, kde-format +msgid "Dra&w frame around not completely loaded images" +msgstr "ا&رسم إطارًا حول الصور غير مكتملة التحميل" + +#: appearance.cpp:70 +#, fuzzy, kde-format +msgid "" +"If this box is checked, Konqueror will draw a frame as a placeholder " +"around images embedded in a web page that are not yet fully loaded.
You " +"will probably want to check this box to enhance your browsing experience, " +"especially if have a slow network connection." +msgstr "" +"إذا اختير هذا الصندوق فإن كنكرر سوف يرسم إطارًا حول الصور المضمنة في " +"صفحات الوب التي لم يكتمل تحميلها.
من المرجح أنك تريد أن تعلم على هذا " +"المربع لتحسّن من تجربة تصفحك وخصوصا إذا كنت تملك اتصالًا ضعيفًا بالشبكة." + +#: appearance.cpp:80 +#, kde-format +msgctxt "animations" +msgid "Enabled" +msgstr "مُمكَّنة" + +#: appearance.cpp:81 +#, kde-format +msgctxt "animations" +msgid "Disabled" +msgstr "مُعطَّلة" + +#: appearance.cpp:82 +#, kde-format +msgid "Show Only Once" +msgstr "أظهرها مرّة واحدة فقط" + +#: appearance.cpp:83 +#, fuzzy, kde-format +msgid "" +"Controls how Konqueror shows animated images:
  • Enabled: Show all animations completely.
  • Disabled: Never show " +"animations, show the starting image only.
  • Show only once: " +"Show all animations completely but do not repeat them.
" +msgstr "" +"يتحكم في كيفية عرض كنكرر للصور المتحركة:
  • مُمكّنة: " +"أظهر جميع الصور بشكل كامل.
  • مُعطّلة: لا تعرض الصور المتحركة، " +"اعرض صورة البدء فقط.
  • أظهرها مرة واحدة فقط: أظهر كل الصور " +"المتحركة بشكل كامل ولكن لا تكررها.
" + +#: appearance.cpp:88 +#, kde-format +msgid "A&nimations:" +msgstr "ال&حركات:" + +#: appearance.cpp:91 htmlopts.cpp:116 +#, kde-format +msgctxt "@title:group" +msgid "Miscellaneous" +msgstr "متنوّع" + +#: appearance.cpp:96 +#, kde-format +msgctxt "underline" +msgid "Enabled" +msgstr "مُمكَّن" + +#: appearance.cpp:97 +#, kde-format +msgctxt "underline" +msgid "Disabled" +msgstr "مُعطَّل" + +#: appearance.cpp:98 +#, kde-format +msgid "Only on Hover" +msgstr "فقط عند التحويم" + +#: appearance.cpp:99 +#, kde-format +msgid "Und&erline links:" +msgstr "ت&سطير الوصلات:" + +#: appearance.cpp:102 +#, fuzzy, kde-format +msgid "" +"Controls how Konqueror handles underlining hyperlinks:
  • Enabled: Always underline links
  • Disabled: " +"Never underline links
  • Only on Hover: Underline when the mouse " +"is moved over the link

Note: The site's CSS definitions " +"can override this value." +msgstr "" +"يتحكم في كيفية التي يتعامل بها كنكرر مع تسطير الوصلات:
  • مُمكّن: يسطر الوصلات دائما
  • مُعطّل: لا يسطر " +"الوصلات مطلقا
  • عند تمرير المؤشر : يسطر الوصلات عندما يمر فوقها " +"مؤشر الفأرة

ملاحظة: ملف تعريف CSS للموقع يستطيع أن يتجاوز " +"هذه القيمة." + +#: appearance.cpp:111 +#, kde-format +msgid "When Efficient" +msgstr "عندما يكون ذلك مناسبًا" + +#: appearance.cpp:112 +#, kde-format +msgctxt "smooth scrolling" +msgid "Always" +msgstr "دائما" + +#: appearance.cpp:113 +#, kde-format +msgctxt "soft scrolling" +msgid "Never" +msgstr "أبدًا" + +#: appearance.cpp:114 +#, kde-format +msgid "S&mooth scrolling:" +msgstr "التمرير الناعم:" + +#: appearance.cpp:116 +#, kde-format +msgid "" +"Determines whether Konqueror should use smooth steps to scroll HTML " +"pages, or whole steps:
  • Always: Always use smooth steps " +"when scrolling.
  • Never: Never use smooth scrolling, scroll " +"with whole steps instead.
  • When Efficient: Only use smooth " +"scrolling on pages where it can be achieved with moderate usage of system " +"resources.
" +msgstr "" +"يحدد فيما إذا كان على كنكرر أن يستخدم خطوات ناعمة لتمرير صفحات الوب أم " +"يستخدم خطوات كاملة:

+See the class list for more information. + +See also the +kfm-devel +mailing list. + +@authors +Torben Weis \
+David Faure \
+Simon Hausmann \
+Holger Freyther \ + +@maintainers +[Unknown/None] + +@licenses +@gpl
+Some files: @lgpl + +*/ + +// DOXYGEN_SET_PROJECT_NAME = libkonq +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/libkonq/Messages.sh b/libkonq/Messages.sh new file mode 100644 index 0000000..a93f8dc --- /dev/null +++ b/libkonq/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT src/*.cpp src/*.h -o $podir/libkonq.pot diff --git a/libkonq/SERVICEMENUS b/libkonq/SERVICEMENUS new file mode 100644 index 0000000..ec56230 --- /dev/null +++ b/libkonq/SERVICEMENUS @@ -0,0 +1,52 @@ +This file explains how to add an item in the popupmenu (for both +konqueror and kdesktop), without using the file associations. + +Why +=== +One reason for doing this is being able to associate +some action with all files without this action becoming a default handler +(called on left click). +Another is that for text-based programs and tools (e.g. gzip) it's faster +than defining a desktop file for the application, making it hidden, and +associate it with the relevant file types. + +How +=== +Create a file ~/.kde/share/kde4/services/ServiceMenus/something.desktop +and write into it something like (without the comments) : + +[Desktop Entry] +ServiceTypes=KonqPopupMenu/Plugin,text/html,text/plain # use all/all for all entries + # all/allfiles for files only + # and use inode/directory for dirs only + # you can also do things like image/* for all + # image mimetypes +Actions=gzip;mail # those are ';' separated, per the standard ! +X-KDE-Submenu=Menuname # this optional entry allows grouping the + # entries in this servicemenu file into a + # common submenu, in this case "Menuname" +TryExec=gzip # Find if executable exist, if it doesn't exist + # menu entry is not displaying +ExcludeServiceTypes=application/x-zip # This entry is used to avoid to display menu + # when it's a specific servicetype + # for exemple when we use all/allfiles and zip + # them, we don't want to zip a zip file + + +[Desktop Action gzip] # One "Desktop Action " group per Action +Name=GZip this file +Name[fr]=... +Icon=application-x-tarz +Exec=gzip %f + +[Desktop Action mail] +Name=Mail this file +Name[fr]=... +Icon=internet-mail +Exec=kmail --there-is-no-such-option-yet %f + + +See also the "desktop entry standard", which defines more formally the same +concept of actions but for desktop files (e.g. eject on a device desktop file, +etc.) + diff --git a/libkonq/autotests/CMakeLists.txt b/libkonq/autotests/CMakeLists.txt new file mode 100644 index 0000000..015753e --- /dev/null +++ b/libkonq/autotests/CMakeLists.txt @@ -0,0 +1,16 @@ +include(ECMAddTests) + +find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) + + +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + + +########### konqpopupmenutest ############### + +ecm_add_tests( + konqpopupmenutest.cpp + LINK_LIBRARIES KF5Konq Qt5::Test +) + +############################################ diff --git a/libkonq/autotests/konqpopupmenutest.cpp b/libkonq/autotests/konqpopupmenutest.cpp new file mode 100644 index 0000000..800be37 --- /dev/null +++ b/libkonq/autotests/konqpopupmenutest.cpp @@ -0,0 +1,455 @@ +/* This file is part of KDE + Copyright (c) 2007 David Faure + + 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. +*/ + +#undef QT_NO_CAST_FROM_ASCII + +#include "konqpopupmenutest.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +QTEST_MAIN(KonqPopupMenuTest) + +KonqPopupMenuTest::KonqPopupMenuTest() + : m_actionCollection(this) +{ + m_appFlags = KonqPopupMenu::NoPlugins; +} + +static QStringList extractActionNames(QMenu &menu) +{ + menu.aboutToShow(); // signals are now public in Qt5, how convenient :-) + + QString lastObjectName; + QStringList ret; + bool lastIsSeparator = false; + foreach (const QAction *action, menu.actions()) { + if (action->isSeparator()) { + if (!lastIsSeparator) { // Qt gets rid of duplicate separators, so we should too + ret.append(QStringLiteral("separator")); + } + lastIsSeparator = true; + } else { + lastIsSeparator = false; + //qDebug() << action->objectName() << action->metaObject()->className() << action->text(); + const QString objectName = action->objectName(); + if (objectName.isEmpty()) { + if (action->menu()) { // if this fails, then we have an unnamed action somewhere... + ret.append(QStringLiteral("submenu")); + } else { + ret.append("UNNAMED " + action->text()); + } + } else { + if (objectName == QLatin1String("menuaction") // a single service-menu action, or a service-menu submenu: skip; too variable. + || objectName == QLatin1String("actions_submenu")) { + } else if (objectName == QLatin1String("openWith_submenu")) { + ret.append(QStringLiteral("openwith")); + } else if (objectName == QLatin1String("openwith_browse") && lastObjectName == QLatin1String("openwith")) { + // We had "open with foo" followed by openwith_browse, all is well. + // The expected lists only say "openwith" so that they work in both cases + // -> skip the browse action. + } else { + ret.append(objectName); + } + } + } + lastObjectName = action->objectName(); + } + return ret; + +} + +void KonqPopupMenuTest::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); + + KSharedConfig::Ptr dolphin = KSharedConfig::openConfig(QStringLiteral("dolphinrc")); + KConfigGroup(dolphin, "General").writeEntry("ShowCopyMoveMenu", true); + + m_thisDirectoryItem = KFileItem(QUrl::fromLocalFile(QDir::currentPath()), QStringLiteral("inode/directory"), S_IFDIR + 0777); + const QString makefile = QDir::currentPath() + "/Makefile"; + QVERIFY2(QFile::exists(makefile), qPrintable(makefile)); + m_fileItem = KFileItem(QUrl::fromLocalFile(makefile), QStringLiteral("text/x-makefile"), S_IFREG + 0660); + m_linkItem = KFileItem(QUrl::fromLocalFile(QStringLiteral("http://www.kde.org/foo")), QStringLiteral("text/html"), S_IFREG + 0660); + m_subDirItem = KFileItem(QUrl::fromLocalFile(QDir::currentPath() + "/CMakeFiles"), QStringLiteral("inode/directory"), S_IFDIR + 0755); + m_cut = KStandardAction::cut(nullptr, nullptr, this); + m_actionCollection.addAction(QStringLiteral("cut"), m_cut); + m_copy = KStandardAction::copy(nullptr, nullptr, this); + m_actionCollection.addAction(QStringLiteral("copy"), m_copy); + m_paste = KStandardAction::paste(nullptr, nullptr, this); + m_actionCollection.addAction(QStringLiteral("paste"), m_paste); + m_pasteTo = KStandardAction::paste(nullptr, nullptr, this); + m_actionCollection.addAction(QStringLiteral("pasteto"), m_pasteTo); + m_properties = new QAction(this); + m_actionCollection.addAction(QStringLiteral("properties"), m_properties); + + m_tabHandlingActions = new QActionGroup(this); + m_newWindow = new QAction(m_tabHandlingActions); + m_actionCollection.addAction(QStringLiteral("openInNewWindow"), m_newWindow); + m_newTab = new QAction(m_tabHandlingActions); + m_actionCollection.addAction(QStringLiteral("openInNewTab"), m_newTab); + QAction *separator = new QAction(m_tabHandlingActions); + separator->setSeparator(true); + QCOMPARE(m_tabHandlingActions->actions().count(), 3); + + m_previewActions = new QActionGroup(this); + m_preview1 = new QAction(m_previewActions); + m_actionCollection.addAction(QStringLiteral("preview1"), m_preview1); + m_preview2 = new QAction(m_previewActions); + m_actionCollection.addAction(QStringLiteral("preview2"), m_preview2); + + m_fileEditActions = new QActionGroup(this); + m_rename = new QAction(m_fileEditActions); + m_actionCollection.addAction(QStringLiteral("rename"), m_rename); + m_trash = new QAction(m_fileEditActions); + m_actionCollection.addAction(QStringLiteral("trash"), m_trash); + + m_htmlEditActions = new QActionGroup(this); + // TODO use m_htmlEditActions like in khtml (see khtml_popupmenu.rc) + + m_linkActions = new QActionGroup(this); + QAction *saveLinkAs = new QAction(m_linkActions); + m_actionCollection.addAction(QStringLiteral("savelinkas"), saveLinkAs); + QAction *copyLinkLocation = new QAction(m_linkActions); + m_actionCollection.addAction(QStringLiteral("copylinklocation"), copyLinkLocation); + // TODO there's a whole bunch of things for frames, and for images, see khtml_popupmenu.rc + + m_partActions = new QActionGroup(this); + separator = new QAction(m_partActions); + separator->setSeparator(true); + m_partActions->addAction(separator); // we better start with a separator + QAction *viewDocumentSource = new QAction(m_partActions); + m_actionCollection.addAction(QStringLiteral("viewDocumentSource"), viewDocumentSource); + + m_newMenu = new KNewFileMenu(&m_actionCollection, QStringLiteral("newmenu"), nullptr); + + // Check if extractActionNames works + QMenu popup; + popup.addAction(m_rename); + QMenu *subMenu = new QMenu(&popup); + popup.addMenu(subMenu); + subMenu->addAction(m_trash); + QStringList actions = extractActionNames(popup); + qDebug() << actions; + QCOMPARE(actions, QStringList() << "rename" << "submenu"); +} + +void KonqPopupMenuTest::testFile() +{ + KFileItemList itemList; + itemList << m_fileItem; + QUrl viewUrl = QUrl::fromLocalFile(QDir::currentPath()); + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowProperties + | KonqPopupMenu::ShowUrlOperations; + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + actionGroups.insert(KonqPopupMenu::EditActions, m_fileEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, QList() << m_preview1); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags, + nullptr /*parent*/); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("openInNewWindow") << QStringLiteral("openInNewTab") << QStringLiteral("separator") + << QStringLiteral("cut") << QStringLiteral("copy") << QStringLiteral("rename") << QStringLiteral("trash") + << QStringLiteral("openwith") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview1"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu") << QStringLiteral("separator"); + // (came from arkplugin) << "compress" + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testFileInReadOnlyDirectory() +{ + const KFileItem item(QUrl::fromLocalFile(QStringLiteral("/etc/passwd"))); + KFileItemList itemList; + itemList << item; + + KFileItemListProperties capabilities(itemList); + QVERIFY(!capabilities.supportsMoving()); + + QUrl viewUrl = QUrl::fromLocalFile(QStringLiteral("/etc")); + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowProperties + | KonqPopupMenu::ShowUrlOperations; + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + // DolphinPart doesn't add rename/trash when supportsMoving is false + // Maybe we should test dolphinpart directly :) + //actionGroups.insert(KonqPopupMenu::EditActions, m_fileEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, QList() << m_preview1); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("openInNewWindow") << QStringLiteral("openInNewTab") << QStringLiteral("separator") + << QStringLiteral("copy") + << QStringLiteral("openwith") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview1"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("separator"); + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testFilePreviewSubMenu() +{ + // Same as testFile, but this time the "preview" action group has more than one action + KFileItemList itemList; + itemList << m_fileItem; + QUrl viewUrl = QUrl::fromLocalFile(QDir::currentPath()); + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowProperties + | KonqPopupMenu::ShowUrlOperations; + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + actionGroups.insert(KonqPopupMenu::EditActions, m_fileEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("openInNewWindow") << QStringLiteral("openInNewTab") << QStringLiteral("separator") + << QStringLiteral("cut") << QStringLiteral("copy") << QStringLiteral("rename") << QStringLiteral("trash") + << QStringLiteral("openwith") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu") << QStringLiteral("separator"); + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testSubDirectory() +{ + KFileItemList itemList; + itemList << m_subDirItem; + QUrl viewUrl = QUrl::fromLocalFile(QDir::currentPath()); + + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowProperties + | KonqPopupMenu::ShowUrlOperations; + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + actionGroups.insert(KonqPopupMenu::EditActions, m_fileEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("openInNewWindow") << QStringLiteral("openInNewTab") << QStringLiteral("separator") + << QStringLiteral("cut") << QStringLiteral("copy") << QStringLiteral("pasteto") << QStringLiteral("rename") << QStringLiteral("trash") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu") << QStringLiteral("separator"); + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testViewDirectory() +{ + KFileItemList itemList; + itemList << m_thisDirectoryItem; + QUrl viewUrl = m_thisDirectoryItem.url(); + const KonqPopupMenu::Flags flags = m_appFlags | + KonqPopupMenu::ShowCreateDirectory | + KonqPopupMenu::ShowUrlOperations | + KonqPopupMenu::ShowProperties; + // KonqMainWindow says: doTabHandling = !openedForViewURL && ... So we don't add tabhandling here + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("newmenu") << QStringLiteral("separator") + << QStringLiteral("paste") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu") << QStringLiteral("separator"); + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testViewReadOnlyDirectory() +{ + KFileItem rootItem(QUrl::fromLocalFile(QDir::rootPath()), QStringLiteral("inode/directory"), KFileItem::Unknown); + KFileItemList itemList; + itemList << rootItem; + QUrl viewUrl = rootItem.url(); + const KonqPopupMenu::Flags flags = m_appFlags | + KonqPopupMenu::ShowCreateDirectory | + KonqPopupMenu::ShowUrlOperations | + KonqPopupMenu::ShowProperties; + // KonqMainWindow says: doTabHandling = !openedForViewURL && ... So we don't add tabhandling here + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + + QStringList actions = extractActionNames(popup); + actions.removeAll(QStringLiteral("services_submenu")); + qDebug() << actions; + QStringList expectedActions; + expectedActions // << "paste" // no paste since readonly + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu"); + expectedActions << QStringLiteral("separator"); + expectedActions << QStringLiteral("copyTo_submenu") << QStringLiteral("separator"); // no moveTo_submenu, since readonly + expectedActions << QStringLiteral("properties"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testHtmlLink() +{ + KFileItemList itemList; + itemList << m_linkItem; + QUrl viewUrl(QStringLiteral("http://www.kde.org")); + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowBookmark + | KonqPopupMenu::IsLink; + KonqPopupMenu::ActionGroupMap actionGroups; + actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + actionGroups.insert(KonqPopupMenu::EditActions, m_htmlEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + actionGroups.insert(KonqPopupMenu::LinkActions, m_linkActions->actions()); + actionGroups.insert(KonqPopupMenu::CustomActions, m_partActions->actions()); + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + popup.setBookmarkManager(KBookmarkManager::userBookmarksManager()); + + QStringList actions = extractActionNames(popup); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("openInNewWindow") << QStringLiteral("openInNewTab") << QStringLiteral("separator") + << QStringLiteral("bookmark_add") << QStringLiteral("savelinkas") << QStringLiteral("copylinklocation") + << QStringLiteral("openwith") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu") + << QStringLiteral("separator") + << QStringLiteral("viewDocumentSource"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +void KonqPopupMenuTest::testHtmlPage() +{ + KFileItemList itemList; + itemList << m_linkItem; + QUrl viewUrl = m_linkItem.url(); + + const KonqPopupMenu::Flags flags = m_appFlags + | KonqPopupMenu::ShowBookmark; + KonqPopupMenu::ActionGroupMap actionGroups; + // KonqMainWindow says: doTabHandling = !openedForViewURL && ... So we don't add tabhandling here + // TODO we could just move that logic to KonqPopupMenu... + //actionGroups.insert(KonqPopupMenu::TabHandlingActions, m_tabHandlingActions->actions()); + actionGroups.insert(KonqPopupMenu::EditActions, m_htmlEditActions->actions()); + actionGroups.insert(KonqPopupMenu::PreviewActions, m_previewActions->actions()); + //actionGroups.insert(KonqPopupMenu::LinkActions, m_linkActions->actions()); + QAction *security = new QAction(m_partActions); + m_actionCollection.addAction(QStringLiteral("security"), security); + QAction *setEncoding = new QAction(m_partActions); + m_actionCollection.addAction(QStringLiteral("setEncoding"), setEncoding); + actionGroups.insert(KonqPopupMenu::CustomActions, m_partActions->actions()); + + KonqPopupMenu popup(itemList, viewUrl, m_actionCollection, flags); + popup.setNewFileMenu(m_newMenu); + popup.setActionGroups(actionGroups); + popup.setBookmarkManager(KBookmarkManager::userBookmarksManager()); + + QStringList actions = extractActionNames(popup); + qDebug() << actions; + QStringList expectedActions; + expectedActions << QStringLiteral("bookmark_add") + << QStringLiteral("openwith") + << QStringLiteral("openwith") + << QStringLiteral("separator") + << QStringLiteral("preview_submenu") + << QStringLiteral("separator") + // << TODO "stopanimations" + << QStringLiteral("viewDocumentSource") << QStringLiteral("security") << QStringLiteral("setEncoding"); + qDebug() << "Expected:" << expectedActions; + QCOMPARE(actions, expectedActions); +} + +// TODO test ShowBookmark. Probably the same logic? +// TODO separate filemanager and webbrowser bookmark managers, too (share file bookmarks with file dialog) + +// TODO test text selection actions in khtml + +// TODO trash:/ tests + +// TODO test NoDeletion part flag diff --git a/libkonq/autotests/konqpopupmenutest.h b/libkonq/autotests/konqpopupmenutest.h new file mode 100644 index 0000000..c64ddfd --- /dev/null +++ b/libkonq/autotests/konqpopupmenutest.h @@ -0,0 +1,75 @@ +/* This file is part of KDE + Copyright (c) 2007 David Faure + + 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 KONQPOPUPMENUTEST_H +#define KONQPOPUPMENUTEST_H + +#include +#include +#include +#include +class KNewFileMenu; + +class KonqPopupMenuTest : public QObject +{ + Q_OBJECT +public: + KonqPopupMenuTest(); + +private Q_SLOTS: + void initTestCase(); + void testFile(); + void testFileInReadOnlyDirectory(); + void testFilePreviewSubMenu(); + void testSubDirectory(); + void testViewDirectory(); + void testViewReadOnlyDirectory(); + + void testHtmlLink(); + void testHtmlPage(); + +private: + KonqPopupMenu::Flags m_appFlags; + + KFileItem m_fileItem; + KFileItem m_linkItem; + KFileItem m_subDirItem; + KFileItem m_thisDirectoryItem; + QAction *m_cut; + QAction *m_copy; + QAction *m_paste; + QAction *m_pasteTo; + QAction *m_properties; + QAction *m_rename; + QAction *m_trash; + QAction *m_newWindow; + QAction *m_newTab; + QAction *m_preview1; + QAction *m_preview2; + QActionGroup *m_tabHandlingActions; + QActionGroup *m_previewActions; + QActionGroup *m_htmlEditActions; + QActionGroup *m_fileEditActions; + QActionGroup *m_linkActions; + QActionGroup *m_partActions; + KNewFileMenu *m_newMenu; + KActionCollection m_actionCollection; +}; + +#endif diff --git a/libkonq/src/CMakeLists.txt b/libkonq/src/CMakeLists.txt new file mode 100644 index 0000000..6dd2cc3 --- /dev/null +++ b/libkonq/src/CMakeLists.txt @@ -0,0 +1,60 @@ +add_definitions(-DTRANSLATION_DOMAIN=\"libkonq\") + +########### libkonq ############### + +set(konq_LIB_SRCS + konq_popupmenu.cpp # now only used by konqueror, could move there + konq_events.cpp + konq_historyentry.cpp + konq_historyloader.cpp + konq_historyprovider.cpp # konqueror and konqueror/sidebar +) + +add_library(KF5Konq ${konq_LIB_SRCS}) + +include(GenerateExportHeader) +generate_export_header(KF5Konq BASE_NAME libkonq EXPORT_FILE_NAME libkonq_export.h) + +add_library(KF5::Konq ALIAS KF5Konq) + +target_link_libraries(KF5Konq + PUBLIC + KF5::XmlGui + KF5::ConfigCore + KF5::KIOCore + KF5::KIOFileWidgets + KF5::CoreAddons + KF5::Service + KF5::Parts + PRIVATE + KF5::Bookmarks + KF5::I18n + ${ZLIB_LIBRARY} +) + +# For crc32 in konq_historyloader.cpp +target_include_directories(KF5Konq PRIVATE ${ZLIB_INCLUDE_DIR}) + + +set_target_properties(KF5Konq PROPERTIES + VERSION ${KONQ_VERSION_STRING} + SOVERSION ${KONQ_SOVERSION} + EXPORT_NAME Konq +) + +install(TARGETS KF5Konq EXPORT KF5KonqTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) + +########### install files ############### + +install(FILES directory_bookmarkbar.desktop DESTINATION ${KDE_INSTALL_DATADIR_KF5}/kbookmark) +install(FILES + konq_events.h + konq_historyentry.h + konq_historyprovider.h + konq_popupmenu.h + ${LibKonq_BINARY_DIR}/src/libkonq_export.h + + DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} + COMPONENT Devel +) + diff --git a/libkonq/src/directory_bookmarkbar.desktop b/libkonq/src/directory_bookmarkbar.desktop new file mode 100644 index 0000000..bcbe584 --- /dev/null +++ b/libkonq/src/directory_bookmarkbar.desktop @@ -0,0 +1,95 @@ +[Desktop Entry] +Icon=bookmark-toolbar +Name=Bookmark Toolbar +Name[af]=Boekmerk Nutsbalk +Name[ar]=شريط أدوات العلامات +Name[as]=পত্ৰচিহ্নৰ টুলবাৰ +Name[ast]=Barra de ferramientes de marcadores +Name[be]=Панель закладак +Name[be@latin]=Panel zakładak +Name[bg]=Лента с отметки +Name[bn]=বুকমার্ক টুলবার +Name[bn_IN]=বুকমার্ক টুল-বার +Name[br]=Barrenn ostilhoù sined +Name[bs]=Traka sa obeleživačima +Name[ca]=Barra d'eines de punts +Name[ca@valencia]=Barra d'eines de punts +Name[cs]=Panel nástrojů se záložkami +Name[csb]=Lëstew załóżków +Name[cy]=Bar Offer Nodau Tudalen +Name[da]=Bogmærkeværktøjslinje +Name[de]=Lesezeichenleiste +Name[el]=Γραμμή εργαλείων Σελιδοδεικτών +Name[en_GB]=Bookmark Toolbar +Name[eo]=Legosigna ilobreto +Name[es]=Barra de herramientas de marcadores +Name[et]=Järjehoidjate tööriistariba +Name[eu]=Laster-marken barra +Name[fa]=میله ابزار چوب الف +Name[fi]=Kirjanmerkkien työkalurivi +Name[fr]=Barre d'outils pour les signets +Name[fy]=Blêdwizerbalke +Name[ga]=Barra Uirlisí Leabharmharcanna +Name[gl]=Barra de Marcadores +Name[gu]=બુકમાર્ક સાધનપટ્ટી +Name[he]=סרגל הסימניות +Name[hi]=पसंदीदा औज़ार पट्टी +Name[hne]=निसानी औजार पट्टी +Name[hr]=Traka s oznakama +Name[hsb]=Nastrojowy pas za lubuški +Name[hu]=Könyvjelző-eszköztár +Name[ia]=Barra de instrumento de marcator de libros +Name[id]=Bilah Alat Markah +Name[is]=Bókamerkjaslá +Name[it]=Barra dei segnalibri +Name[ja]=ブックマークツールバー +Name[ka]=სანიშნეთა პანელი +Name[kk]=Бетбелгі панелі +Name[km]=របារ​ឧបករណ៍​ចំណាំ +Name[kn]=ಅಂಕನ (ಬುಕ್ಮಾರ್ಕ್) ಸಲಕರಣೆಪಟ್ಟಿ +Name[ko]=책갈피 도구 모음 +Name[ku]=Darikê Amûran a Bijareyan +Name[lt]=Žymelių įrankinė +Name[lv]=Grāmatzīmju rīkjosla +Name[mai]=पसंदीदा अओजार पट्टी +Name[mk]=Алатник за обележувачи +Name[ml]=പണിയായുധനിര +Name[mr]=ओळखचिन्ह साधनपट्टी +Name[ms]=Bar Alatan Penandabuku +Name[nb]=Verktøylinje for bokmerker +Name[nds]=Leesteken-Warktüüchbalken +Name[ne]=पुस्तकचिनो उपकरणपट्टी +Name[nl]=Werkbalk met bladwijzers +Name[nn]=Bokmerke-verktøylinje +Name[oc]=Barra dels favorits +Name[or]=ସାଧନପଟିକୁ ଚିହ୍ନଟ କରନ୍ତୁ +Name[pa]=ਬੁੱਕਮਾਰਕ ਸੰਦਪੱਟੀ +Name[pl]=Pasek zakładek +Name[pt]=Barra de Favoritos +Name[pt_BR]=Barra de ferramentas de favoritos +Name[ro]=Bară semne de carte +Name[ru]=Панель закладок +Name[se]=Girjemearkaholga +Name[si]=පොත්සලකුණු මෙවලම් තීරුව +Name[sk]=Panel záložiek +Name[sl]=Orodna vrstica zaznamkov +Name[sr]=Трака са обележивачима +Name[sr@ijekavian]=Трака са обиљеживачима +Name[sr@ijekavianlatin]=Traka sa obilježivačima +Name[sr@latin]=Traka sa obeleživačima +Name[sv]=Verktygsrad med bokmärken +Name[ta]=புத்தகக்குறிக் கருவிப்பட்டை +Name[te]=సాధనపట్టీని ఇష్టాంశముచేయుము +Name[tg]=Лавҳаи хатчӯбҳо +Name[th]=แถบเครื่องมือที่คั่นหน้า +Name[tr]=Yer İmleri Araç Çubuğu +Name[ug]=خەتكۈش قورال بالداق +Name[uk]=Панель закладок +Name[uz]=Xatchoʻp paneli +Name[uz@cyrillic]=Хатчўп панели +Name[vi]=Thanh công cụ Lưu địa chỉ +Name[wa]=Bår ås usteyes des rmåkes +Name[xh]=Ibar yesixhobo Senqaku lencwadi +Name[x-test]=xxBookmark Toolbarxx +Name[zh_CN]=书签工具栏 +Name[zh_TW]=書籤工具列 diff --git a/libkonq/src/konq_events.cpp b/libkonq/src/konq_events.cpp new file mode 100644 index 0000000..4f29765 --- /dev/null +++ b/libkonq/src/konq_events.cpp @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Simon Hausmann + Copyright (C) 2000-2007 David Faure + + 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. +*/ + +#include "konq_events.h" + +const char *const KonqFileSelectionEvent::s_fileItemSelectionEventName = "Konqueror/FileSelection"; +const char *const KonqFileMouseOverEvent::s_fileItemMouseOverEventName = "Konqueror/FileMouseOver"; + +KonqFileSelectionEvent::KonqFileSelectionEvent(const KFileItemList &selection, KParts::ReadOnlyPart *part) + : KParts::Event(s_fileItemSelectionEventName), m_selection(selection), m_part(part) +{ +} + +KonqFileSelectionEvent::~KonqFileSelectionEvent() +{ +} + +KonqFileMouseOverEvent::KonqFileMouseOverEvent(const KFileItem &item, KParts::ReadOnlyPart *part) + : KParts::Event(s_fileItemMouseOverEventName), m_item(item), m_part(part) +{ +} + +KonqFileMouseOverEvent::~KonqFileMouseOverEvent() +{ +} diff --git a/libkonq/src/konq_events.h b/libkonq/src/konq_events.h new file mode 100644 index 0000000..c499291 --- /dev/null +++ b/libkonq/src/konq_events.h @@ -0,0 +1,92 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Simon Hausmann + Copyright (C) 2000-2007 David Faure + + 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 __konq_events_h__ +#define __konq_events_h__ + +#include +#include +#include +#include +#include + +namespace KParts +{ +class ReadOnlyPart; +} + + +class LIBKONQ_EXPORT KonqFileSelectionEvent : public KParts::Event +{ +public: + KonqFileSelectionEvent(const KFileItemList &selection, KParts::ReadOnlyPart *part); + ~KonqFileSelectionEvent() override; + + KFileItemList selection() const + { + return m_selection; + } + KParts::ReadOnlyPart *part() const + { + return m_part; + } + + static bool test(const QEvent *event) + { + return KParts::Event::test(event, s_fileItemSelectionEventName); + } + +private: + Q_DISABLE_COPY(KonqFileSelectionEvent) + static const char *const s_fileItemSelectionEventName; + + KFileItemList m_selection; + KParts::ReadOnlyPart *m_part; +}; + +class LIBKONQ_EXPORT KonqFileMouseOverEvent : public KParts::Event +{ +public: + KonqFileMouseOverEvent(const KFileItem &item, KParts::ReadOnlyPart *part); + ~KonqFileMouseOverEvent() override; + + const KFileItem &item() const + { + return m_item; + } + KParts::ReadOnlyPart *part() const + { + return m_part; + } + + static bool test(const QEvent *event) + { + return KParts::Event::test(event, s_fileItemMouseOverEventName); + } + +private: + Q_DISABLE_COPY(KonqFileMouseOverEvent) + static const char *const s_fileItemMouseOverEventName; + + KFileItem m_item; + KParts::ReadOnlyPart *m_part; +}; + +#endif diff --git a/libkonq/src/konq_historyentry.cpp b/libkonq/src/konq_historyentry.cpp new file mode 100644 index 0000000..4fd4958 --- /dev/null +++ b/libkonq/src/konq_historyentry.cpp @@ -0,0 +1,125 @@ +/* This file is part of the KDE project + Copyright 2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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. +*/ + +#include "konq_historyentry.h" +#include + +KonqHistoryEntry::KonqHistoryEntry() + : numberOfTimesVisited(1), d(nullptr) +{ +} + +KonqHistoryEntry::~KonqHistoryEntry() +{ +} + +KonqHistoryEntry::KonqHistoryEntry(const KonqHistoryEntry &other) +{ + operator=(other); +} + +KonqHistoryEntry &KonqHistoryEntry::operator=(const KonqHistoryEntry &other) +{ + url = other.url; + typedUrl = other.typedUrl; + title = other.title; + numberOfTimesVisited = other.numberOfTimesVisited; + firstVisited = other.firstVisited; + lastVisited = other.lastVisited; + d = nullptr; + return *this; +} + +bool KonqHistoryEntry::operator==(const KonqHistoryEntry &entry) const +{ + return url == entry.url && + typedUrl == entry.typedUrl && + title == entry.title && + numberOfTimesVisited == entry.numberOfTimesVisited && + firstVisited == entry.firstVisited && + lastVisited == entry.lastVisited; +} + +void KonqHistoryEntry::load(QDataStream &s, Flags flags) +{ + if (flags & MarshalUrlAsStrings) { + QString urlStr; + s >> urlStr; + url = QUrl(urlStr); + } else { + s >> url; + } + s >> typedUrl; + s >> title; + s >> numberOfTimesVisited; + s >> firstVisited; + s >> lastVisited; +} + +void KonqHistoryEntry::save(QDataStream &s, Flags flags) const +{ + if (flags & MarshalUrlAsStrings) { + s << url.url(); + } else { + s << url; + } + s << typedUrl; + s << title; + s << numberOfTimesVisited; + s << firstVisited; + s << lastVisited; +} + +//// + +KonqHistoryList::iterator KonqHistoryList::findEntry(const QUrl &url) +{ + // we search backwards, probably faster to find an entry + KonqHistoryList::iterator it = end(); + while (it != begin()) { + --it; + if ((*it).url == url) { + return it; + } + } + return end(); +} + +KonqHistoryList::const_iterator KonqHistoryList::constFindEntry(const QUrl &url) const +{ + // we search backwards, probably faster to find an entry + KonqHistoryList::const_iterator it = constEnd(); + while (it != constBegin()) { + --it; + if ((*it).url == url) { + return it; + } + } + return constEnd(); +} + +void KonqHistoryList::removeEntry(const QUrl &url) +{ + iterator it = findEntry(url); + if (it != end()) { + erase(it); + } +} + diff --git a/libkonq/src/konq_historyentry.h b/libkonq/src/konq_historyentry.h new file mode 100644 index 0000000..038246f --- /dev/null +++ b/libkonq/src/konq_historyentry.h @@ -0,0 +1,85 @@ +/* This file is part of the KDE project + Copyright 2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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 KONQ_HISTORYENTRY_H +#define KONQ_HISTORYENTRY_H + +#include +#include +#include +#include "libkonq_export.h" + +class LIBKONQ_EXPORT KonqHistoryEntry +{ +public: + KonqHistoryEntry(); + KonqHistoryEntry(const KonqHistoryEntry &other); + ~KonqHistoryEntry(); + + KonqHistoryEntry &operator=(const KonqHistoryEntry &entry); + + QUrl url; + QString typedUrl; + QString title; + quint32 numberOfTimesVisited; + QDateTime firstVisited; + QDateTime lastVisited; + + // Necessary for QList (on Windows) + bool operator==(const KonqHistoryEntry &entry) const; + + enum Flags { NoFlags = 0, MarshalUrlAsStrings = 1 }; + void load(QDataStream &s, Flags flags); + void save(QDataStream &s, Flags flags) const; + +private: + class Private; + Private *d; +}; + +#ifdef MAKE_KONQ_LIB +KDE_DUMMY_QHASH_FUNCTION(KonqHistoryEntry) +#endif + +Q_DECLARE_METATYPE(KonqHistoryEntry) + +class LIBKONQ_EXPORT KonqHistoryList : public QList +{ +public: + /** + * Finds an entry by URL and return an iterator to it. + * If no matching entry is found, end() is returned. + */ + iterator findEntry(const QUrl &url); + + /** + * Finds an entry by URL and return an iterator to it. + * If no matching entry is found, end() is returned. + */ + const_iterator constFindEntry(const QUrl &url) const; + + /** + * Finds an entry by URL and removes it + */ + void removeEntry(const QUrl &url); +}; + +#endif /* KONQ_HISTORYENTRY_H */ + diff --git a/libkonq/src/konq_historyloader.cpp b/libkonq/src/konq_historyloader.cpp new file mode 100644 index 0000000..63a6aec --- /dev/null +++ b/libkonq/src/konq_historyloader.cpp @@ -0,0 +1,149 @@ +/* This file is part of the KDE project + Copyright 2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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. +*/ + +#include "konq_historyloader_p.h" +#include "konq_historyentry.h" + +#include +#include +#include +#include + +#include // for crc32 + +class KonqHistoryLoaderPrivate +{ +public: + KonqHistoryList m_history; +}; + +KonqHistoryLoader::KonqHistoryLoader(QObject *parent) + : QObject(parent), d(new KonqHistoryLoaderPrivate) +{ + loadHistory(); +} + +KonqHistoryLoader::~KonqHistoryLoader() +{ + delete d; +} + +/** + * Ensures that the items are sorted by the lastVisited date + * (oldest goes first) + */ +static bool lastVisitedOrder(const KonqHistoryEntry &lhs, const KonqHistoryEntry &rhs) +{ + return lhs.lastVisited < rhs.lastVisited; +} + +bool KonqHistoryLoader::loadHistory() +{ + d->m_history.clear(); + + const QString filename = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/konqueror/konq_history"); + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + if (file.exists()) { + qWarning() << "Can't open" << filename; + } + return false; + } + + QDataStream fileStream(&file); + QByteArray data; // only used for version == 2 + // we construct the stream object now but fill in the data later. + QDataStream crcStream(&data, QIODevice::ReadOnly); + KonqHistoryEntry::Flags flags = KonqHistoryEntry::NoFlags; + + if (!fileStream.atEnd()) { + quint32 version; + fileStream >> version; + + QDataStream *stream = &fileStream; + + bool crcChecked = false; + bool crcOk = false; + + if (version >= 2 && version <= 4) { + quint32 crc; + crcChecked = true; + fileStream >> crc >> data; + crcOk = crc32(0, reinterpret_cast(data.data()), data.size()) == crc; + stream = &crcStream; // pick up the right stream + } + + // We can't read v3 history anymore, because operator<<(KURL) disappeared. + + if (version == 4) { + // Use QUrl marshalling for V4 format. + flags = KonqHistoryEntry::NoFlags; + } + +#if 0 // who cares for versions 1 and 2 nowadays... + if (version != 0 && version < 3) { //Versions 1,2 (but not 0) are also valid + //Turn on backwards compatibility mode.. + marshalURLAsStrings = true; + // it doesn't make sense to save to save maxAge and maxCount in the + // binary file, this would make backups impossible (they would clear + // themselves on startup, because all entries expire). + // [But V1 and V2 formats did it, so we do a dummy read] + quint32 dummy; + *stream >> dummy; + *stream >> dummy; + + //OK. + version = 3; + } +#endif + + if (historyVersion() != int(version) || (crcChecked && !crcOk)) { + qWarning() << "The history version doesn't match, aborting loading"; + file.close(); + return false; + } + + while (!stream->atEnd()) { + KonqHistoryEntry entry; + entry.load(*stream, flags); + // kDebug(1202) << "loaded entry:" << entry.url << ", Title:" << entry.title; + d->m_history.append(entry); + } + + //kDebug(1202) << "loaded:" << m_history.count() << "entries."; + + std::sort(d->m_history.begin(), d->m_history.end(), lastVisitedOrder); + } + + // Theoretically, we should emit update() here, but as we only ever + // load items on startup up to now, this doesn't make much sense. + // emit KParts::HistoryProvider::update(some list); + return true; +} + +const KonqHistoryList &KonqHistoryLoader::entries() const +{ + return d->m_history; +} + +int KonqHistoryLoader::historyVersion() +{ + return 4; +} diff --git a/libkonq/src/konq_historyloader_p.h b/libkonq/src/konq_historyloader_p.h new file mode 100644 index 0000000..ffab98a --- /dev/null +++ b/libkonq/src/konq_historyloader_p.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright 2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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 KONQ_HISTORYLOADER_H +#define KONQ_HISTORYLOADER_H + +#include "libkonq_export.h" +#include + +class KonqHistoryList; +class KonqHistoryLoaderPrivate; + +/** + * @internal + * This class loads the Konqueror history file. + * @since 4.3 + */ +class KonqHistoryLoader : public QObject +{ + Q_OBJECT + +public: + explicit KonqHistoryLoader(QObject *parent = nullptr); + ~KonqHistoryLoader() override; + + /** + * Load the history. No need to call this more than once... + */ + bool loadHistory(); + + /** + * @returns the list of all history entries, sorted by date + * (oldest entries first) + */ + const KonqHistoryList &entries() const; + + static int historyVersion(); + +private: + KonqHistoryLoaderPrivate *const d; +}; + +#endif /* KONQ_HISTORYLOADER_H */ diff --git a/libkonq/src/konq_historyprovider.cpp b/libkonq/src/konq_historyprovider.cpp new file mode 100644 index 0000000..ff05d33 --- /dev/null +++ b/libkonq/src/konq_historyprovider.cpp @@ -0,0 +1,465 @@ +/* This file is part of the KDE project + Copyright 2000,2001 Carsten Pfeiffer + Copyright 2007-2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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. +*/ + +#include "konq_historyprovider.h" + +#include +#include +#include "konq_historyloader_p.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for crc32 + +class KonqHistoryProviderPrivate : public QObject, QDBusContext +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.Konqueror.HistoryManager") +public: + KonqHistoryProviderPrivate(KonqHistoryProvider *qq); + + /** + * Resizes the history list to contain less or equal than m_maxCount + * entries. The first (oldest) entries are removed. + */ + void adjustSize(); + + /** + * Saves the entire history. + */ + bool saveHistory(); + +Q_SIGNALS: // DBUS methods/signals, they have to match org.kde.Konqueror.HistoryManager.xml + friend class KonqHistoryProvider; + /** + * Every konqueror instance broadcasts new history entries to the other + * konqueror instances. Those add the entry to their list, but don't + * save the list, because the sender saves the list. + * + * @param e the new history entry + * @param saveId is the dbus service of the sender so that + * only the sender saves the new history. + */ + void notifyHistoryEntry(const QByteArray &historyEntry); + + /** + * Called when the configuration of the maximum count changed. + * Called via DBUS by some config-module + */ + void notifyMaxCount(int count); + + /** + * Called when the configuration of the maximum age of history-entries + * changed. Called via DBUS by some config-module + */ + void notifyMaxAge(int days); + + /** + * Clears the history completely. Called via DBUS by some config-module + */ + void notifyClear(); + + /** + * Notifes about a url that has to be removed from the history. + * The sender instance has to save the history. + */ + void notifyRemove(const QString &url); + + /** + * Notifes about a list of urls that has to be removed from the history. + * The sender instance has to save the history. + */ + void notifyRemoveList(const QStringList &urls); + +private Q_SLOTS: // connected to DBUS signals + void slotNotifyHistoryEntry(const QByteArray &historyEntry); + void slotNotifyMaxCount(int count); + void slotNotifyMaxAge(int days); + void slotNotifyClear(); + void slotNotifyRemove(const QString &url); + void slotNotifyRemoveList(const QStringList &urls); + +public: + KSharedConfig::Ptr konqConfig() + { + // We want to use konquerorrc even when this class isn't used in konqueror, + // this is why this doesn't say KSharedConfig::openConfig(). + return KSharedConfig::openConfig(QStringLiteral("konquerorrc")); + } + + KonqHistoryList m_history; + int m_maxCount; // maximum of history entries + int m_maxAgeDays; // maximum age of a history entry + KonqHistoryProvider *q; +}; + +KonqHistoryProviderPrivate::KonqHistoryProviderPrivate(KonqHistoryProvider *qq) + : QObject(), QDBusContext(), q(qq) +{ + // defaults + KConfigGroup cs(konqConfig(), "HistorySettings"); + m_maxCount = cs.readEntry("Maximum of History entries", 500); + m_maxCount = qMax(1, m_maxCount); + m_maxAgeDays = cs.readEntry("Maximum age of History entries", 90); + + const QString dbusPath = QStringLiteral("/KonqHistoryManager"); + const QString dbusInterface = QStringLiteral("org.kde.Konqueror.HistoryManager"); + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject(dbusPath, this, QDBusConnection::ExportAllSignals); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyClear"), this, SLOT(slotNotifyClear())); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyHistoryEntry"), this, SLOT(slotNotifyHistoryEntry(QByteArray))); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyMaxAge"), this, SLOT(slotNotifyMaxAge(int))); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyMaxCount"), this, SLOT(slotNotifyMaxCount(int))); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyRemove"), this, SLOT(slotNotifyRemove(QString))); + dbus.connect(QString(), dbusPath, dbusInterface, QStringLiteral("notifyRemoveList"), this, SLOT(slotNotifyRemoveList(QStringList))); +} + +//// + +KonqHistoryProvider::KonqHistoryProvider(QObject *parent) + : KParts::HistoryProvider(parent), d(new KonqHistoryProviderPrivate(this)) +{ +} + +KonqHistoryProvider::~KonqHistoryProvider() +{ + delete d; +} + +const KonqHistoryList &KonqHistoryProvider::entries() const +{ + return d->m_history; +} + +bool KonqHistoryProvider::loadHistory() +{ + KonqHistoryLoader loader; + if (!loader.loadHistory()) { + return false; + } + + d->m_history = loader.entries(); + + d->adjustSize(); + + QListIterator it(d->m_history); + while (it.hasNext()) { + const KonqHistoryEntry &entry = it.next(); + + // Fill the entries into KParts::HistoryProvider. + const QString urlString = entry.url.url(); + KParts::HistoryProvider::insert(urlString); + // DF: also insert the "pretty" version if different + // This helps getting 'visited' links on websites which don't use fully-escaped urls. + const QString prettyUrlString = entry.url.toDisplayString(); + if (urlString != prettyUrlString) { + KParts::HistoryProvider::insert(prettyUrlString); + } + } + + return true; +} + +void KonqHistoryProviderPrivate::adjustSize() +{ + if (m_history.isEmpty()) { + return; + } + + KonqHistoryEntry entry = m_history.first(); + const QDateTime expirationDate(QDate::currentDate().addDays(-m_maxAgeDays)); + + while (m_history.count() > qint32(m_maxCount) || + (m_maxAgeDays > 0 && entry.lastVisited.isValid() && entry.lastVisited < expirationDate)) { // i.e. entry is expired + q->removeEntry(m_history.begin()); + + if (m_history.isEmpty()) { + break; + } + entry = m_history.first(); + } +} + +static QString dbusService() +{ + return QDBusConnection::sessionBus().baseService(); +} + +void KonqHistoryProvider::emitAddToHistory(const KonqHistoryEntry &entry) +{ + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + entry.save(stream, KonqHistoryEntry::MarshalUrlAsStrings); + stream << dbusService(); + // Protection against very long urls (like data:) + if (data.size() > 4096) { + return; + } + emit d->notifyHistoryEntry(data); +} + +void KonqHistoryProvider::emitRemoveFromHistory(const QUrl &url) +{ + emit d->notifyRemove(url.url()); +} + +void KonqHistoryProvider::emitRemoveListFromHistory(const QList &urls) +{ + QStringList result; + foreach (const QUrl &url, urls) { + result << url.url(); + } + emit d->notifyRemoveList(result); +} + +void KonqHistoryProvider::emitClear() +{ + emit d->notifyClear(); +} + +void KonqHistoryProvider::emitSetMaxCount(int count) +{ + emit d->notifyMaxCount(count); +} + +void KonqHistoryProvider::emitSetMaxAge(int days) +{ + emit d->notifyMaxAge(days); +} + +/** + * Returns whether the D-Bus call we are handling was a call from us self + */ +static bool isSenderOfSignal(const QDBusMessage &msg) +{ + return dbusService() == msg.service(); +} + +void KonqHistoryProviderPrivate::slotNotifyHistoryEntry(const QByteArray &data) +{ + KonqHistoryEntry e; + QDataStream stream(const_cast(&data), QIODevice::ReadOnly); + + //This is important - we need to switch to a consistent marshalling format for + //communicating between different konqueror instances. Since during an upgrade + //some "old" copies may still running, we use the old format for the DBUS transfers. + //This doesn't make that much difference performance-wise for single entries anyway. + e.load(stream, KonqHistoryEntry::MarshalUrlAsStrings); + //kDebug(1202) << "Got new entry from Broadcast:" << e.url; + + KonqHistoryList::iterator existingEntry = q->findEntry(e.url); + QString urlString = e.url.url(); + const bool newEntry = existingEntry == m_history.end(); + + KonqHistoryEntry entry; + + if (!newEntry) { + entry = *existingEntry; + } else { // create a new history entry + entry.url = e.url; + entry.firstVisited = e.firstVisited; + entry.numberOfTimesVisited = 0; // will get set to 1 below + q->KParts::HistoryProvider::insert(urlString); + } + + if (!e.typedUrl.isEmpty()) { + entry.typedUrl = e.typedUrl; + } + if (!e.title.isEmpty()) { + entry.title = e.title; + } + entry.numberOfTimesVisited += e.numberOfTimesVisited; + entry.lastVisited = e.lastVisited; + + if (newEntry) { + m_history.append(entry); + } else { + *existingEntry = entry; + } + + adjustSize(); + + q->finishAddingEntry(entry, isSenderOfSignal(message())); + + emit q->entryAdded(entry); +} + +void KonqHistoryProviderPrivate::slotNotifyMaxCount(int count) +{ + m_maxCount = count; + // TODO clearPending(); + adjustSize(); + + KConfigGroup cs(konqConfig(), "HistorySettings"); + cs.writeEntry("Maximum of History entries", m_maxCount); + + if (isSenderOfSignal(message())) { + saveHistory(); + cs.sync(); + } +} + +void KonqHistoryProviderPrivate::slotNotifyMaxAge(int days) +{ + m_maxAgeDays = days; + // TODO clearPending(); + adjustSize(); + + KConfigGroup cs(konqConfig(), "HistorySettings"); + cs.writeEntry("Maximum age of History entries", m_maxAgeDays); + + if (isSenderOfSignal(message())) { + saveHistory(); + cs.sync(); + } +} + +void KonqHistoryProviderPrivate::slotNotifyClear() +{ + m_history.clear(); + + if (isSenderOfSignal(message())) { + saveHistory(); + } + + q->KParts::HistoryProvider::clear(); // also emits the cleared() signal +} + +void KonqHistoryProviderPrivate::slotNotifyRemove(const QString &urlStr) +{ + QUrl url(urlStr); + + KonqHistoryList::iterator existingEntry = q->findEntry(url); + if (existingEntry != m_history.end()) { + q->removeEntry(existingEntry); + if (isSenderOfSignal(message())) { + saveHistory(); + } + } +} + +void KonqHistoryProviderPrivate::slotNotifyRemoveList(const QStringList &urls) +{ + bool doSave = false; + QStringList::const_iterator it = urls.begin(); + for (; it != urls.end(); ++it) { + QUrl url(*it); + KonqHistoryList::iterator existingEntry = m_history.findEntry(url); + if (existingEntry != m_history.end()) { + q->removeEntry(existingEntry); + doSave = true; + } + } + + if (doSave && isSenderOfSignal(message())) { + saveHistory(); + } +} + +void KonqHistoryProvider::removeEntry(KonqHistoryList::iterator existingEntry) +{ + const KonqHistoryEntry entry = *existingEntry; // make copy, due to erase call below + const QString urlString = entry.url.url(); + + KParts::HistoryProvider::remove(urlString); + + d->m_history.erase(existingEntry); + emit entryRemoved(entry); +} + +int KonqHistoryProvider::maxCount() const +{ + return d->m_maxCount; +} + +int KonqHistoryProvider::maxAge() const +{ + return d->m_maxAgeDays; +} + +bool KonqHistoryProviderPrivate::saveHistory() +{ + const QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/konqueror"); + QDir().mkpath(dir); + const QString filename = dir + QLatin1String("/konq_history"); + QSaveFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + qWarning() << "Can't open" << file.fileName() << "for saving history"; + return false; + } + + QDataStream fileStream(&file); + fileStream << KonqHistoryLoader::historyVersion(); + + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + QListIterator it(m_history); + while (it.hasNext()) { + //We use QUrl for marshalling URLs in entries in the V4 + //file format + it.next().save(stream, KonqHistoryEntry::NoFlags); + } + + quint32 crc = crc32(0, reinterpret_cast(data.data()), data.size()); + fileStream << crc << data; + + return file.commit(); +} + +KonqHistoryList::iterator KonqHistoryProvider::findEntry(const QUrl &url) +{ + // small optimization (dict lookup) for items _not_ in our history + if (!KParts::HistoryProvider::contains(url.url())) { + return d->m_history.end(); + } + return d->m_history.findEntry(url); +} + +KonqHistoryList::const_iterator KonqHistoryProvider::constFindEntry(const QUrl &url) const +{ + // small optimization (dict lookup) for items _not_ in our history + if (!KParts::HistoryProvider::contains(url.url())) { + return d->m_history.constEnd(); + } + return d->m_history.constFindEntry(url); +} + +void KonqHistoryProvider::finishAddingEntry(const KonqHistoryEntry &entry, bool isSender) +{ + Q_UNUSED(entry); // this arg is used by konq's reimplementation + if (isSender) { + // we are the sender of the broadcast, so we save + d->saveHistory(); + } +} + +#include "konq_historyprovider.moc" + diff --git a/libkonq/src/konq_historyprovider.h b/libkonq/src/konq_historyprovider.h new file mode 100644 index 0000000..c7f6b5f --- /dev/null +++ b/libkonq/src/konq_historyprovider.h @@ -0,0 +1,160 @@ +/* This file is part of the KDE project + Copyright 2000,2001 Carsten Pfeiffer + Copyright 2007-2009 David Faure + + 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 ) version 3 or, at the discretion of KDE e.V. + ( which shall act as a proxy as in section 14 of the GPLv3 ), 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 KONQ_HISTORYPROVIDER_H +#define KONQ_HISTORYPROVIDER_H + +#include +#include +#include "libkonq_export.h" +#include "konq_historyentry.h" + +class KonqHistoryEntry; +class KonqHistoryList; +class KonqHistoryProviderPrivate; + +/** + * This class maintains and manages a history of all URLs visited by Konqueror. + * It synchronizes the history with other KonqHistoryProvider instances in + * other processes (konqueror, history list, krunner etc.) via D-Bus to keep + * one global and persistent history. + */ +class LIBKONQ_EXPORT KonqHistoryProvider : public KParts::HistoryProvider +{ + Q_OBJECT + +public: + /** + * Returns the KonqHistoryProvider instance. This relies on a KonqHistoryProvider + * instance being created first! + * This is a bit like "qApp": you can access the instance anywhere, but you need to + * create it first. + */ + static KonqHistoryProvider *self() + { + return static_cast(KParts::HistoryProvider::self()); + } + + explicit KonqHistoryProvider(QObject *parent = nullptr); + ~KonqHistoryProvider() override; + + /** + * @returns the list of all history entries, sorted by date + * (oldest entries first) + */ + const KonqHistoryList &entries() const; + + /** + * @returns the current maximum number of history entries. + */ + int maxCount() const; + + /** + * @returns the current maximum age (in days) of history entries. + */ + int maxAge() const; + + /** + * Sets a new maximum size of history and truncates the current history + * if necessary. Notifies all other Konqueror instances via D-Bus + * to do the same. + * + * The history is saved after receiving the D-Bus call. + */ + void emitSetMaxCount(int count); + + /** + * Sets a new maximum age of history entries and removes all entries that + * are older than @p days. Notifies all other Konqueror instances via D-Bus + * to do the same. + * + * An age of 0 means no expiry based on the age. + * + * The history is saved after receiving the D-Bus call. + */ + void emitSetMaxAge(int days); + + /** + * Removes the history entry for @p url, if existent. Tells all other + * Konqueror instances via D-Bus to do the same. + * + * The history is saved after receiving the D-Bus call. + */ + void emitRemoveFromHistory(const QUrl &url); + + /** + * Removes the history entries for the given list of @p urls. Tells all + * other Konqueror instances via D-Bus to do the same. + * + * The history is saved after receiving the D-Bus call. + */ + void emitRemoveListFromHistory(const QList &urls); + + /** + * Clears the history and tells all other Konqueror instances via D-Bus + * to do the same. + * The history is saved afterwards, if necessary. + */ + void emitClear(); + + /** + * Load the whole history from disk. Call this exactly once. + */ + bool loadHistory(); + +Q_SIGNALS: + /** + * Emitted after a new entry was added + */ + void entryAdded(const KonqHistoryEntry &entry); + + /** + * Emitted after an entry was removed from the history + * Note, that this entry will be deleted immediately after you got + * that signal. + */ + void entryRemoved(const KonqHistoryEntry &entry); + +protected: // only to be used by konqueror's KonqHistoryManager + + virtual void finishAddingEntry(const KonqHistoryEntry &entry, bool isSender); + virtual void removeEntry(KonqHistoryList::iterator it); + + /** + * a little optimization for KonqHistoryList::findEntry(), + * checking the dict of KParts::HistoryProvider before traversing the list. + * Can't be used everywhere, because it always returns end() for "pending" + * entries, as those are not added to the dict, currently. + */ + KonqHistoryList::iterator findEntry(const QUrl &url); + KonqHistoryList::const_iterator constFindEntry(const QUrl &url) const; + + /** + * Notifies all running instances about a new HistoryEntry via D-Bus. + */ + void emitAddToHistory(const KonqHistoryEntry &entry); + +private: + KonqHistoryProviderPrivate *const d; + friend class KonqHistoryProviderPrivate; +}; + +#endif /* KONQ_HISTORYPROVIDER_H */ diff --git a/libkonq/src/konq_popupmenu.cpp b/libkonq/src/konq_popupmenu.cpp new file mode 100644 index 0000000..0f78dda --- /dev/null +++ b/libkonq/src/konq_popupmenu.cpp @@ -0,0 +1,560 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2008 David Faure + Copyright (C) 2001 Holger Freyther + + 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. +*/ + +#include "konq_popupmenu.h" + +#include + +#include +#include "kfileitemactions.h" +#include "kabstractfileitemactionplugin.h" +#include "kpropertiesdialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + Test cases: + iconview file: background + iconview file: file (with and without servicemenus) + iconview file: directory + iconview remote protocol (e.g. ftp: or fish:) + iconview trash:/ + sidebar directory tree + sidebar Devices / Hard Disc + khtml background + khtml link + khtml image (www.kde.org RMB on K logo) + khtmlimage (same as above, then choose View image, then RMB) + selected text in khtml + embedded katepart + folder on the desktop + trash link on the desktop + trashed file or directory + application .desktop file + Then the same after uninstalling kdeaddons/konq-plugins (arkplugin in particular) +*/ + +class KonqPopupMenuPrivate +{ +public: + KonqPopupMenuPrivate(KonqPopupMenu *qq, KActionCollection &actions, QWidget *parentWidget) + : q(qq), + m_parentWidget(parentWidget), + m_popupFlags(KonqPopupMenu::DefaultPopupItems), + m_pMenuNew(nullptr), + m_copyToMenu(parentWidget), + m_bookmarkManager(nullptr), + m_actions(actions) + { + } + + ~KonqPopupMenuPrivate() + { + qDeleteAll(m_ownActions); + } + + void addNamedAction(const char *name); + void addGroup(KonqPopupMenu::ActionGroup group); + void populate(); + void aboutToShow(); + + void slotPopupNewDir(); + void slotPopupNewView(); + void slotPopupEmptyTrashBin(); + void slotConfigTrashBin(); + void slotPopupRestoreTrashedItems(); + void slotPopupAddToBookmark(); + void slotPopupMimeType(); + void slotPopupProperties(); + void slotShowOriginalFile(); + + KonqPopupMenu *q; + QWidget *m_parentWidget; + QString m_urlTitle; + KonqPopupMenu::Flags m_popupFlags; + KNewFileMenu *m_pMenuNew; + QUrl m_sViewURL; + KFileItemListProperties m_popupItemProperties; + KFileItemActions m_menuActions; + KFileCopyToMenu m_copyToMenu; + KBookmarkManager *m_bookmarkManager; + KActionCollection &m_actions; + QList m_ownActions; + KonqPopupMenu::ActionGroupMap m_actionGroups; +}; + +////////////////// + +KonqPopupMenu::KonqPopupMenu(const KFileItemList &items, + const QUrl &viewURL, + KActionCollection &actions, + Flags popupFlags, + QWidget *parentWidget) + : QMenu(parentWidget), + d(new KonqPopupMenuPrivate(this, actions, parentWidget)) +{ + d->m_sViewURL = viewURL; + d->m_popupItemProperties.setItems(items); + d->m_menuActions.setParentWidget(parentWidget); + d->m_popupFlags = popupFlags; + + connect(this, &QMenu::aboutToShow, this, [this]() { d->aboutToShow(); }); +} + +void KonqPopupMenuPrivate::addNamedAction(const char *name) +{ + QAction *act = m_actions.action(QString::fromLatin1(name)); + if (act) { + q->addAction(act); + } +} + +void KonqPopupMenuPrivate::aboutToShow() +{ + populate(); + KAcceleratorManager::manage(q); +} + +void KonqPopupMenuPrivate::populate() +{ + Q_ASSERT(m_popupItemProperties.items().count() >= 1); + + bool bTrashIncluded = false; + + const KFileItemList lstItems = m_popupItemProperties.items(); + QList lstUrls; + lstUrls.reserve(lstItems.count()); + for (const KFileItem &item : lstItems) { + const QUrl url = item.url(); + lstUrls.append(url); + if (!bTrashIncluded && ((url.scheme() == QLatin1String("trash") && url.path().length() <= 1))) { + bTrashIncluded = true; + } + } + + const bool isDirectory = m_popupItemProperties.isDirectory(); + const bool sReading = m_popupItemProperties.supportsReading(); + bool sDeleting = (m_popupFlags & KonqPopupMenu::NoDeletion) == 0 + && m_popupItemProperties.supportsDeleting(); + const bool sWriting = m_popupItemProperties.supportsWriting(); + const bool sMoving = sDeleting && m_popupItemProperties.supportsMoving(); + + QUrl url = m_sViewURL.adjusted(QUrl::NormalizePathSegments); + + bool isTrashLink = false; + bool isCurrentTrash = false; + bool currentDir = false; + bool isSymLink = false; + bool isSymLinkInSameDir = false; // true for "ln -s foo bar", false for links to foo/sub or /foo + + //check if url is current directory + if (lstItems.count() == 1) { + KFileItem firstPopupItem(lstItems.first()); + if (firstPopupItem.isLink()) { + isSymLink = true; + isSymLinkInSameDir = !firstPopupItem.linkDest().contains(QLatin1Char('/')); + } + QUrl firstPopupURL(firstPopupItem.url().adjusted(QUrl::NormalizePathSegments)); + //kDebug(1203) << "View path is " << url.url(); + //kDebug(1203) << "First popup path is " << firstPopupURL.url(); + currentDir = (firstPopupURL.matches(url, QUrl::StripTrailingSlash)); + if (firstPopupItem.isDesktopFile()) { + KDesktopFile desktopFile(firstPopupItem.localPath()); + const KConfigGroup cfg = desktopFile.desktopGroup(); + isTrashLink = cfg.readEntry("Type") == QLatin1String("Link") + && cfg.readEntry("URL") == QLatin1String("trash:/"); + } + + if (isTrashLink) { + sDeleting = false; + } + + // isCurrentTrash: popup on trash:/ itself, or on the trash.desktop link + isCurrentTrash = (firstPopupURL.scheme() == QLatin1String("trash") && firstPopupURL.path().length() <= 1) + || isTrashLink; + } + + const bool isIntoTrash = (url.scheme() == QLatin1String("trash")) && !isCurrentTrash; // trashed file, not trash:/ itself + + const bool bIsLink = (m_popupFlags & KonqPopupMenu::IsLink); + + //kDebug() << "isLocal=" << isLocal << " url=" << url << " isCurrentTrash=" << isCurrentTrash << " isIntoTrash=" << isIntoTrash << " bTrashIncluded=" << bTrashIncluded; + + ////////////////////////////////////////////////////////////////////////// + + addGroup(KonqPopupMenu::TopActions); // used e.g. for ShowMenuBar. includes a separator at the end + + QAction *act; + + QAction *actNewWindow = nullptr; + +#if 0 // TODO in the desktop code itself. + if ((flags & KonqPopupMenu::ShowProperties) && isOnDesktop && + !KAuthorized::authorizeAction("editable_desktop_icons")) { + flags &= ~KonqPopupMenu::ShowProperties; // remove flag + } +#endif + + // Either 'newview' is in the actions we're given (probably in the tabhandling group) + // or we need to insert it ourselves (e.g. for the desktop). + // In the first case, actNewWindow must remain 0. + if (((m_popupFlags & KonqPopupMenu::ShowNewWindow) != 0) && sReading) { + const QString openStr = i18n("&Open"); + actNewWindow = new QAction(m_parentWidget /*for status tips*/); + m_ownActions.append(actNewWindow); + actNewWindow->setIcon(QIcon::fromTheme(QStringLiteral("window-new"))); + actNewWindow->setText(openStr); + QObject::connect(actNewWindow, &QAction::triggered, [this]() { + slotPopupNewView(); + }); + } + + if (isDirectory && sWriting && !isCurrentTrash) { // A dir, and we can create things into it + const bool mkdirRequested = m_popupFlags & KonqPopupMenu::ShowCreateDirectory; + if ((currentDir || mkdirRequested) && m_pMenuNew) { // Current dir -> add the "new" menu + // As requested by KNewFileMenu : + m_pMenuNew->checkUpToDate(); + m_pMenuNew->setPopupFiles(m_popupItemProperties.urlList()); + + q->addAction(m_pMenuNew); + q->addSeparator(); + } else if (mkdirRequested) { + QAction *actNewDir = new QAction(m_parentWidget); + m_ownActions.append(actNewDir); + actNewDir->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); + actNewDir->setText(i18n("Create &Folder...")); + QObject::connect(actNewDir, &QAction::triggered, [this]() { + slotPopupNewDir(); + }); + q->addAction(actNewDir); + q->addSeparator(); + } + } else if (isIntoTrash) { + // Trashed item, offer restoring + act = new QAction(m_parentWidget /*for status tips*/); + m_ownActions.append(act); + act->setText(i18n("&Restore")); + //PORT QT5 act->setHelpText(i18n("Restores this file or directory, back to the location where it was deleted from initially")); + QObject::connect(act, &QAction::triggered, [this]() { + slotPopupRestoreTrashedItems(); + }); + q->addAction(act); + } + + if (!currentDir && isSymLink && !isSymLinkInSameDir) { + // #65151: offer to open the target's parent dir + act = new QAction(m_parentWidget); + m_ownActions.append(act); + act->setText(isDirectory ? i18n("Show Original Directory") : i18n("Show Original File")); + //PORT TO QT5 act->setHelpText(i18n("Opens a new file manager window showing the target of this link, in its parent directory.")); + QObject::connect(act, &QAction::triggered, [this]() { + slotShowOriginalFile(); + }); + q->addAction(act); + } + + // "open in new window" is either provided by us, or by the tabhandling group + if (actNewWindow) { + q->addAction(actNewWindow); + q->addSeparator(); + } + addGroup(KonqPopupMenu::TabHandlingActions); // includes a separator at the end + + if (m_popupFlags & KonqPopupMenu::ShowUrlOperations) { + if (!currentDir && sReading) { + if (sDeleting) { + addNamedAction("cut"); + } + addNamedAction("copy"); + } + + if (isDirectory && sWriting) { + if (currentDir) { + addNamedAction("paste"); + } else { + addNamedAction("pasteto"); + } + } + } + if (isCurrentTrash) { + act = new QAction(m_parentWidget); + m_ownActions.append(act); + act->setIcon(QIcon::fromTheme(QStringLiteral("trash-empty"))); + act->setText(i18n("&Empty Trash Bin")); + KConfig trashConfig(QStringLiteral("trashrc"), KConfig::SimpleConfig); + act->setEnabled(!trashConfig.group("Status").readEntry("Empty", true)); + QObject::connect(act, &QAction::triggered, [this]() { + slotPopupEmptyTrashBin(); + }); + q->addAction(act); + } + if (isCurrentTrash) { + act = new QAction(m_parentWidget); + m_ownActions.append(act); + act->setIcon(QIcon::fromTheme(QStringLiteral("trash-empty"))); + act->setText(i18n("&Configure Trash Bin")); + QObject::connect(act, &QAction::triggered, [this]() { + slotConfigTrashBin(); + }); + q->addAction(act); + } + + // This is used by KHTML, see khtml_popupmenu.rc (copy, selectAll, searchProvider etc.) + // and by DolphinPart (rename, trash, delete) + addGroup(KonqPopupMenu::EditActions); + + if (m_popupFlags & KonqPopupMenu::ShowTextSelectionItems) { + // OK, we have to stop here. + + // Anything else that is provided by the part + addGroup(KonqPopupMenu::CustomActions); + return; + } + + if (!isCurrentTrash && !isIntoTrash && (m_popupFlags & KonqPopupMenu::ShowBookmark)) { + QString caption; + if (currentDir) { + const bool httpPage = m_sViewURL.scheme().startsWith(QLatin1String("http"), Qt::CaseInsensitive); + if (httpPage) { + caption = i18n("&Bookmark This Page"); + } else { + caption = i18n("&Bookmark This Location"); + } + } else if (isDirectory) { + caption = i18n("&Bookmark This Folder"); + } else if (bIsLink) { + caption = i18n("&Bookmark This Link"); + } else { + caption = i18n("&Bookmark This File"); + } + + act = new QAction(m_parentWidget); + m_ownActions.append(act); + act->setObjectName(QStringLiteral("bookmark_add")); // for unittest + act->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new"))); + act->setText(caption); + QObject::connect(act, &QAction::triggered, [this]() { + slotPopupAddToBookmark(); + }); + if (lstItems.count() > 1) { + act->setEnabled(false); + } + if (KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { + q->addAction(act); + } + if (bIsLink) { + addGroup(KonqPopupMenu::LinkActions); // see khtml + } + } + + // "Open With" actions + + m_menuActions.setItemListProperties(m_popupItemProperties); + + if (sReading) { + m_menuActions.addOpenWithActionsTo(q, QStringLiteral("DesktopEntryName != 'kfmclient' and DesktopEntryName != 'kfmclient_dir' and DesktopEntryName != 'kfmclient_html'")); + + QList previewActions = m_actionGroups.value(KonqPopupMenu::PreviewActions); + if (!previewActions.isEmpty()) { + if (previewActions.count() == 1) { + q->addAction(previewActions.first()); + } else { + QMenu *subMenu = new QMenu(i18n("Preview In"), q); + subMenu->menuAction()->setObjectName(QStringLiteral("preview_submenu")); // for the unittest + q->addMenu(subMenu); + subMenu->addActions(previewActions); + } + } + } + + // Second block, builtin + user + m_menuActions.addServiceActionsTo(q); + + q->addSeparator(); + + // Use the Dolphin setting for showing the "Copy To" and "Move To" actions + KSharedConfig::Ptr dolphin = KSharedConfig::openConfig(QStringLiteral("dolphinrc")); + + // CopyTo/MoveTo menus + if (m_popupFlags & KonqPopupMenu::ShowUrlOperations && + KConfigGroup(dolphin, "General").readEntry("ShowCopyMoveMenu", false)) { + + m_copyToMenu.setUrls(lstUrls); + m_copyToMenu.setReadOnly(sMoving == false); + m_copyToMenu.addActionsTo(q); + q->addSeparator(); + } + + if (!isCurrentTrash && !isIntoTrash && sReading && + (m_popupFlags & KonqPopupMenu::NoPlugins) == 0) { + m_menuActions.addPluginActionsTo(q); + } + + if ((m_popupFlags & KonqPopupMenu::ShowProperties) && KPropertiesDialog::canDisplay(lstItems)) { + act = new QAction(m_parentWidget); + m_ownActions.append(act); + act->setObjectName(QStringLiteral("properties")); // for unittest + act->setText(i18n("&Properties")); + QObject::connect(act, &QAction::triggered, [this]() { + slotPopupProperties(); + }); + q->addAction(act); + } + + while (!q->actions().isEmpty() && + q->actions().last()->isSeparator()) { + delete q->actions().last(); + } + + // Anything else that is provided by the part + addGroup(KonqPopupMenu::CustomActions); + + QObject::connect(&m_menuActions, &KFileItemActions::openWithDialogAboutToBeShown, q, &KonqPopupMenu::openWithDialogAboutToBeShown); +} + +KonqPopupMenu::~KonqPopupMenu() +{ + delete d; + //kDebug(1203) << "~KonqPopupMenu leave"; +} + +void KonqPopupMenu::setNewFileMenu(KNewFileMenu *newMenu) +{ + d->m_pMenuNew = newMenu; +} + +void KonqPopupMenu::setBookmarkManager(KBookmarkManager *manager) +{ + d->m_bookmarkManager = manager; +} + +void KonqPopupMenu::setActionGroups(const KonqPopupMenu::ActionGroupMap &actionGroups) +{ + d->m_actionGroups = actionGroups; +} + +void KonqPopupMenu::setURLTitle(const QString &urlTitle) +{ + d->m_urlTitle = urlTitle; +} + +void KonqPopupMenuPrivate::slotPopupNewView() +{ + Q_FOREACH (const QUrl &url, m_popupItemProperties.urlList()) { + (void) new KRun(url, m_parentWidget); + } +} + +void KonqPopupMenuPrivate::slotPopupNewDir() +{ + m_pMenuNew->createDirectory(); +} + +void KonqPopupMenuPrivate::slotPopupEmptyTrashBin() +{ + KIO::JobUiDelegate uiDelegate; + uiDelegate.setWindow(m_parentWidget); + if (uiDelegate.askDeleteConfirmation(QList(), KIO::JobUiDelegate::EmptyTrash, KIO::JobUiDelegate::DefaultConfirmation)) { + KIO::Job *job = KIO::emptyTrash(); + KJobWidgets::setWindow(job, m_parentWidget); + job->uiDelegate()->setAutoErrorHandlingEnabled(true); // or connect to the result signal + } +} + +void KonqPopupMenuPrivate::slotConfigTrashBin() +{ + KRun::run(QStringLiteral("kcmshell5 kcmtrash"), QList(), m_parentWidget); +} + +void KonqPopupMenuPrivate::slotPopupRestoreTrashedItems() +{ + KIO::RestoreJob *job = KIO::restoreFromTrash(m_popupItemProperties.urlList()); + KJobWidgets::setWindow(job, m_parentWidget); + job->uiDelegate()->setAutoErrorHandlingEnabled(true); +} + +void KonqPopupMenuPrivate::slotPopupAddToBookmark() +{ + KBookmarkGroup root; + if (m_popupItemProperties.urlList().count() == 1) { + const QUrl url = m_popupItemProperties.urlList().first(); + const QString title = m_urlTitle.isEmpty() ? url.toDisplayString() : m_urlTitle; + KBookmarkDialog dlg(m_bookmarkManager, m_parentWidget); + dlg.addBookmark(title, url, QString()); + } else { + root = m_bookmarkManager->root(); + Q_FOREACH (const QUrl &url, m_popupItemProperties.urlList()) { + root.addBookmark(url.toDisplayString(), url, QString()); + } + m_bookmarkManager->emitChanged(root); + } +} + +void KonqPopupMenuPrivate::slotPopupMimeType() +{ + KMimeTypeEditor::editMimeType(m_popupItemProperties.mimeType(), m_parentWidget); +} + +void KonqPopupMenuPrivate::slotPopupProperties() +{ + KPropertiesDialog::showDialog(m_popupItemProperties.items(), m_parentWidget, false); +} + +void KonqPopupMenuPrivate::addGroup(KonqPopupMenu::ActionGroup group) +{ + q->addActions(m_actionGroups.value(group)); +} + +void KonqPopupMenuPrivate::slotShowOriginalFile() +{ + const KFileItem item = m_popupItemProperties.items().first(); + QUrl destUrl = QUrl::fromLocalFile(item.linkDest()); + + if (!destUrl.isValid()) { + return; + } + + // Now destUrl points to the target file, let's go up to parent dir + destUrl = destUrl.adjusted(QUrl::RemoveFilename); + KRun::runUrl(destUrl, QStringLiteral("inode/directory"), m_parentWidget, KRun::RunFlags()); +} diff --git a/libkonq/src/konq_popupmenu.h b/libkonq/src/konq_popupmenu.h new file mode 100644 index 0000000..ccb2313 --- /dev/null +++ b/libkonq/src/konq_popupmenu.h @@ -0,0 +1,144 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2016 David Faure + Copyright (C) 2001 Holger Freyther + + 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 __konqpopupmenu_h +#define __konqpopupmenu_h + +#include + +#include + +class KFileItemList; +class KNewFileMenu; + +class KActionCollection; +class KBookmarkManager; +class KonqPopupMenuPrivate; +class QUrl; + +/** + * This class implements the popup menu for URLs in file managers. + * + * The recommended usage is to use QMenu::popup() to avoid modal popupmenus. + * + * Either reuse the instance, or delete it after use with + * connect(menu, &QMenu::aboutToHide, [menu]() { menu->deleteLater(); }); + * + * Users of KonqPopupMenu include: konqueror, kfind, the folderview desktop plasmoid. + */ +class LIBKONQ_EXPORT KonqPopupMenu : public QMenu +{ + Q_OBJECT +public: + + /** + * Each action group is inserted into the context menu at a specific position. + * "editactions" for actions related text editing, + * "linkactions" for actions related to hyperlinks, + * "partactions" for any other actions provided by the part + */ + enum ActionGroup { + TopActions, ///< actions to be shown at the top of the context menu, like "show menu bar" + TabHandlingActions, ///< actions for tab handling, like "open in new tab" + EditActions, ///< move to trash, delete, etc. + PreviewActions, ///< actions related to viewing the selected file with an embedded viewer + CustomActions, ///< group for more custom actions, such as those provided by KParts components + LinkActions ///< actions related to handling of hyperlinks, only shown if the IsLink flag is set + }; + + typedef QMap > ActionGroupMap; + + /** + * Set of flags to ask for some items in the popup menu. + */ + enum Flag { + DefaultPopupItems = 0x0000, ///< default value, no additional menu item + ShowBookmark = 0x0008, ///< show "add to bookmarks" (usually not done on the local filesystem) + ShowCreateDirectory = 0x0010, ///< show "create directory" (usually only done on the background of the view, or + /// in hierarchical views like directory trees, where the new dir would be visible) + ShowTextSelectionItems = 0x0020, ///< set when selecting text, for a popup that only contains text-related items. + NoDeletion = 0x0040, ///< "cut" not allowed (e.g. parent dir not writeable). + /// (this is only needed if the protocol itself supports deletion, unlike e.g. HTTP) + IsLink = 0x0080, ///< show "Bookmark This Link" and other link-related actions (LinkActions group) + ShowUrlOperations = 0x0100, ///< show copy, paste, as well as cut if NoDeletion is not set. + ShowProperties = 0x0200, ///< show "Properties" action (usually done by directory views) + ShowNewWindow = 0x0400, ///< Show "Open in new window" action + NoPlugins = 0x0800 ///< Disable plugins - mostly for the unittest + }; + Q_DECLARE_FLAGS(Flags, Flag) + + /** + * Constructor + * @param items the list of file items the popupmenu should be shown for + * @param viewURL the URL shown in the view, to test for RMB click on view background + * @param actions list of actions the caller wants to see in the menu + * @param flags flags which control which items to show in the popupmenu + * @param parentWidget the widget we're showing this popup for. Helps destroying + * the popup if the widget is destroyed before the popup. + * + * The actions to pass in the action collection are : + * reload, cut, copy, paste, pasteto + * The others items are automatically inserted. + */ + KonqPopupMenu(const KFileItemList &items, + const QUrl &viewURL, + KActionCollection &actions, + Flags flags, + QWidget *parentWidget = nullptr); + + /** + * Don't forget to destroy the object + */ + ~KonqPopupMenu() override; + + /** + * Sets the "New file" menu instance. This allows to share it with the menubar. + */ + void setNewFileMenu(KNewFileMenu *newMenu); + + /** + * Sets the bookmark manager for the "add to bookmark" action. + * Only used if ShowBookmark is set + */ + void setBookmarkManager(KBookmarkManager *manager); + + /** + * Sets the additional actions to show in the context menu + */ + void setActionGroups(const ActionGroupMap &actionGroups); + + /** + * Set the title of the URL, when the popupmenu is opened for a single URL. + * This is used if the user chooses to add a bookmark for this URL. + */ + void setURLTitle(const QString &urlTitle); + +Q_SIGNALS: + /** + * Emitted before the "Open With" dialog is shown + * This is used e.g in folderview to close the folder peek popups on invoking the "Open With" menu action + */ + void openWithDialogAboutToBeShown(); + +private: + KonqPopupMenuPrivate *d; +}; + +#endif diff --git a/org.kde.konqueror.appdata.xml b/org.kde.konqueror.appdata.xml new file mode 100644 index 0000000..678ca35 --- /dev/null +++ b/org.kde.konqueror.appdata.xml @@ -0,0 +1,427 @@ + + + org.kde.konqueror.desktop + CC0-1.0 + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + ਕੋਨਕਿਊਰੋਰ + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + Konqueror + К‑освајач + K‑osvajač + К‑освајач + K‑osvajač + Konqueror + Konqueror + Konqueror + xxKonquerorxx + Konqueror + 瀏覽器_Konqueror +