From 88ae0b60b81325b838aae2c48b790b81f810b903 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Mon, 31 Mar 2014 03:48:38 +0200 Subject: [PATCH] Initial import from the monolithic kde-workspace. This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the techbase wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://community.kde.org/Frameworks/GitOldHistory If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo kde-workspace, frameworks branch, at commit 049113e719dd2fc4446d054fa1a3aada330094f0 --- CMakeLists.txt | 109 + COPYING | 346 ++ COPYING.DOC | 397 ++ ConfigureChecks.cmake | 54 + HACKING | 21 + Mainpage.dox | 21 + applets/CMakeLists.txt | 13 + applets/kickoff/CMakeLists.txt | 62 + applets/kickoff/DESIGN-GOALS | 71 + applets/kickoff/Messages.sh | 4 + applets/kickoff/STATUS-TODO | 66 + applets/kickoff/core/applicationmodel.cpp | 696 +++ applets/kickoff/core/applicationmodel.h | 131 + applets/kickoff/core/favoritesmodel.cpp | 376 ++ applets/kickoff/core/favoritesmodel.h | 72 + applets/kickoff/core/itemhandlers.cpp | 191 + applets/kickoff/core/itemhandlers.h | 59 + applets/kickoff/core/kickoffabstractmodel.cpp | 92 + applets/kickoff/core/kickoffabstractmodel.h | 53 + applets/kickoff/core/kickoffmodel.cpp | 99 + applets/kickoff/core/kickoffmodel.h | 55 + applets/kickoff/core/kickoffplugin.cpp | 45 + applets/kickoff/core/kickoffplugin.h | 35 + applets/kickoff/core/kickoffproxymodel.cpp | 92 + applets/kickoff/core/kickoffproxymodel.h | 53 + applets/kickoff/core/krunnermodel.cpp | 289 ++ applets/kickoff/core/krunnermodel.h | 76 + applets/kickoff/core/kuserproxy.cpp | 101 + applets/kickoff/core/kuserproxy.h | 53 + applets/kickoff/core/leavemodel.cpp | 212 + applets/kickoff/core/leavemodel.h | 48 + applets/kickoff/core/models.cpp | 214 + applets/kickoff/core/models.h | 140 + .../kickoff/core/org.kde.kickoff.recent.xml | 7 + applets/kickoff/core/org.kde.kickoff.xml | 7 + applets/kickoff/core/qmldir | 1 + applets/kickoff/core/recentapplications.cpp | 195 + applets/kickoff/core/recentapplications.h | 91 + applets/kickoff/core/recentlyusedmodel.cpp | 282 ++ applets/kickoff/core/recentlyusedmodel.h | 78 + applets/kickoff/core/systemmodel.cpp | 489 ++ applets/kickoff/core/systemmodel.h | 103 + applets/kickoff/core/urlitemlauncher.cpp | 164 + applets/kickoff/core/urlitemlauncher.h | 87 + .../package/contents/config/config.qml | 29 + .../kickoff/package/contents/config/main.xml | 20 + .../package/contents/ui/ApplicationsView.qml | 217 + .../kickoff/package/contents/ui/BaseView.qml | 65 + .../package/contents/ui/Breadcrumb.qml | 74 + .../package/contents/ui/ContextMenu.qml | 85 + .../package/contents/ui/FavoritesView.qml | 169 + .../kickoff/package/contents/ui/Footer.qml | 55 + .../kickoff/package/contents/ui/Header.qml | 225 + .../kickoff/package/contents/ui/Kickoff.qml | 404 ++ .../package/contents/ui/KickoffButton.qml | 73 + .../package/contents/ui/KickoffItem.qml | 171 + .../kickoff/package/contents/ui/LeaveView.qml | 27 + .../package/contents/ui/RecentlyUsedView.qml | 51 + .../package/contents/ui/SearchView.qml | 69 + .../package/contents/ui/SectionDelegate.qml | 64 + .../package/contents/ui/SystemView.qml | 26 + .../package/contents/ui/configGeneral.qml | 56 + applets/kickoff/package/metadata.desktop | 184 + applets/pager/CMakeLists.txt | 27 + applets/pager/Messages.sh | 3 + applets/pager/package/contents/code/utils.js | 6 + .../pager/package/contents/config/config.qml | 29 + .../pager/package/contents/config/main.xml | 33 + .../package/contents/ui/configGeneral.qml | 143 + applets/pager/package/contents/ui/main.qml | 329 ++ applets/pager/package/metadata.desktop | 170 + applets/pager/plugin/model.cpp | 250 + applets/pager/plugin/model.h | 112 + applets/pager/plugin/pager.cpp | 601 +++ applets/pager/plugin/pager.h | 168 + applets/pager/plugin/pagerplugin.cpp | 29 + applets/pager/plugin/pagerplugin.h | 35 + applets/pager/plugin/qmldir | 1 + applets/showActivityManager/CMakeLists.txt | 1 + applets/showActivityManager/Messages.sh | 4 + .../package/contents/ui/main.qml | 61 + .../package/metadata.desktop | 127 + applets/taskmanager/CMakeLists.txt | 26 + applets/taskmanager/Messages.sh | 4 + .../package/contents/code/layout.js | 172 + .../package/contents/code/tools.js | 118 + .../package/contents/config/config.qml | 30 + .../package/contents/config/main.xml | 48 + .../package/contents/ui/ConfigGeneral.qml | 137 + .../package/contents/ui/GroupDialog.qml | 115 + .../contents/ui/GroupExpanderOverlay.qml | 98 + .../package/contents/ui/MouseHandler.qml | 92 + .../taskmanager/package/contents/ui/Task.qml | 340 ++ .../package/contents/ui/TaskList.qml | 42 + .../package/contents/ui/ToolTipDelegate.qml | 111 + .../taskmanager/package/contents/ui/main.qml | 236 + applets/taskmanager/package/metadata.desktop | 172 + applets/taskmanager/plugin/backend.cpp | 272 + applets/taskmanager/plugin/backend.h | 91 + applets/taskmanager/plugin/blur.cpp | 154 + applets/taskmanager/plugin/draghelper.cpp | 61 + applets/taskmanager/plugin/draghelper.h | 45 + applets/taskmanager/plugin/qmldir | 2 + .../taskmanager/plugin/taskmanagerplugin.cpp | 53 + .../taskmanager/plugin/taskmanagerplugin.h | 35 + applets/taskmanager/plugin/textlabel.cpp | 273 + applets/taskmanager/plugin/textlabel.h | 80 + applets/trash/Messages.sh | 4 + applets/trash/contents/ui/main.qml | 96 + applets/trash/metadata.desktop | 90 + applets/window-list/Messages.sh | 4 + applets/window-list/contents/ui/Menu.qml | 79 + .../window-list/contents/ui/TaskDelegate.qml | 91 + applets/window-list/contents/ui/main.qml | 176 + applets/window-list/metadata.desktop | 119 + config-X11.h.cmake | 44 + config-unix.h.cmake | 35 + config-workspace.h.cmake | 159 + containments/CMakeLists.txt | 2 + containments/desktop/CMakeLists.txt | 2 + containments/desktop/Messages.sh | 4 + containments/desktop/TODO | 73 + .../package/contents/code/LayoutManager.js | 294 ++ .../desktop/package/contents/config/main.xml | 31 + .../contents/images/resize-handle.svgz | Bin 0 -> 1375 bytes .../package/contents/ui/ActionButton.qml | 144 + .../package/contents/ui/AppletAppearance.qml | 376 ++ .../package/contents/ui/AppletHandle.qml | 260 + .../package/contents/ui/BusyOverlay.qml | 64 + .../package/contents/ui/ContainmentConfig.qml | 127 + .../desktop/package/contents/ui/main.qml | 315 ++ containments/desktop/package/metadata.desktop | 152 + containments/desktop/tests/CMakeLists.txt | 6 + .../tests/framehandle-resizing-draft.qml | 100 + .../contents/code/testbackground.qml | 141 + .../contents/plasmatepreviewerlog.txt | 498 ++ .../org.kde.tests.background/metadata.desktop | 87 + containments/panel/Messages.sh | 4 + .../panel/contents/code/LayoutManager.js | 158 + containments/panel/contents/config/main.xml | 14 + .../panel/contents/ui/ConfigOverlay.qml | 292 ++ containments/panel/contents/ui/main.qml | 328 ++ containments/panel/metadata.desktop | 67 + .../panel/plasma-containment-panel.desktop | 113 + design/CHANGELOG-4.2 | 263 + design/CHANGELOG-4.3 | 246 + design/CHANGELOG-4.4 | 169 + design/CHANGELOG-4.5 | 80 + design/CHANGELOG-4.6 | 53 + design/CHANGELOG-template | 43 + design/README | 9 + design/activities | 85 + design/containmentactions | 86 + design/context | 33 + design/dataengine | 62 + design/ideas.txt | 53 + design/notifications | 67 + design/plasma-desktop-screen-handling | 14 + design/plasmoids | 82 + design/remotewidgets | 40 + design/screensaver | 61 + design/security | 57 + design/standardEffects | 22 + design/systemtraywidget | 55 + design/tooltips | 39 + design/wallpaper | 99 + design/widgets | 43 + desktoppackage/Messages.sh | 3 + .../activitymanager/ActivityBrowser.qml | 160 + .../ActivityCreationDialog.qml | 197 + .../ActivityDeletionDialog.qml | 131 + .../contents/activitymanager/ActivityItem.qml | 186 + .../contents/activitymanager/ActivityList.qml | 199 + .../activitymanager/ActivityManager.qml | 54 + .../activitymanager/ControlButton.qml | 59 + .../contents/activitymanager/Heading.qml | 118 + .../activitymanager/StoppedActivityItem.qml | 158 + .../activitymanager/WindowPreview.qml | 75 + .../contents/applet/AppletError.qml | 45 + .../contents/applet/CompactApplet.qml | 134 + .../applet/DefaultCompactRepresentation.qml | 36 + .../configuration/AppletConfiguration.qml | 262 + .../configuration/ConfigCategoryDelegate.qml | 85 + .../ConfigurationContainmentActions.qml | 119 + .../ConfigurationContainmentAppearance.qml | 106 + .../configuration/ConfigurationShortcuts.qml | 33 + .../ContainmentConfiguration.qml | 47 + .../configuration/MouseEventInputButton.qml | 71 + .../configuration/PanelConfiguration.qml | 172 + .../panelconfiguration/EdgeHandle.qml | 101 + .../panelconfiguration/Ruler.qml | 356 ++ .../panelconfiguration/SizeHandle.qml | 57 + .../panelconfiguration/SliderHandle.qml | 173 + .../panelconfiguration/ToolBar.qml | 365 ++ desktoppackage/contents/defaults | 16 + .../contents/explorer/AppletDelegate.qml | 116 + desktoppackage/contents/explorer/Tooltip.qml | 148 + .../contents/explorer/WidgetExplorer.qml | 287 ++ desktoppackage/contents/layout.js | 18 + desktoppackage/contents/loader.qml | 51 + desktoppackage/contents/views/Desktop.qml | 194 + desktoppackage/contents/views/Panel.qml | 181 + desktoppackage/metadata.desktop | 131 + doc/CMakeLists.txt | 3 + doc/kcontrol/CMakeLists.txt | 24 + doc/kcontrol/autostart/CMakeLists.txt | 3 + doc/kcontrol/autostart/index.docbook | 183 + doc/kcontrol/bell/CMakeLists.txt | 2 + doc/kcontrol/bell/index.docbook | 64 + doc/kcontrol/clock/CMakeLists.txt | 2 + doc/kcontrol/clock/index.docbook | 90 + doc/kcontrol/colors/CMakeLists.txt | 2 + doc/kcontrol/colors/index.docbook | 399 ++ doc/kcontrol/cursortheme/CMakeLists.txt | 2 + doc/kcontrol/cursortheme/index.docbook | 59 + .../desktopthemedetails/CMakeLists.txt | 3 + .../desktopthemedetails/clicking-apply.png | Bin 0 -> 124555 bytes .../desktopthemedetails/customizing.png | Bin 0 -> 128220 bytes .../desktopthemedetails/index.docbook | 182 + doc/kcontrol/fontinst/CMakeLists.txt | 2 + doc/kcontrol/fontinst/index.docbook | 109 + doc/kcontrol/fonts/CMakeLists.txt | 2 + doc/kcontrol/fonts/adjust-all.png | Bin 0 -> 32155 bytes doc/kcontrol/fonts/anti-aliasing.png | Bin 0 -> 21340 bytes doc/kcontrol/fonts/index.docbook | 169 + doc/kcontrol/fonts/main.png | Bin 0 -> 33765 bytes doc/kcontrol/joystick/CMakeLists.txt | 3 + doc/kcontrol/joystick/index.docbook | 137 + .../joystick/joystick-calibration.png | Bin 0 -> 25142 bytes doc/kcontrol/joystick/joystick-main.png | Bin 0 -> 45306 bytes doc/kcontrol/kcmaccess/CMakeLists.txt | 4 + doc/kcontrol/kcmaccess/index.docbook | 264 + doc/kcontrol/kcmsmserver/CMakeLists.txt | 3 + doc/kcontrol/kcmsmserver/index.docbook | 122 + doc/kcontrol/kcmstyle/CMakeLists.txt | 2 + doc/kcontrol/kcmstyle/index.docbook | 238 + doc/kcontrol/keyboard/CMakeLists.txt | 2 + doc/kcontrol/keyboard/index.docbook | 218 + doc/kcontrol/keys/CMakeLists.txt | 2 + doc/kcontrol/keys/index.docbook | 202 + doc/kcontrol/khotkeys/CMakeLists.txt | 2 + doc/kcontrol/khotkeys/groups-comment.png | Bin 0 -> 63546 bytes doc/kcontrol/khotkeys/index.docbook | 751 +++ doc/kcontrol/khotkeys/manage-export.png | Bin 0 -> 68149 bytes ...xygen-22x22-edit-clear-locationbar-rtl.png | Bin 0 -> 859 bytes doc/kcontrol/khotkeys/settings.png | Bin 0 -> 56454 bytes .../khotkeys/shortcuts-action-command.png | Bin 0 -> 64061 bytes .../khotkeys/shortcuts-action-keyboard.png | Bin 0 -> 70165 bytes .../khotkeys/shortcuts-trigger-keyboard.png | Bin 0 -> 63851 bytes .../khotkeys/shortcuts-trigger-mouse.png | Bin 0 -> 63226 bytes doc/kcontrol/mouse/CMakeLists.txt | 2 + doc/kcontrol/mouse/index.docbook | 472 ++ doc/kcontrol/paths/CMakeLists.txt | 2 + doc/kcontrol/paths/index.docbook | 91 + doc/kcontrol/paths/paths.png | Bin 0 -> 11152 bytes doc/kcontrol/powerdevil/CMakeLists.txt | 3 + doc/kcontrol/powerdevil/activity.png | Bin 0 -> 60677 bytes doc/kcontrol/powerdevil/advanced.png | Bin 0 -> 53231 bytes doc/kcontrol/powerdevil/energy.png | Bin 0 -> 68729 bytes doc/kcontrol/powerdevil/index.docbook | 317 ++ doc/kcontrol/solid-actions/CMakeLists.txt | 3 + doc/kcontrol/solid-actions/add-action.png | Bin 0 -> 13822 bytes doc/kcontrol/solid-actions/edit-action.png | Bin 0 -> 49373 bytes doc/kcontrol/solid-actions/index.docbook | 222 + doc/kcontrol/solid-actions/main.png | Bin 0 -> 65245 bytes doc/kcontrol/solid-hardware/CMakeLists.txt | 3 + doc/kcontrol/solid-hardware/index.docbook | 62 + doc/kcontrol/splashscreen/CMakeLists.txt | 3 + doc/kcontrol/splashscreen/get-new-theme.png | Bin 0 -> 67741 bytes doc/kcontrol/splashscreen/index.docbook | 117 + doc/kcontrol/splashscreen/splash-main.png | Bin 0 -> 66684 bytes doc/kfontview/CMakeLists.txt | 1 + doc/kfontview/index.docbook | 124 + doc/kfontview/kfontview.png | Bin 0 -> 66103 bytes doc/plasma-desktop/CMakeLists.txt | 5 + doc/plasma-desktop/add-widgets.png | Bin 0 -> 28524 bytes doc/plasma-desktop/desktop-settings.png | Bin 0 -> 96709 bytes doc/plasma-desktop/device_notifier_widget.png | Bin 0 -> 38856 bytes .../device_notifier_widget_actions.png | Bin 0 -> 41041 bytes doc/plasma-desktop/index.docbook | 642 +++ doc/plasma-desktop/panel-settings.png | Bin 0 -> 35520 bytes .../plasma-desktop-annotated.png | Bin 0 -> 387050 bytes doc/plasma-desktop/system-tray-settings.png | Bin 0 -> 44856 bytes doc/plasma-desktop/system-tray-up-arrow.png | Bin 0 -> 428 bytes doc/plasma-desktop/taskbar-settings.png | Bin 0 -> 47842 bytes kcms/CMakeLists.txt | 49 + kcms/PURPOSE | 10 + kcms/access/CMakeLists.txt | 58 + kcms/access/Messages.sh | 4 + kcms/access/kaccess.cpp | 921 ++++ kcms/access/kaccess.desktop | 97 + kcms/access/kaccess.h | 118 + kcms/access/kaccess.notifyrc | 1532 ++++++ kcms/access/kcmaccess.cpp | 786 +++ kcms/access/kcmaccess.desktop | 240 + kcms/access/kcmaccess.h | 76 + kcms/access/main.cpp | 55 + kcms/autostart/AUTHORS | 2 + kcms/autostart/CMakeLists.txt | 18 + kcms/autostart/Messages.sh | 4 + kcms/autostart/addscriptdialog.cpp | 105 + kcms/autostart/addscriptdialog.h | 61 + kcms/autostart/advanceddialog.cpp | 55 + kcms/autostart/advanceddialog.h | 40 + kcms/autostart/autostart.cpp | 438 ++ kcms/autostart/autostart.desktop | 190 + kcms/autostart/autostart.h | 75 + kcms/autostart/autostartconfig.ui | 82 + kcms/autostart/autostartitem.cpp | 111 + kcms/autostart/autostartitem.h | 75 + kcms/bell/CMakeLists.txt | 28 + kcms/bell/Messages.sh | 2 + kcms/bell/bell.cpp | 257 + kcms/bell/bell.desktop | 242 + kcms/bell/bell.h | 53 + kcms/colors/CMakeLists.txt | 30 + kcms/colors/Messages.sh | 4 + kcms/colors/README.i18n | 54 + kcms/colors/TODO | 3 + kcms/colors/colors.desktop | 194 + kcms/colors/colorschemes.knsrc | 6 + kcms/colors/colorscm.cpp | 1470 ++++++ kcms/colors/colorscm.h | 216 + kcms/colors/colorsettings.ui | 1298 +++++ kcms/colors/preview.ui | 336 ++ kcms/colors/previewwidget.cpp | 168 + kcms/colors/previewwidget.h | 49 + kcms/colors/schemes/Honeycomb.colors | 96 + kcms/colors/schemes/Norway.colors | 96 + kcms/colors/schemes/ObsidianCoast.colors | 95 + kcms/colors/schemes/Oxygen.colors | 103 + kcms/colors/schemes/OxygenCold.colors | 95 + kcms/colors/schemes/Steel.colors | 95 + kcms/colors/schemes/WontonSoup.colors | 94 + kcms/colors/schemes/Zion.colors | 96 + kcms/colors/schemes/ZionReversed.colors | 96 + kcms/colors/setpreview.ui | 347 ++ kcms/colors/setpreviewwidget.cpp | 138 + kcms/colors/setpreviewwidget.h | 49 + kcms/dateandtime/CMakeLists.txt | 34 + kcms/dateandtime/Messages.sh | 3 + kcms/dateandtime/clock.desktop | 196 + kcms/dateandtime/dateandtime.ui | 198 + kcms/dateandtime/dtime.cpp | 476 ++ kcms/dateandtime/dtime.h | 121 + kcms/dateandtime/helper.cpp | 254 + kcms/dateandtime/helper.h | 54 + kcms/dateandtime/kcmclock_actions.actions | 209 + kcms/dateandtime/main.cpp | 117 + kcms/dateandtime/main.h | 47 + kcms/desktoppaths/CMakeLists.txt | 17 + kcms/desktoppaths/Messages.sh | 2 + kcms/desktoppaths/desktoppath.desktop | 237 + kcms/desktoppaths/globalpaths.cpp | 455 ++ kcms/desktoppaths/globalpaths.h | 84 + kcms/desktoptheme/CMakeLists.txt | 27 + kcms/desktoptheme/DesktopTheme.ui | 104 + kcms/desktoptheme/DesktopThemeDetails.ui | 395 ++ kcms/desktoptheme/Messages.sh | 4 + kcms/desktoptheme/desktoptheme.desktop | 189 + kcms/desktoptheme/desktopthemedetails.cpp | 590 +++ kcms/desktoptheme/desktopthemedetails.h | 68 + kcms/desktoptheme/kcmdesktoptheme.cpp | 260 + kcms/desktoptheme/kcmdesktoptheme.h | 90 + kcms/desktoptheme/plasma-themes.knsrc | 6 + kcms/desktoptheme/thememodel.cpp | 224 + kcms/desktoptheme/thememodel.h | 87 + kcms/fonts/CMakeLists.txt | 37 + kcms/fonts/Messages.sh | 2 + kcms/fonts/fonts.cpp | 850 ++++ kcms/fonts/fonts.desktop | 241 + kcms/fonts/fonts.h | 127 + kcms/fonts/kxftconfig.cpp | 847 ++++ kcms/fonts/kxftconfig.h | 167 + kcms/hardware/CMakeLists.txt | 9 + kcms/hardware/display/CMakeLists.txt | 23 + kcms/hardware/display/Messages.sh | 2 + kcms/hardware/display/display.cpp | 117 + kcms/hardware/display/display.desktop | 191 + kcms/hardware/display/display.h | 48 + kcms/hardware/joystick/CMakeLists.txt | 32 + kcms/hardware/joystick/Messages.sh | 2 + kcms/hardware/joystick/caldialog.cpp | 200 + kcms/hardware/joystick/caldialog.h | 54 + kcms/hardware/joystick/joydevice.cpp | 403 ++ kcms/hardware/joystick/joydevice.h | 117 + kcms/hardware/joystick/joystick.cpp | 97 + kcms/hardware/joystick/joystick.desktop | 228 + kcms/hardware/joystick/joystick.h | 46 + kcms/hardware/joystick/joywidget.cpp | 418 ++ kcms/hardware/joystick/joywidget.h | 79 + kcms/hardware/joystick/poswidget.cpp | 133 + kcms/hardware/joystick/poswidget.h | 54 + kcms/input/AUTHORS | 7 + kcms/input/CMakeLists.txt | 115 + kcms/input/ChangeLog | 11 + kcms/input/Messages.sh | 4 + kcms/input/config-kcontrol-input.h.cmake | 3 + kcms/input/consoleUserPerms | 42 + kcms/input/core/bitmaps.h | 147 + kcms/input/core/themepage.cpp | 225 + kcms/input/core/themepage.h | 54 + kcms/input/cursor_large.bdf | 4447 +++++++++++++++++ kcms/input/cursor_large_black.pcf.gz | Bin 0 -> 3339 bytes kcms/input/cursor_large_white.pcf.gz | Bin 0 -> 3521 bytes kcms/input/cursor_small_white.pcf.gz | Bin 0 -> 3524 bytes kcms/input/cursortheme.desktop | 169 + kcms/input/kapplymousetheme.cpp | 88 + kcms/input/kcmcursortheme.cpp | 70 + kcms/input/kcmcursortheme.h | 42 + kcms/input/kmousedlg.ui | 295 ++ kcms/input/logitechmouse.cpp | 421 ++ kcms/input/logitechmouse.h | 107 + kcms/input/logitechmouse.usermap | 35 + kcms/input/logitechmouse_base.ui | 134 + kcms/input/main.cpp | 94 + kcms/input/mouse.cpp | 821 +++ kcms/input/mouse.desktop | 240 + kcms/input/mouse.h | 160 + kcms/input/pics/CMakeLists.txt | 1 + kcms/input/pics/mouse_lh.png | Bin 0 -> 10704 bytes kcms/input/pics/mouse_lh.svgz | Bin 0 -> 4614 bytes kcms/input/pics/mouse_rh.png | Bin 0 -> 10793 bytes kcms/input/pics/mouse_rh.svgz | Bin 0 -> 4528 bytes kcms/input/xcursor/cursortheme.cpp | 155 + kcms/input/xcursor/cursortheme.h | 143 + kcms/input/xcursor/itemdelegate.cpp | 174 + kcms/input/xcursor/itemdelegate.h | 42 + kcms/input/xcursor/previewwidget.cpp | 239 + kcms/input/xcursor/previewwidget.h | 51 + kcms/input/xcursor/sortproxymodel.cpp | 50 + kcms/input/xcursor/sortproxymodel.h | 77 + kcms/input/xcursor/thememodel.cpp | 419 ++ kcms/input/xcursor/thememodel.h | 114 + kcms/input/xcursor/themepage.cpp | 589 +++ kcms/input/xcursor/themepage.h | 99 + kcms/input/xcursor/themepage.ui | 120 + kcms/input/xcursor/xcursor.knsrc | 6 + kcms/input/xcursor/xcursortheme.cpp | 229 + kcms/input/xcursor/xcursortheme.h | 71 + kcms/keyboard/CMakeLists.txt | 177 + kcms/keyboard/Messages.sh | 5 + kcms/keyboard/README | 44 + kcms/keyboard/TODO | 37 + kcms/keyboard/bindings.cpp | 148 + kcms/keyboard/bindings.h | 53 + kcms/keyboard/flags.cpp | 325 ++ kcms/keyboard/flags.h | 72 + kcms/keyboard/iso_codes.cpp | 139 + kcms/keyboard/iso_codes.h | 72 + kcms/keyboard/kcm_add_layout_dialog.cpp | 165 + kcms/keyboard/kcm_add_layout_dialog.h | 58 + kcms/keyboard/kcm_add_layout_dialog.ui | 149 + kcms/keyboard/kcm_keyboard.cpp | 109 + kcms/keyboard/kcm_keyboard.desktop | 241 + kcms/keyboard/kcm_keyboard.h | 47 + kcms/keyboard/kcm_keyboard.ui | 481 ++ kcms/keyboard/kcm_keyboard_widget.cpp | 692 +++ kcms/keyboard/kcm_keyboard_widget.h | 101 + kcms/keyboard/kcm_view_models.cpp | 504 ++ kcms/keyboard/kcm_view_models.h | 170 + kcms/keyboard/kcmmisc.cpp | 238 + kcms/keyboard/kcmmisc.h | 91 + kcms/keyboard/kcmmiscwidget.ui | 335 ++ kcms/keyboard/keyboard.desktop | 75 + kcms/keyboard/keyboard_applet.cpp | 221 + kcms/keyboard/keyboard_applet.h | 81 + kcms/keyboard/keyboard_config.cpp | 208 + kcms/keyboard/keyboard_config.h | 93 + kcms/keyboard/keyboard_daemon.cpp | 255 + kcms/keyboard/keyboard_daemon.h | 81 + kcms/keyboard/keyboard_dbus.h | 27 + kcms/keyboard/keyboard_hardware.cpp | 112 + kcms/keyboard/keyboard_hardware.h | 25 + kcms/keyboard/layout_memory.cpp | 211 + kcms/keyboard/layout_memory.h | 66 + kcms/keyboard/layout_memory_persister.cpp | 260 + kcms/keyboard/layout_memory_persister.h | 52 + kcms/keyboard/layout_tray_icon.cpp | 125 + kcms/keyboard/layout_tray_icon.h | 69 + kcms/keyboard/layout_widget.cpp | 121 + kcms/keyboard/layout_widget.h | 60 + kcms/keyboard/layouts_menu.cpp | 142 + kcms/keyboard/layouts_menu.h | 56 + kcms/keyboard/numlockx.c | 305 ++ kcms/keyboard/pics/CMakeLists.txt | 1 + kcms/keyboard/pics/epo.png | Bin 0 -> 235 bytes kcms/keyboard/plasma_applet_keyboard.desktop | 165 + kcms/keyboard/preview/TODO | 10 + kcms/keyboard/preview/kbpreviewframe.cpp | 367 ++ kcms/keyboard/preview/kbpreviewframe.h | 55 + kcms/keyboard/preview/keyaliases.cpp | 127 + kcms/keyboard/preview/keyaliases.h | 35 + kcms/keyboard/preview/keyboardlayout.cpp | 186 + kcms/keyboard/preview/keyboardlayout.h | 50 + kcms/keyboard/preview/keyboardpainter.cpp | 53 + kcms/keyboard/preview/keyboardpainter.h | 44 + kcms/keyboard/preview/keysym2ucs.cpp | 899 ++++ kcms/keyboard/preview/keysym2ucs.h | 27 + kcms/keyboard/preview/keysymbols.cpp | 60 + kcms/keyboard/preview/keysymbols.h | 37 + kcms/keyboard/preview/keysymhelper.cpp | 78 + kcms/keyboard/preview/keysymhelper.h | 40 + kcms/keyboard/tests/CMakeLists.txt | 55 + kcms/keyboard/tests/config/base.1.1.xml | 68 + kcms/keyboard/tests/config/base.bad.xml | 5 + kcms/keyboard/tests/config/base.xml | 48 + kcms/keyboard/tests/flags_test.cpp | 103 + kcms/keyboard/tests/iso_codes_test.cpp | 78 + kcms/keyboard/tests/keyboard_daemon_test.cpp | 101 + .../tests/layout_memory_persister_test.cpp | 160 + kcms/keyboard/tests/xkb_rules_test.cpp | 240 + kcms/keyboard/x11_helper.cpp | 404 ++ kcms/keyboard/x11_helper.h | 185 + kcms/keyboard/xinput_helper.cpp | 162 + kcms/keyboard/xinput_helper.h | 50 + kcms/keyboard/xkb_helper.cpp | 184 + kcms/keyboard/xkb_helper.h | 35 + kcms/keyboard/xkb_rules.cpp | 417 ++ kcms/keyboard/xkb_rules.h | 119 + kcms/keys/CMakeLists.txt | 53 + kcms/keys/ChangeLog | 29 + kcms/keys/Messages.sh | 7 + kcms/keys/README | 7 + kcms/keys/export_scheme_dialog.cpp | 73 + kcms/keys/export_scheme_dialog.h | 59 + kcms/keys/export_scheme_dialog.ui | 35 + kcms/keys/globalshortcuts.cpp | 92 + kcms/keys/globalshortcuts.h | 44 + kcms/keys/keys.desktop | 229 + kcms/keys/kglobalshortcutseditor.cpp | 673 +++ kcms/keys/kglobalshortcutseditor.h | 154 + kcms/keys/kglobalshortcutseditor.ui | 57 + kcms/keys/schemes/kde3.kksrc | 166 + kcms/keys/schemes/kde4.kksrc | 166 + kcms/keys/schemes/mac4.kksrc | 171 + kcms/keys/schemes/old_kde3.kksrc | 51 + kcms/keys/schemes/old_kde4.kksrc | 51 + kcms/keys/schemes/old_mac4.kksrc | 51 + kcms/keys/schemes/old_unix3.kksrc | 51 + kcms/keys/schemes/old_win3.kksrc | 51 + kcms/keys/schemes/old_win4.kksrc | 51 + kcms/keys/schemes/old_wm3.kksrc | 51 + kcms/keys/schemes/split_kksrc | 111 + kcms/keys/schemes/unix3.kksrc | 171 + kcms/keys/schemes/win3.kksrc | 170 + kcms/keys/schemes/win4.kksrc | 170 + kcms/keys/schemes/wm3.kksrc | 165 + kcms/keys/select_scheme_dialog.cpp | 81 + kcms/keys/select_scheme_dialog.h | 49 + kcms/keys/select_scheme_dialog.ui | 150 + kcms/kfontinst/AUTHORS | 1 + kcms/kfontinst/CMakeLists.txt | 49 + kcms/kfontinst/ChangeLog | 562 +++ kcms/kfontinst/Messages.sh | 4 + kcms/kfontinst/apps/CMakeLists.txt | 51 + kcms/kfontinst/apps/CreateParent.h | 73 + kcms/kfontinst/apps/Installer.cpp | 153 + kcms/kfontinst/apps/Installer.h | 53 + kcms/kfontinst/apps/Printer.cpp | 495 ++ kcms/kfontinst/apps/Printer.h | 103 + kcms/kfontinst/apps/Viewer.cpp | 168 + kcms/kfontinst/apps/Viewer.h | 60 + kcms/kfontinst/apps/installfont.desktop | 96 + kcms/kfontinst/apps/kfontview.desktop | 192 + kcms/kfontinst/apps/kfontviewui.rc | 4 + kcms/kfontinst/apps/ox16-app-kfontview.png | Bin 0 -> 719 bytes kcms/kfontinst/apps/ox22-app-kfontview.png | Bin 0 -> 1047 bytes kcms/kfontinst/apps/ox32-app-kfontview.png | Bin 0 -> 1545 bytes kcms/kfontinst/apps/ox48-app-kfontview.png | Bin 0 -> 2701 bytes kcms/kfontinst/apps/ox64-app-kfontview.png | Bin 0 -> 4025 bytes kcms/kfontinst/apps/oxsc-app-kfontview.svgz | Bin 0 -> 9292 bytes kcms/kfontinst/config-fontinst.h.cmake | 9 + kcms/kfontinst/dbus/CMakeLists.txt | 31 + kcms/kfontinst/dbus/FcConfig.cpp | 194 + kcms/kfontinst/dbus/FcConfig.h | 39 + kcms/kfontinst/dbus/Folder.cpp | 418 ++ kcms/kfontinst/dbus/Folder.h | 114 + kcms/kfontinst/dbus/FontInst.cpp | 971 ++++ kcms/kfontinst/dbus/FontInst.h | 162 + kcms/kfontinst/dbus/FontinstIface.cpp | 28 + kcms/kfontinst/dbus/FontinstIface.h | 136 + kcms/kfontinst/dbus/Helper.cpp | 443 ++ kcms/kfontinst/dbus/Helper.h | 63 + kcms/kfontinst/dbus/Main.cpp | 36 + kcms/kfontinst/dbus/Utils.cpp | 249 + kcms/kfontinst/dbus/Utils.h | 54 + kcms/kfontinst/dbus/fontinst.actions | 227 + kcms/kfontinst/dbus/fontinst_x11 | 62 + .../dbus/org.kde.fontinst.service.cmake | 4 + .../org.kde.fontinst.system-service.cmake | 5 + kcms/kfontinst/dbus/org.kde.fontinst.xml | 112 + kcms/kfontinst/kcmfontinst/ActionLabel.cpp | 113 + kcms/kfontinst/kcmfontinst/ActionLabel.h | 58 + kcms/kfontinst/kcmfontinst/CMakeLists.txt | 31 + .../kcmfontinst/DuplicatesDialog.cpp | 679 +++ kcms/kfontinst/kcmfontinst/DuplicatesDialog.h | 181 + kcms/kfontinst/kcmfontinst/FcQuery.cpp | 120 + kcms/kfontinst/kcmfontinst/FcQuery.h | 70 + kcms/kfontinst/kcmfontinst/FontFilter.cpp | 400 ++ kcms/kfontinst/kcmfontinst/FontFilter.h | 98 + .../kcmfontinst/FontFilterProxyStyle.cpp | 170 + .../kcmfontinst/FontFilterProxyStyle.h | 71 + .../kfontinst/kcmfontinst/FontInstInterface.h | 23 + kcms/kfontinst/kcmfontinst/FontList.cpp | 2066 ++++++++ kcms/kfontinst/kcmfontinst/FontList.h | 383 ++ kcms/kfontinst/kcmfontinst/FontsPackage.cpp | 97 + kcms/kfontinst/kcmfontinst/FontsPackage.h | 42 + kcms/kfontinst/kcmfontinst/GroupList.cpp | 1029 ++++ kcms/kfontinst/kcmfontinst/GroupList.h | 241 + kcms/kfontinst/kcmfontinst/JobRunner.cpp | 769 +++ kcms/kfontinst/kcmfontinst/JobRunner.h | 141 + kcms/kfontinst/kcmfontinst/KCmFontInst.cpp | 1270 +++++ kcms/kfontinst/kcmfontinst/KCmFontInst.h | 145 + kcms/kfontinst/kcmfontinst/PreviewList.cpp | 223 + kcms/kfontinst/kcmfontinst/PreviewList.h | 105 + kcms/kfontinst/kcmfontinst/PrintDialog.cpp | 68 + kcms/kfontinst/kcmfontinst/PrintDialog.h | 49 + kcms/kfontinst/kcmfontinst/fontinst.desktop | 193 + kcms/kfontinst/kcmfontinst/kfontinst.knsrc | 7 + .../kcmfontinst/ox16-action-addfont.png | Bin 0 -> 704 bytes .../kcmfontinst/ox16-action-disablefont.png | Bin 0 -> 731 bytes .../kcmfontinst/ox16-action-enablefont.png | Bin 0 -> 736 bytes .../kcmfontinst/ox16-action-fontstatus.png | Bin 0 -> 744 bytes .../kcmfontinst/ox22-action-addfont.png | Bin 0 -> 1003 bytes .../kcmfontinst/ox22-action-disablefont.png | Bin 0 -> 1050 bytes .../kcmfontinst/ox22-action-enablefont.png | Bin 0 -> 1042 bytes .../kcmfontinst/ox22-action-fontstatus.png | Bin 0 -> 1096 bytes .../kcmfontinst/oxsc-action-addfont.svgz | Bin 0 -> 55400 bytes .../kcmfontinst/oxsc-action-disablefont.svgz | Bin 0 -> 55550 bytes .../kcmfontinst/oxsc-action-enablefont.svgz | Bin 0 -> 55250 bytes .../kcmfontinst/oxsc-action-fontstatus.svgz | Bin 0 -> 55218 bytes kcms/kfontinst/kio/CMakeLists.txt | 12 + kcms/kfontinst/kio/FontInstInterface.cpp | 176 + kcms/kfontinst/kio/FontInstInterface.h | 75 + kcms/kfontinst/kio/KioFonts.cpp | 820 +++ kcms/kfontinst/kio/KioFonts.h | 86 + kcms/kfontinst/kio/fonts.desktop | 99 + kcms/kfontinst/kio/fonts.protocol | 18 + .../kio/ox128-mimetypes-fonts-package.png | Bin 0 -> 5266 bytes .../kio/ox16-mimetypes-fonts-package.png | Bin 0 -> 638 bytes .../kio/ox22-mimetypes-fonts-package.png | Bin 0 -> 873 bytes .../kio/ox32-mimetypes-fonts-package.png | Bin 0 -> 1273 bytes .../kio/ox48-mimetypes-fonts-package.png | Bin 0 -> 1896 bytes .../kio/ox64-mimetypes-fonts-package.png | Bin 0 -> 2613 bytes .../kio/oxsc-mimetypes-fonts-package.svgz | Bin 0 -> 3498 bytes kcms/kfontinst/lib/CMakeLists.txt | 20 + kcms/kfontinst/lib/Family.cpp | 155 + kcms/kfontinst/lib/Family.h | 88 + kcms/kfontinst/lib/Fc.cpp | 650 +++ kcms/kfontinst/lib/Fc.h | 126 + kcms/kfontinst/lib/FcEngine.cpp | 1436 ++++++ kcms/kfontinst/lib/FcEngine.h | 136 + kcms/kfontinst/lib/File.cpp | 93 + kcms/kfontinst/lib/File.h | 82 + kcms/kfontinst/lib/KfiConstants.h | 130 + kcms/kfontinst/lib/Misc.cpp | 484 ++ kcms/kfontinst/lib/Misc.h | 124 + kcms/kfontinst/lib/Style.cpp | 189 + kcms/kfontinst/lib/Style.h | 83 + kcms/kfontinst/lib/WritingSystems.cpp | 176 + kcms/kfontinst/lib/WritingSystems.h | 53 + kcms/kfontinst/lib/XmlStrings.h | 45 + kcms/kfontinst/lib/kfontinst_export.h | 45 + ...pp-preferences-desktop-font-installer.svgz | Bin 0 -> 54135 bytes kcms/kfontinst/thumbnail/CMakeLists.txt | 14 + kcms/kfontinst/thumbnail/FontThumbnail.cpp | 125 + kcms/kfontinst/thumbnail/FontThumbnail.h | 51 + .../kfontinst/thumbnail/fontthumbnail.desktop | 98 + kcms/kfontinst/viewpart/CMakeLists.txt | 16 + kcms/kfontinst/viewpart/COPYING.UNICODE | 31 + kcms/kfontinst/viewpart/CharTip.cpp | 298 ++ kcms/kfontinst/viewpart/CharTip.h | 73 + kcms/kfontinst/viewpart/FontPreview.cpp | 179 + kcms/kfontinst/viewpart/FontPreview.h | 97 + kcms/kfontinst/viewpart/FontViewPart.cpp | 556 +++ kcms/kfontinst/viewpart/FontViewPart.h | 124 + .../viewpart/PreviewSelectAction.cpp | 98 + kcms/kfontinst/viewpart/PreviewSelectAction.h | 67 + kcms/kfontinst/viewpart/UnicodeBlocks.h | 179 + kcms/kfontinst/viewpart/UnicodeCategories.h | 2128 ++++++++ kcms/kfontinst/viewpart/UnicodeScripts.h | 1286 +++++ .../viewpart/download-unicode-files.sh | 26 + .../viewpart/generate-unicode-tables.pl | 854 ++++ kcms/kfontinst/viewpart/kfontviewpart.desktop | 98 + kcms/kfontinst/viewpart/kfontviewpart.rc | 11 + kcms/krdb/AUTHORS | 9 + kcms/krdb/CMakeLists.txt | 10 + kcms/krdb/Messages.sh | 2 + kcms/krdb/ad/AAAAAAGeneral.ad | 2 + kcms/krdb/ad/AAAMotif.ad | 74 + kcms/krdb/ad/AAATk.ad | 107 + kcms/krdb/ad/AAAXaw.ad | 36 + kcms/krdb/ad/AcroRead.ad | 8 + kcms/krdb/ad/CMakeLists.txt | 3 + kcms/krdb/ad/Editres.ad | 5 + kcms/krdb/ad/Emacs.ad | 17 + kcms/krdb/ad/GV.ad | 1 + kcms/krdb/ad/ML.ad | 36 + kcms/krdb/ad/Nedit.ad | 2 + kcms/krdb/ad/Netscape.ad | 25 + kcms/krdb/ad/README | 63 + kcms/krdb/ad/RVPlayer.ad | 40 + kcms/krdb/ad/WPerfect.ad | 68 + kcms/krdb/ad/XCalc.ad | 7 + kcms/krdb/ad/XOsview.ad | 5 + kcms/krdb/ad/XTerm.ad | 4 + kcms/krdb/ad/XV.ad | 2 + kcms/krdb/ad/Xawtv.ad | 10 + kcms/krdb/ad/Xdvi.ad | 1 + kcms/krdb/ad/Xpdf.ad | 3 + kcms/krdb/ad/krdb | 4 + kcms/krdb/krdb.cpp | 591 +++ kcms/krdb/krdb.h | 34 + kcms/krdb/krdb_clearlibrarypath.cpp | 75 + kcms/krdb/krdb_libpathwipe.upd | 2 + kcms/krdb/pics/CMakeLists.txt | 2 + kcms/krdb/pics/lo-energy.png | Bin 0 -> 1767 bytes kcms/krdb/pics/logo.png | Bin 0 -> 785 bytes kcms/krdb/pics/mini-world.png | Bin 0 -> 983 bytes kcms/krdb/themes/CMakeLists.txt | 12 + .../HighContrastDark-big/CMakeLists.txt | 1 + .../HighContrastDark-big.preview.png | Bin 0 -> 6976 bytes .../HighContrastDark-big.xml | 158 + .../themes/HighContrastDark/CMakeLists.txt | 1 + .../HighContrastDark.preview.png | Bin 0 -> 5385 bytes .../HighContrastDark/HighContrastDark.xml | 158 + .../HighContrastLight-big/CMakeLists.txt | 2 + .../HighContrastLight-big.preview.png | Bin 0 -> 42834 bytes .../HighContrastLight-big.xml | 158 + .../themes/HighContrastLight/CMakeLists.txt | 2 + .../HighContrastLight.preview.png | Bin 0 -> 40603 bytes .../HighContrastLight/HighContrastLight.xml | 158 + kcms/krdb/themes/KDE_Classic/CMakeLists.txt | 1 + .../KDE_Classic/KDE_Classic.preview.png | Bin 0 -> 36961 bytes kcms/krdb/themes/KDE_Classic/KDE_Classic.xml | 124 + kcms/krdb/themes/Keramik/CMakeLists.txt | 2 + kcms/krdb/themes/Keramik/Keramik.preview.png | Bin 0 -> 41073 bytes kcms/krdb/themes/Keramik/Keramik.xml | 124 + kcms/krdb/themes/Plastik/CMakeLists.txt | 1 + kcms/krdb/themes/Plastik/Plastik.preview.png | Bin 0 -> 37186 bytes kcms/krdb/themes/Plastik/Plastik.xml | 124 + kcms/krdb/themes/Platinum/CMakeLists.txt | 1 + .../krdb/themes/Platinum/Platinum.preview.png | Bin 0 -> 31282 bytes kcms/krdb/themes/Platinum/Platinum.xml | 124 + kcms/krdb/themes/Redmond/CMakeLists.txt | 1 + kcms/krdb/themes/Redmond/Redmond.preview.png | Bin 0 -> 30318 bytes kcms/krdb/themes/Redmond/Redmond.xml | 124 + kcms/krdb/themes/Sunshine/CMakeLists.txt | 1 + .../krdb/themes/Sunshine/Sunshine.preview.png | Bin 0 -> 28343 bytes kcms/krdb/themes/Sunshine/Sunshine.xml | 124 + .../themes/YellowOnBlue-big/CMakeLists.txt | 1 + .../YellowOnBlue-big.preview.png | Bin 0 -> 55401 bytes .../YellowOnBlue-big/YellowOnBlue-big.xml | 158 + kcms/krdb/themes/YellowOnBlue/CMakeLists.txt | 1 + .../YellowOnBlue/YellowOnBlue.preview.png | Bin 0 -> 53362 bytes .../krdb/themes/YellowOnBlue/YellowOnBlue.xml | 158 + kcms/launch/CMakeLists.txt | 38 + kcms/launch/Messages.sh | 2 + kcms/launch/interface_util.h | 26 + kcms/launch/kcmlaunch.cpp | 276 + kcms/launch/kcmlaunch.desktop | 233 + kcms/launch/kcmlaunch.h | 71 + kcms/standard_actions/CMakeLists.txt | 14 + kcms/standard_actions/Messages.sh | 2 + .../standard_actions/standard_actions.desktop | 215 + .../standard_actions_module.cpp | 164 + .../standard_actions_module.h | 49 + kcms/style/CMakeLists.txt | 40 + kcms/style/Messages.sh | 4 + kcms/style/finetuning.ui | 259 + kcms/style/kcmstyle.cpp | 879 ++++ kcms/style/kcmstyle.h | 122 + kcms/style/kcmstyle.notifyrc | 176 + kcms/style/style.desktop | 237 + kcms/style/styleconfdialog.cpp | 48 + kcms/style/styleconfdialog.h | 46 + kcms/style/stylepreview.ui | 171 + ktouchpadenabler/CMakeLists.txt | 27 + ktouchpadenabler/COPYING | 339 ++ ktouchpadenabler/Messages.sh | 2 + ktouchpadenabler/ktouchpadenabler.desktop | 95 + ktouchpadenabler/ktouchpadenabler.kcfg | 12 + ktouchpadenabler/ktouchpadenabler_daemon.cpp | 218 + ktouchpadenabler/ktouchpadenabler_daemon.h | 37 + ktouchpadenabler/settings.kcfgc | 5 + runners/CMakeLists.txt | 2 + runners/plasma-desktop/CMakeLists.txt | 10 + runners/plasma-desktop/Messages.sh | 4 + .../plasma-desktop/plasma-desktop-runner.cpp | 146 + .../plasma-desktop/plasma-desktop-runner.h | 51 + .../plasma-runner-plasma-desktop.desktop | 140 + solid-actions-kcm/ActionEditor.cpp | 190 + solid-actions-kcm/ActionEditor.h | 62 + solid-actions-kcm/ActionEditor.ui | 335 ++ solid-actions-kcm/ActionItem.cpp | 158 + solid-actions-kcm/ActionItem.h | 76 + solid-actions-kcm/ActionModel.cpp | 121 + solid-actions-kcm/ActionModel.h | 48 + solid-actions-kcm/AddAction.ui | 43 + solid-actions-kcm/CMakeLists.txt | 38 + solid-actions-kcm/DesktopFileGenerator.cpp | 74 + solid-actions-kcm/Messages.sh | 4 + solid-actions-kcm/PredicateItem.cpp | 208 + solid-actions-kcm/PredicateItem.h | 56 + solid-actions-kcm/PredicateModel.cpp | 176 + solid-actions-kcm/PredicateModel.h | 56 + solid-actions-kcm/SolidActionData.cpp | 192 + solid-actions-kcm/SolidActionData.h | 57 + solid-actions-kcm/SolidActions.cpp | 231 + solid-actions-kcm/SolidActions.h | 65 + solid-actions-kcm/SolidActions.ui | 53 + .../device-actions/CMakeLists.txt | 3 + .../solid-device-AcAdapter.desktop | 120 + .../solid-device-AudioInterface.desktop | 435 ++ .../solid-device-Battery.desktop | 406 ++ .../device-actions/solid-device-Block.desktop | 286 ++ .../solid-device-Button.desktop | 285 ++ .../solid-device-Camera.desktop | 215 + .../solid-device-DvbInterface.desktop | 363 ++ .../solid-device-NetworkInterface.desktop | 364 ++ .../solid-device-OpticalDisc.desktop | 941 ++++ .../solid-device-OpticalDrive.desktop | 723 +++ .../solid-device-PortableMediaPlayer.desktop | 215 + .../solid-device-Processor.desktop | 355 ++ .../solid-device-SerialInterface.desktop | 259 + .../solid-device-SmartCardReader.desktop | 143 + .../solid-device-StorageAccess.desktop | 217 + .../solid-device-StorageDrive.desktop | 434 ++ .../solid-device-StorageVolume.desktop | 507 ++ .../device-actions/solid-device-Video.desktop | 144 + .../solid-action-template.desktop | 9 + solid-actions-kcm/solid-actions.desktop | 176 + solid-actions-kcm/solid-device-type.desktop | 70 + toolboxes/CMakeLists.txt | 4 + toolboxes/desktoptoolbox/Messages.sh | 4 + .../desktoptoolbox/contents/config/main.xml | 31 + .../contents/ui/ActionDelegate.qml | 73 + .../contents/ui/ToolBoxButton.qml | 247 + .../contents/ui/ToolBoxItem.qml | 212 + .../contents/ui/ToolBoxRoot.qml | 160 + toolboxes/desktoptoolbox/metadata.desktop | 95 + toolboxes/paneltoolbox/contents/ui/main.qml | 94 + toolboxes/paneltoolbox/metadata.desktop | 93 + toolboxes/plasma-toolbox-paneltoolbox.desktop | 109 + 845 files changed, 117937 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 COPYING.DOC create mode 100644 ConfigureChecks.cmake create mode 100644 HACKING create mode 100644 Mainpage.dox create mode 100644 applets/CMakeLists.txt create mode 100644 applets/kickoff/CMakeLists.txt create mode 100644 applets/kickoff/DESIGN-GOALS create mode 100644 applets/kickoff/Messages.sh create mode 100644 applets/kickoff/STATUS-TODO create mode 100644 applets/kickoff/core/applicationmodel.cpp create mode 100644 applets/kickoff/core/applicationmodel.h create mode 100644 applets/kickoff/core/favoritesmodel.cpp create mode 100644 applets/kickoff/core/favoritesmodel.h create mode 100644 applets/kickoff/core/itemhandlers.cpp create mode 100644 applets/kickoff/core/itemhandlers.h create mode 100644 applets/kickoff/core/kickoffabstractmodel.cpp create mode 100644 applets/kickoff/core/kickoffabstractmodel.h create mode 100644 applets/kickoff/core/kickoffmodel.cpp create mode 100644 applets/kickoff/core/kickoffmodel.h create mode 100644 applets/kickoff/core/kickoffplugin.cpp create mode 100644 applets/kickoff/core/kickoffplugin.h create mode 100644 applets/kickoff/core/kickoffproxymodel.cpp create mode 100644 applets/kickoff/core/kickoffproxymodel.h create mode 100644 applets/kickoff/core/krunnermodel.cpp create mode 100644 applets/kickoff/core/krunnermodel.h create mode 100644 applets/kickoff/core/kuserproxy.cpp create mode 100644 applets/kickoff/core/kuserproxy.h create mode 100644 applets/kickoff/core/leavemodel.cpp create mode 100644 applets/kickoff/core/leavemodel.h create mode 100644 applets/kickoff/core/models.cpp create mode 100644 applets/kickoff/core/models.h create mode 100644 applets/kickoff/core/org.kde.kickoff.recent.xml create mode 100644 applets/kickoff/core/org.kde.kickoff.xml create mode 100644 applets/kickoff/core/qmldir create mode 100644 applets/kickoff/core/recentapplications.cpp create mode 100644 applets/kickoff/core/recentapplications.h create mode 100644 applets/kickoff/core/recentlyusedmodel.cpp create mode 100644 applets/kickoff/core/recentlyusedmodel.h create mode 100644 applets/kickoff/core/systemmodel.cpp create mode 100644 applets/kickoff/core/systemmodel.h create mode 100644 applets/kickoff/core/urlitemlauncher.cpp create mode 100644 applets/kickoff/core/urlitemlauncher.h create mode 100644 applets/kickoff/package/contents/config/config.qml create mode 100644 applets/kickoff/package/contents/config/main.xml create mode 100644 applets/kickoff/package/contents/ui/ApplicationsView.qml create mode 100644 applets/kickoff/package/contents/ui/BaseView.qml create mode 100644 applets/kickoff/package/contents/ui/Breadcrumb.qml create mode 100644 applets/kickoff/package/contents/ui/ContextMenu.qml create mode 100644 applets/kickoff/package/contents/ui/FavoritesView.qml create mode 100644 applets/kickoff/package/contents/ui/Footer.qml create mode 100644 applets/kickoff/package/contents/ui/Header.qml create mode 100644 applets/kickoff/package/contents/ui/Kickoff.qml create mode 100644 applets/kickoff/package/contents/ui/KickoffButton.qml create mode 100644 applets/kickoff/package/contents/ui/KickoffItem.qml create mode 100644 applets/kickoff/package/contents/ui/LeaveView.qml create mode 100644 applets/kickoff/package/contents/ui/RecentlyUsedView.qml create mode 100644 applets/kickoff/package/contents/ui/SearchView.qml create mode 100644 applets/kickoff/package/contents/ui/SectionDelegate.qml create mode 100644 applets/kickoff/package/contents/ui/SystemView.qml create mode 100644 applets/kickoff/package/contents/ui/configGeneral.qml create mode 100644 applets/kickoff/package/metadata.desktop create mode 100644 applets/pager/CMakeLists.txt create mode 100644 applets/pager/Messages.sh create mode 100644 applets/pager/package/contents/code/utils.js create mode 100644 applets/pager/package/contents/config/config.qml create mode 100644 applets/pager/package/contents/config/main.xml create mode 100644 applets/pager/package/contents/ui/configGeneral.qml create mode 100644 applets/pager/package/contents/ui/main.qml create mode 100644 applets/pager/package/metadata.desktop create mode 100644 applets/pager/plugin/model.cpp create mode 100644 applets/pager/plugin/model.h create mode 100644 applets/pager/plugin/pager.cpp create mode 100644 applets/pager/plugin/pager.h create mode 100644 applets/pager/plugin/pagerplugin.cpp create mode 100644 applets/pager/plugin/pagerplugin.h create mode 100644 applets/pager/plugin/qmldir create mode 100644 applets/showActivityManager/CMakeLists.txt create mode 100644 applets/showActivityManager/Messages.sh create mode 100644 applets/showActivityManager/package/contents/ui/main.qml create mode 100644 applets/showActivityManager/package/metadata.desktop create mode 100644 applets/taskmanager/CMakeLists.txt create mode 100644 applets/taskmanager/Messages.sh create mode 100644 applets/taskmanager/package/contents/code/layout.js create mode 100644 applets/taskmanager/package/contents/code/tools.js create mode 100644 applets/taskmanager/package/contents/config/config.qml create mode 100644 applets/taskmanager/package/contents/config/main.xml create mode 100644 applets/taskmanager/package/contents/ui/ConfigGeneral.qml create mode 100644 applets/taskmanager/package/contents/ui/GroupDialog.qml create mode 100644 applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml create mode 100644 applets/taskmanager/package/contents/ui/MouseHandler.qml create mode 100644 applets/taskmanager/package/contents/ui/Task.qml create mode 100644 applets/taskmanager/package/contents/ui/TaskList.qml create mode 100644 applets/taskmanager/package/contents/ui/ToolTipDelegate.qml create mode 100644 applets/taskmanager/package/contents/ui/main.qml create mode 100644 applets/taskmanager/package/metadata.desktop create mode 100644 applets/taskmanager/plugin/backend.cpp create mode 100644 applets/taskmanager/plugin/backend.h create mode 100644 applets/taskmanager/plugin/blur.cpp create mode 100644 applets/taskmanager/plugin/draghelper.cpp create mode 100644 applets/taskmanager/plugin/draghelper.h create mode 100644 applets/taskmanager/plugin/qmldir create mode 100644 applets/taskmanager/plugin/taskmanagerplugin.cpp create mode 100644 applets/taskmanager/plugin/taskmanagerplugin.h create mode 100644 applets/taskmanager/plugin/textlabel.cpp create mode 100644 applets/taskmanager/plugin/textlabel.h create mode 100644 applets/trash/Messages.sh create mode 100644 applets/trash/contents/ui/main.qml create mode 100644 applets/trash/metadata.desktop create mode 100644 applets/window-list/Messages.sh create mode 100644 applets/window-list/contents/ui/Menu.qml create mode 100644 applets/window-list/contents/ui/TaskDelegate.qml create mode 100644 applets/window-list/contents/ui/main.qml create mode 100644 applets/window-list/metadata.desktop create mode 100644 config-X11.h.cmake create mode 100644 config-unix.h.cmake create mode 100644 config-workspace.h.cmake create mode 100644 containments/CMakeLists.txt create mode 100644 containments/desktop/CMakeLists.txt create mode 100644 containments/desktop/Messages.sh create mode 100644 containments/desktop/TODO create mode 100644 containments/desktop/package/contents/code/LayoutManager.js create mode 100644 containments/desktop/package/contents/config/main.xml create mode 100755 containments/desktop/package/contents/images/resize-handle.svgz create mode 100644 containments/desktop/package/contents/ui/ActionButton.qml create mode 100644 containments/desktop/package/contents/ui/AppletAppearance.qml create mode 100644 containments/desktop/package/contents/ui/AppletHandle.qml create mode 100644 containments/desktop/package/contents/ui/BusyOverlay.qml create mode 100644 containments/desktop/package/contents/ui/ContainmentConfig.qml create mode 100644 containments/desktop/package/contents/ui/main.qml create mode 100644 containments/desktop/package/metadata.desktop create mode 100644 containments/desktop/tests/CMakeLists.txt create mode 100644 containments/desktop/tests/framehandle-resizing-draft.qml create mode 100644 containments/desktop/tests/org.kde.tests.background/contents/code/testbackground.qml create mode 100644 containments/desktop/tests/org.kde.tests.background/contents/plasmatepreviewerlog.txt create mode 100644 containments/desktop/tests/org.kde.tests.background/metadata.desktop create mode 100644 containments/panel/Messages.sh create mode 100644 containments/panel/contents/code/LayoutManager.js create mode 100644 containments/panel/contents/config/main.xml create mode 100644 containments/panel/contents/ui/ConfigOverlay.qml create mode 100644 containments/panel/contents/ui/main.qml create mode 100644 containments/panel/metadata.desktop create mode 100644 containments/panel/plasma-containment-panel.desktop create mode 100644 design/CHANGELOG-4.2 create mode 100644 design/CHANGELOG-4.3 create mode 100644 design/CHANGELOG-4.4 create mode 100644 design/CHANGELOG-4.5 create mode 100644 design/CHANGELOG-4.6 create mode 100644 design/CHANGELOG-template create mode 100644 design/README create mode 100644 design/activities create mode 100644 design/containmentactions create mode 100644 design/context create mode 100644 design/dataengine create mode 100644 design/ideas.txt create mode 100644 design/notifications create mode 100644 design/plasma-desktop-screen-handling create mode 100644 design/plasmoids create mode 100644 design/remotewidgets create mode 100644 design/screensaver create mode 100644 design/security create mode 100644 design/standardEffects create mode 100644 design/systemtraywidget create mode 100644 design/tooltips create mode 100644 design/wallpaper create mode 100644 design/widgets create mode 100644 desktoppackage/Messages.sh create mode 100644 desktoppackage/contents/activitymanager/ActivityBrowser.qml create mode 100644 desktoppackage/contents/activitymanager/ActivityCreationDialog.qml create mode 100644 desktoppackage/contents/activitymanager/ActivityDeletionDialog.qml create mode 100644 desktoppackage/contents/activitymanager/ActivityItem.qml create mode 100644 desktoppackage/contents/activitymanager/ActivityList.qml create mode 100644 desktoppackage/contents/activitymanager/ActivityManager.qml create mode 100644 desktoppackage/contents/activitymanager/ControlButton.qml create mode 100644 desktoppackage/contents/activitymanager/Heading.qml create mode 100644 desktoppackage/contents/activitymanager/StoppedActivityItem.qml create mode 100644 desktoppackage/contents/activitymanager/WindowPreview.qml create mode 100644 desktoppackage/contents/applet/AppletError.qml create mode 100644 desktoppackage/contents/applet/CompactApplet.qml create mode 100644 desktoppackage/contents/applet/DefaultCompactRepresentation.qml create mode 100644 desktoppackage/contents/configuration/AppletConfiguration.qml create mode 100644 desktoppackage/contents/configuration/ConfigCategoryDelegate.qml create mode 100644 desktoppackage/contents/configuration/ConfigurationContainmentActions.qml create mode 100644 desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml create mode 100644 desktoppackage/contents/configuration/ConfigurationShortcuts.qml create mode 100644 desktoppackage/contents/configuration/ContainmentConfiguration.qml create mode 100644 desktoppackage/contents/configuration/MouseEventInputButton.qml create mode 100644 desktoppackage/contents/configuration/PanelConfiguration.qml create mode 100644 desktoppackage/contents/configuration/panelconfiguration/EdgeHandle.qml create mode 100644 desktoppackage/contents/configuration/panelconfiguration/Ruler.qml create mode 100644 desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml create mode 100644 desktoppackage/contents/configuration/panelconfiguration/SliderHandle.qml create mode 100644 desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml create mode 100644 desktoppackage/contents/defaults create mode 100644 desktoppackage/contents/explorer/AppletDelegate.qml create mode 100644 desktoppackage/contents/explorer/Tooltip.qml create mode 100644 desktoppackage/contents/explorer/WidgetExplorer.qml create mode 100644 desktoppackage/contents/layout.js create mode 100644 desktoppackage/contents/loader.qml create mode 100644 desktoppackage/contents/views/Desktop.qml create mode 100644 desktoppackage/contents/views/Panel.qml create mode 100644 desktoppackage/metadata.desktop create mode 100644 doc/CMakeLists.txt create mode 100644 doc/kcontrol/CMakeLists.txt create mode 100644 doc/kcontrol/autostart/CMakeLists.txt create mode 100644 doc/kcontrol/autostart/index.docbook create mode 100644 doc/kcontrol/bell/CMakeLists.txt create mode 100644 doc/kcontrol/bell/index.docbook create mode 100644 doc/kcontrol/clock/CMakeLists.txt create mode 100644 doc/kcontrol/clock/index.docbook create mode 100644 doc/kcontrol/colors/CMakeLists.txt create mode 100644 doc/kcontrol/colors/index.docbook create mode 100644 doc/kcontrol/cursortheme/CMakeLists.txt create mode 100644 doc/kcontrol/cursortheme/index.docbook create mode 100644 doc/kcontrol/desktopthemedetails/CMakeLists.txt create mode 100644 doc/kcontrol/desktopthemedetails/clicking-apply.png create mode 100644 doc/kcontrol/desktopthemedetails/customizing.png create mode 100644 doc/kcontrol/desktopthemedetails/index.docbook create mode 100644 doc/kcontrol/fontinst/CMakeLists.txt create mode 100644 doc/kcontrol/fontinst/index.docbook create mode 100644 doc/kcontrol/fonts/CMakeLists.txt create mode 100644 doc/kcontrol/fonts/adjust-all.png create mode 100644 doc/kcontrol/fonts/anti-aliasing.png create mode 100644 doc/kcontrol/fonts/index.docbook create mode 100644 doc/kcontrol/fonts/main.png create mode 100644 doc/kcontrol/joystick/CMakeLists.txt create mode 100644 doc/kcontrol/joystick/index.docbook create mode 100644 doc/kcontrol/joystick/joystick-calibration.png create mode 100644 doc/kcontrol/joystick/joystick-main.png create mode 100644 doc/kcontrol/kcmaccess/CMakeLists.txt create mode 100644 doc/kcontrol/kcmaccess/index.docbook create mode 100644 doc/kcontrol/kcmsmserver/CMakeLists.txt create mode 100644 doc/kcontrol/kcmsmserver/index.docbook create mode 100644 doc/kcontrol/kcmstyle/CMakeLists.txt create mode 100644 doc/kcontrol/kcmstyle/index.docbook create mode 100644 doc/kcontrol/keyboard/CMakeLists.txt create mode 100644 doc/kcontrol/keyboard/index.docbook create mode 100644 doc/kcontrol/keys/CMakeLists.txt create mode 100644 doc/kcontrol/keys/index.docbook create mode 100644 doc/kcontrol/khotkeys/CMakeLists.txt create mode 100644 doc/kcontrol/khotkeys/groups-comment.png create mode 100644 doc/kcontrol/khotkeys/index.docbook create mode 100644 doc/kcontrol/khotkeys/manage-export.png create mode 100644 doc/kcontrol/khotkeys/oxygen-22x22-edit-clear-locationbar-rtl.png create mode 100644 doc/kcontrol/khotkeys/settings.png create mode 100644 doc/kcontrol/khotkeys/shortcuts-action-command.png create mode 100644 doc/kcontrol/khotkeys/shortcuts-action-keyboard.png create mode 100644 doc/kcontrol/khotkeys/shortcuts-trigger-keyboard.png create mode 100644 doc/kcontrol/khotkeys/shortcuts-trigger-mouse.png create mode 100644 doc/kcontrol/mouse/CMakeLists.txt create mode 100644 doc/kcontrol/mouse/index.docbook create mode 100644 doc/kcontrol/paths/CMakeLists.txt create mode 100644 doc/kcontrol/paths/index.docbook create mode 100644 doc/kcontrol/paths/paths.png create mode 100644 doc/kcontrol/powerdevil/CMakeLists.txt create mode 100644 doc/kcontrol/powerdevil/activity.png create mode 100644 doc/kcontrol/powerdevil/advanced.png create mode 100644 doc/kcontrol/powerdevil/energy.png create mode 100644 doc/kcontrol/powerdevil/index.docbook create mode 100644 doc/kcontrol/solid-actions/CMakeLists.txt create mode 100644 doc/kcontrol/solid-actions/add-action.png create mode 100644 doc/kcontrol/solid-actions/edit-action.png create mode 100644 doc/kcontrol/solid-actions/index.docbook create mode 100644 doc/kcontrol/solid-actions/main.png create mode 100644 doc/kcontrol/solid-hardware/CMakeLists.txt create mode 100644 doc/kcontrol/solid-hardware/index.docbook create mode 100644 doc/kcontrol/splashscreen/CMakeLists.txt create mode 100644 doc/kcontrol/splashscreen/get-new-theme.png create mode 100644 doc/kcontrol/splashscreen/index.docbook create mode 100644 doc/kcontrol/splashscreen/splash-main.png create mode 100644 doc/kfontview/CMakeLists.txt create mode 100644 doc/kfontview/index.docbook create mode 100644 doc/kfontview/kfontview.png create mode 100644 doc/plasma-desktop/CMakeLists.txt create mode 100644 doc/plasma-desktop/add-widgets.png create mode 100644 doc/plasma-desktop/desktop-settings.png create mode 100644 doc/plasma-desktop/device_notifier_widget.png create mode 100644 doc/plasma-desktop/device_notifier_widget_actions.png create mode 100644 doc/plasma-desktop/index.docbook create mode 100644 doc/plasma-desktop/panel-settings.png create mode 100644 doc/plasma-desktop/plasma-desktop-annotated.png create mode 100644 doc/plasma-desktop/system-tray-settings.png create mode 100644 doc/plasma-desktop/system-tray-up-arrow.png create mode 100644 doc/plasma-desktop/taskbar-settings.png create mode 100644 kcms/CMakeLists.txt create mode 100644 kcms/PURPOSE create mode 100644 kcms/access/CMakeLists.txt create mode 100644 kcms/access/Messages.sh create mode 100644 kcms/access/kaccess.cpp create mode 100644 kcms/access/kaccess.desktop create mode 100644 kcms/access/kaccess.h create mode 100644 kcms/access/kaccess.notifyrc create mode 100644 kcms/access/kcmaccess.cpp create mode 100644 kcms/access/kcmaccess.desktop create mode 100644 kcms/access/kcmaccess.h create mode 100644 kcms/access/main.cpp create mode 100644 kcms/autostart/AUTHORS create mode 100644 kcms/autostart/CMakeLists.txt create mode 100644 kcms/autostart/Messages.sh create mode 100644 kcms/autostart/addscriptdialog.cpp create mode 100644 kcms/autostart/addscriptdialog.h create mode 100644 kcms/autostart/advanceddialog.cpp create mode 100644 kcms/autostart/advanceddialog.h create mode 100644 kcms/autostart/autostart.cpp create mode 100644 kcms/autostart/autostart.desktop create mode 100644 kcms/autostart/autostart.h create mode 100644 kcms/autostart/autostartconfig.ui create mode 100644 kcms/autostart/autostartitem.cpp create mode 100644 kcms/autostart/autostartitem.h create mode 100644 kcms/bell/CMakeLists.txt create mode 100644 kcms/bell/Messages.sh create mode 100644 kcms/bell/bell.cpp create mode 100644 kcms/bell/bell.desktop create mode 100644 kcms/bell/bell.h create mode 100644 kcms/colors/CMakeLists.txt create mode 100644 kcms/colors/Messages.sh create mode 100644 kcms/colors/README.i18n create mode 100644 kcms/colors/TODO create mode 100644 kcms/colors/colors.desktop create mode 100644 kcms/colors/colorschemes.knsrc create mode 100644 kcms/colors/colorscm.cpp create mode 100644 kcms/colors/colorscm.h create mode 100644 kcms/colors/colorsettings.ui create mode 100644 kcms/colors/preview.ui create mode 100644 kcms/colors/previewwidget.cpp create mode 100644 kcms/colors/previewwidget.h create mode 100644 kcms/colors/schemes/Honeycomb.colors create mode 100644 kcms/colors/schemes/Norway.colors create mode 100644 kcms/colors/schemes/ObsidianCoast.colors create mode 100644 kcms/colors/schemes/Oxygen.colors create mode 100644 kcms/colors/schemes/OxygenCold.colors create mode 100644 kcms/colors/schemes/Steel.colors create mode 100644 kcms/colors/schemes/WontonSoup.colors create mode 100644 kcms/colors/schemes/Zion.colors create mode 100644 kcms/colors/schemes/ZionReversed.colors create mode 100644 kcms/colors/setpreview.ui create mode 100644 kcms/colors/setpreviewwidget.cpp create mode 100644 kcms/colors/setpreviewwidget.h create mode 100644 kcms/dateandtime/CMakeLists.txt create mode 100644 kcms/dateandtime/Messages.sh create mode 100644 kcms/dateandtime/clock.desktop create mode 100644 kcms/dateandtime/dateandtime.ui create mode 100644 kcms/dateandtime/dtime.cpp create mode 100644 kcms/dateandtime/dtime.h create mode 100644 kcms/dateandtime/helper.cpp create mode 100644 kcms/dateandtime/helper.h create mode 100644 kcms/dateandtime/kcmclock_actions.actions create mode 100644 kcms/dateandtime/main.cpp create mode 100644 kcms/dateandtime/main.h create mode 100644 kcms/desktoppaths/CMakeLists.txt create mode 100644 kcms/desktoppaths/Messages.sh create mode 100644 kcms/desktoppaths/desktoppath.desktop create mode 100644 kcms/desktoppaths/globalpaths.cpp create mode 100644 kcms/desktoppaths/globalpaths.h create mode 100644 kcms/desktoptheme/CMakeLists.txt create mode 100644 kcms/desktoptheme/DesktopTheme.ui create mode 100644 kcms/desktoptheme/DesktopThemeDetails.ui create mode 100755 kcms/desktoptheme/Messages.sh create mode 100644 kcms/desktoptheme/desktoptheme.desktop create mode 100644 kcms/desktoptheme/desktopthemedetails.cpp create mode 100644 kcms/desktoptheme/desktopthemedetails.h create mode 100644 kcms/desktoptheme/kcmdesktoptheme.cpp create mode 100644 kcms/desktoptheme/kcmdesktoptheme.h create mode 100644 kcms/desktoptheme/plasma-themes.knsrc create mode 100644 kcms/desktoptheme/thememodel.cpp create mode 100644 kcms/desktoptheme/thememodel.h create mode 100644 kcms/fonts/CMakeLists.txt create mode 100644 kcms/fonts/Messages.sh create mode 100644 kcms/fonts/fonts.cpp create mode 100644 kcms/fonts/fonts.desktop create mode 100644 kcms/fonts/fonts.h create mode 100644 kcms/fonts/kxftconfig.cpp create mode 100644 kcms/fonts/kxftconfig.h create mode 100644 kcms/hardware/CMakeLists.txt create mode 100644 kcms/hardware/display/CMakeLists.txt create mode 100644 kcms/hardware/display/Messages.sh create mode 100644 kcms/hardware/display/display.cpp create mode 100644 kcms/hardware/display/display.desktop create mode 100644 kcms/hardware/display/display.h create mode 100644 kcms/hardware/joystick/CMakeLists.txt create mode 100644 kcms/hardware/joystick/Messages.sh create mode 100644 kcms/hardware/joystick/caldialog.cpp create mode 100644 kcms/hardware/joystick/caldialog.h create mode 100644 kcms/hardware/joystick/joydevice.cpp create mode 100644 kcms/hardware/joystick/joydevice.h create mode 100644 kcms/hardware/joystick/joystick.cpp create mode 100644 kcms/hardware/joystick/joystick.desktop create mode 100644 kcms/hardware/joystick/joystick.h create mode 100644 kcms/hardware/joystick/joywidget.cpp create mode 100644 kcms/hardware/joystick/joywidget.h create mode 100644 kcms/hardware/joystick/poswidget.cpp create mode 100644 kcms/hardware/joystick/poswidget.h create mode 100644 kcms/input/AUTHORS create mode 100644 kcms/input/CMakeLists.txt create mode 100644 kcms/input/ChangeLog create mode 100644 kcms/input/Messages.sh create mode 100644 kcms/input/config-kcontrol-input.h.cmake create mode 100755 kcms/input/consoleUserPerms create mode 100644 kcms/input/core/bitmaps.h create mode 100644 kcms/input/core/themepage.cpp create mode 100644 kcms/input/core/themepage.h create mode 100644 kcms/input/cursor_large.bdf create mode 100644 kcms/input/cursor_large_black.pcf.gz create mode 100644 kcms/input/cursor_large_white.pcf.gz create mode 100644 kcms/input/cursor_small_white.pcf.gz create mode 100644 kcms/input/cursortheme.desktop create mode 100644 kcms/input/kapplymousetheme.cpp create mode 100644 kcms/input/kcmcursortheme.cpp create mode 100644 kcms/input/kcmcursortheme.h create mode 100644 kcms/input/kmousedlg.ui create mode 100644 kcms/input/logitechmouse.cpp create mode 100644 kcms/input/logitechmouse.h create mode 100644 kcms/input/logitechmouse.usermap create mode 100644 kcms/input/logitechmouse_base.ui create mode 100644 kcms/input/main.cpp create mode 100644 kcms/input/mouse.cpp create mode 100644 kcms/input/mouse.desktop create mode 100644 kcms/input/mouse.h create mode 100644 kcms/input/pics/CMakeLists.txt create mode 100644 kcms/input/pics/mouse_lh.png create mode 100644 kcms/input/pics/mouse_lh.svgz create mode 100644 kcms/input/pics/mouse_rh.png create mode 100644 kcms/input/pics/mouse_rh.svgz create mode 100644 kcms/input/xcursor/cursortheme.cpp create mode 100644 kcms/input/xcursor/cursortheme.h create mode 100644 kcms/input/xcursor/itemdelegate.cpp create mode 100644 kcms/input/xcursor/itemdelegate.h create mode 100644 kcms/input/xcursor/previewwidget.cpp create mode 100644 kcms/input/xcursor/previewwidget.h create mode 100644 kcms/input/xcursor/sortproxymodel.cpp create mode 100644 kcms/input/xcursor/sortproxymodel.h create mode 100644 kcms/input/xcursor/thememodel.cpp create mode 100644 kcms/input/xcursor/thememodel.h create mode 100644 kcms/input/xcursor/themepage.cpp create mode 100644 kcms/input/xcursor/themepage.h create mode 100644 kcms/input/xcursor/themepage.ui create mode 100644 kcms/input/xcursor/xcursor.knsrc create mode 100644 kcms/input/xcursor/xcursortheme.cpp create mode 100644 kcms/input/xcursor/xcursortheme.h create mode 100644 kcms/keyboard/CMakeLists.txt create mode 100755 kcms/keyboard/Messages.sh create mode 100644 kcms/keyboard/README create mode 100644 kcms/keyboard/TODO create mode 100644 kcms/keyboard/bindings.cpp create mode 100644 kcms/keyboard/bindings.h create mode 100644 kcms/keyboard/flags.cpp create mode 100644 kcms/keyboard/flags.h create mode 100644 kcms/keyboard/iso_codes.cpp create mode 100644 kcms/keyboard/iso_codes.h create mode 100644 kcms/keyboard/kcm_add_layout_dialog.cpp create mode 100644 kcms/keyboard/kcm_add_layout_dialog.h create mode 100644 kcms/keyboard/kcm_add_layout_dialog.ui create mode 100644 kcms/keyboard/kcm_keyboard.cpp create mode 100644 kcms/keyboard/kcm_keyboard.desktop create mode 100644 kcms/keyboard/kcm_keyboard.h create mode 100644 kcms/keyboard/kcm_keyboard.ui create mode 100644 kcms/keyboard/kcm_keyboard_widget.cpp create mode 100644 kcms/keyboard/kcm_keyboard_widget.h create mode 100644 kcms/keyboard/kcm_view_models.cpp create mode 100644 kcms/keyboard/kcm_view_models.h create mode 100644 kcms/keyboard/kcmmisc.cpp create mode 100644 kcms/keyboard/kcmmisc.h create mode 100644 kcms/keyboard/kcmmiscwidget.ui create mode 100644 kcms/keyboard/keyboard.desktop create mode 100644 kcms/keyboard/keyboard_applet.cpp create mode 100644 kcms/keyboard/keyboard_applet.h create mode 100644 kcms/keyboard/keyboard_config.cpp create mode 100644 kcms/keyboard/keyboard_config.h create mode 100644 kcms/keyboard/keyboard_daemon.cpp create mode 100644 kcms/keyboard/keyboard_daemon.h create mode 100644 kcms/keyboard/keyboard_dbus.h create mode 100644 kcms/keyboard/keyboard_hardware.cpp create mode 100644 kcms/keyboard/keyboard_hardware.h create mode 100644 kcms/keyboard/layout_memory.cpp create mode 100644 kcms/keyboard/layout_memory.h create mode 100644 kcms/keyboard/layout_memory_persister.cpp create mode 100644 kcms/keyboard/layout_memory_persister.h create mode 100644 kcms/keyboard/layout_tray_icon.cpp create mode 100644 kcms/keyboard/layout_tray_icon.h create mode 100644 kcms/keyboard/layout_widget.cpp create mode 100644 kcms/keyboard/layout_widget.h create mode 100644 kcms/keyboard/layouts_menu.cpp create mode 100644 kcms/keyboard/layouts_menu.h create mode 100644 kcms/keyboard/numlockx.c create mode 100644 kcms/keyboard/pics/CMakeLists.txt create mode 100644 kcms/keyboard/pics/epo.png create mode 100644 kcms/keyboard/plasma_applet_keyboard.desktop create mode 100644 kcms/keyboard/preview/TODO create mode 100644 kcms/keyboard/preview/kbpreviewframe.cpp create mode 100644 kcms/keyboard/preview/kbpreviewframe.h create mode 100644 kcms/keyboard/preview/keyaliases.cpp create mode 100644 kcms/keyboard/preview/keyaliases.h create mode 100644 kcms/keyboard/preview/keyboardlayout.cpp create mode 100644 kcms/keyboard/preview/keyboardlayout.h create mode 100644 kcms/keyboard/preview/keyboardpainter.cpp create mode 100644 kcms/keyboard/preview/keyboardpainter.h create mode 100644 kcms/keyboard/preview/keysym2ucs.cpp create mode 100644 kcms/keyboard/preview/keysym2ucs.h create mode 100644 kcms/keyboard/preview/keysymbols.cpp create mode 100644 kcms/keyboard/preview/keysymbols.h create mode 100644 kcms/keyboard/preview/keysymhelper.cpp create mode 100644 kcms/keyboard/preview/keysymhelper.h create mode 100644 kcms/keyboard/tests/CMakeLists.txt create mode 100644 kcms/keyboard/tests/config/base.1.1.xml create mode 100644 kcms/keyboard/tests/config/base.bad.xml create mode 100644 kcms/keyboard/tests/config/base.xml create mode 100644 kcms/keyboard/tests/flags_test.cpp create mode 100644 kcms/keyboard/tests/iso_codes_test.cpp create mode 100644 kcms/keyboard/tests/keyboard_daemon_test.cpp create mode 100644 kcms/keyboard/tests/layout_memory_persister_test.cpp create mode 100644 kcms/keyboard/tests/xkb_rules_test.cpp create mode 100644 kcms/keyboard/x11_helper.cpp create mode 100644 kcms/keyboard/x11_helper.h create mode 100644 kcms/keyboard/xinput_helper.cpp create mode 100644 kcms/keyboard/xinput_helper.h create mode 100644 kcms/keyboard/xkb_helper.cpp create mode 100644 kcms/keyboard/xkb_helper.h create mode 100644 kcms/keyboard/xkb_rules.cpp create mode 100644 kcms/keyboard/xkb_rules.h create mode 100644 kcms/keys/CMakeLists.txt create mode 100644 kcms/keys/ChangeLog create mode 100644 kcms/keys/Messages.sh create mode 100644 kcms/keys/README create mode 100644 kcms/keys/export_scheme_dialog.cpp create mode 100644 kcms/keys/export_scheme_dialog.h create mode 100644 kcms/keys/export_scheme_dialog.ui create mode 100644 kcms/keys/globalshortcuts.cpp create mode 100644 kcms/keys/globalshortcuts.h create mode 100644 kcms/keys/keys.desktop create mode 100644 kcms/keys/kglobalshortcutseditor.cpp create mode 100644 kcms/keys/kglobalshortcutseditor.h create mode 100644 kcms/keys/kglobalshortcutseditor.ui create mode 100644 kcms/keys/schemes/kde3.kksrc create mode 100644 kcms/keys/schemes/kde4.kksrc create mode 100644 kcms/keys/schemes/mac4.kksrc create mode 100644 kcms/keys/schemes/old_kde3.kksrc create mode 100644 kcms/keys/schemes/old_kde4.kksrc create mode 100644 kcms/keys/schemes/old_mac4.kksrc create mode 100644 kcms/keys/schemes/old_unix3.kksrc create mode 100644 kcms/keys/schemes/old_win3.kksrc create mode 100644 kcms/keys/schemes/old_win4.kksrc create mode 100644 kcms/keys/schemes/old_wm3.kksrc create mode 100755 kcms/keys/schemes/split_kksrc create mode 100644 kcms/keys/schemes/unix3.kksrc create mode 100644 kcms/keys/schemes/win3.kksrc create mode 100644 kcms/keys/schemes/win4.kksrc create mode 100644 kcms/keys/schemes/wm3.kksrc create mode 100644 kcms/keys/select_scheme_dialog.cpp create mode 100644 kcms/keys/select_scheme_dialog.h create mode 100644 kcms/keys/select_scheme_dialog.ui create mode 100644 kcms/kfontinst/AUTHORS create mode 100644 kcms/kfontinst/CMakeLists.txt create mode 100644 kcms/kfontinst/ChangeLog create mode 100644 kcms/kfontinst/Messages.sh create mode 100644 kcms/kfontinst/apps/CMakeLists.txt create mode 100644 kcms/kfontinst/apps/CreateParent.h create mode 100644 kcms/kfontinst/apps/Installer.cpp create mode 100644 kcms/kfontinst/apps/Installer.h create mode 100644 kcms/kfontinst/apps/Printer.cpp create mode 100644 kcms/kfontinst/apps/Printer.h create mode 100644 kcms/kfontinst/apps/Viewer.cpp create mode 100644 kcms/kfontinst/apps/Viewer.h create mode 100644 kcms/kfontinst/apps/installfont.desktop create mode 100755 kcms/kfontinst/apps/kfontview.desktop create mode 100644 kcms/kfontinst/apps/kfontviewui.rc create mode 100644 kcms/kfontinst/apps/ox16-app-kfontview.png create mode 100644 kcms/kfontinst/apps/ox22-app-kfontview.png create mode 100644 kcms/kfontinst/apps/ox32-app-kfontview.png create mode 100644 kcms/kfontinst/apps/ox48-app-kfontview.png create mode 100644 kcms/kfontinst/apps/ox64-app-kfontview.png create mode 100644 kcms/kfontinst/apps/oxsc-app-kfontview.svgz create mode 100644 kcms/kfontinst/config-fontinst.h.cmake create mode 100644 kcms/kfontinst/dbus/CMakeLists.txt create mode 100644 kcms/kfontinst/dbus/FcConfig.cpp create mode 100644 kcms/kfontinst/dbus/FcConfig.h create mode 100644 kcms/kfontinst/dbus/Folder.cpp create mode 100644 kcms/kfontinst/dbus/Folder.h create mode 100644 kcms/kfontinst/dbus/FontInst.cpp create mode 100644 kcms/kfontinst/dbus/FontInst.h create mode 100644 kcms/kfontinst/dbus/FontinstIface.cpp create mode 100644 kcms/kfontinst/dbus/FontinstIface.h create mode 100644 kcms/kfontinst/dbus/Helper.cpp create mode 100644 kcms/kfontinst/dbus/Helper.h create mode 100644 kcms/kfontinst/dbus/Main.cpp create mode 100644 kcms/kfontinst/dbus/Utils.cpp create mode 100644 kcms/kfontinst/dbus/Utils.h create mode 100644 kcms/kfontinst/dbus/fontinst.actions create mode 100755 kcms/kfontinst/dbus/fontinst_x11 create mode 100644 kcms/kfontinst/dbus/org.kde.fontinst.service.cmake create mode 100644 kcms/kfontinst/dbus/org.kde.fontinst.system-service.cmake create mode 100644 kcms/kfontinst/dbus/org.kde.fontinst.xml create mode 100644 kcms/kfontinst/kcmfontinst/ActionLabel.cpp create mode 100644 kcms/kfontinst/kcmfontinst/ActionLabel.h create mode 100644 kcms/kfontinst/kcmfontinst/CMakeLists.txt create mode 100644 kcms/kfontinst/kcmfontinst/DuplicatesDialog.cpp create mode 100644 kcms/kfontinst/kcmfontinst/DuplicatesDialog.h create mode 100644 kcms/kfontinst/kcmfontinst/FcQuery.cpp create mode 100644 kcms/kfontinst/kcmfontinst/FcQuery.h create mode 100644 kcms/kfontinst/kcmfontinst/FontFilter.cpp create mode 100644 kcms/kfontinst/kcmfontinst/FontFilter.h create mode 100644 kcms/kfontinst/kcmfontinst/FontFilterProxyStyle.cpp create mode 100644 kcms/kfontinst/kcmfontinst/FontFilterProxyStyle.h create mode 100644 kcms/kfontinst/kcmfontinst/FontInstInterface.h create mode 100644 kcms/kfontinst/kcmfontinst/FontList.cpp create mode 100644 kcms/kfontinst/kcmfontinst/FontList.h create mode 100644 kcms/kfontinst/kcmfontinst/FontsPackage.cpp create mode 100644 kcms/kfontinst/kcmfontinst/FontsPackage.h create mode 100644 kcms/kfontinst/kcmfontinst/GroupList.cpp create mode 100644 kcms/kfontinst/kcmfontinst/GroupList.h create mode 100644 kcms/kfontinst/kcmfontinst/JobRunner.cpp create mode 100644 kcms/kfontinst/kcmfontinst/JobRunner.h create mode 100644 kcms/kfontinst/kcmfontinst/KCmFontInst.cpp create mode 100644 kcms/kfontinst/kcmfontinst/KCmFontInst.h create mode 100644 kcms/kfontinst/kcmfontinst/PreviewList.cpp create mode 100644 kcms/kfontinst/kcmfontinst/PreviewList.h create mode 100644 kcms/kfontinst/kcmfontinst/PrintDialog.cpp create mode 100644 kcms/kfontinst/kcmfontinst/PrintDialog.h create mode 100644 kcms/kfontinst/kcmfontinst/fontinst.desktop create mode 100644 kcms/kfontinst/kcmfontinst/kfontinst.knsrc create mode 100644 kcms/kfontinst/kcmfontinst/ox16-action-addfont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox16-action-disablefont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox16-action-enablefont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox16-action-fontstatus.png create mode 100644 kcms/kfontinst/kcmfontinst/ox22-action-addfont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox22-action-disablefont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox22-action-enablefont.png create mode 100644 kcms/kfontinst/kcmfontinst/ox22-action-fontstatus.png create mode 100644 kcms/kfontinst/kcmfontinst/oxsc-action-addfont.svgz create mode 100644 kcms/kfontinst/kcmfontinst/oxsc-action-disablefont.svgz create mode 100644 kcms/kfontinst/kcmfontinst/oxsc-action-enablefont.svgz create mode 100644 kcms/kfontinst/kcmfontinst/oxsc-action-fontstatus.svgz create mode 100644 kcms/kfontinst/kio/CMakeLists.txt create mode 100644 kcms/kfontinst/kio/FontInstInterface.cpp create mode 100644 kcms/kfontinst/kio/FontInstInterface.h create mode 100644 kcms/kfontinst/kio/KioFonts.cpp create mode 100644 kcms/kfontinst/kio/KioFonts.h create mode 100644 kcms/kfontinst/kio/fonts.desktop create mode 100644 kcms/kfontinst/kio/fonts.protocol create mode 100644 kcms/kfontinst/kio/ox128-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/ox16-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/ox22-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/ox32-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/ox48-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/ox64-mimetypes-fonts-package.png create mode 100644 kcms/kfontinst/kio/oxsc-mimetypes-fonts-package.svgz create mode 100644 kcms/kfontinst/lib/CMakeLists.txt create mode 100644 kcms/kfontinst/lib/Family.cpp create mode 100644 kcms/kfontinst/lib/Family.h create mode 100644 kcms/kfontinst/lib/Fc.cpp create mode 100644 kcms/kfontinst/lib/Fc.h create mode 100644 kcms/kfontinst/lib/FcEngine.cpp create mode 100644 kcms/kfontinst/lib/FcEngine.h create mode 100644 kcms/kfontinst/lib/File.cpp create mode 100644 kcms/kfontinst/lib/File.h create mode 100644 kcms/kfontinst/lib/KfiConstants.h create mode 100644 kcms/kfontinst/lib/Misc.cpp create mode 100644 kcms/kfontinst/lib/Misc.h create mode 100644 kcms/kfontinst/lib/Style.cpp create mode 100644 kcms/kfontinst/lib/Style.h create mode 100644 kcms/kfontinst/lib/WritingSystems.cpp create mode 100644 kcms/kfontinst/lib/WritingSystems.h create mode 100644 kcms/kfontinst/lib/XmlStrings.h create mode 100644 kcms/kfontinst/lib/kfontinst_export.h create mode 100644 kcms/kfontinst/oxsc-app-preferences-desktop-font-installer.svgz create mode 100644 kcms/kfontinst/thumbnail/CMakeLists.txt create mode 100644 kcms/kfontinst/thumbnail/FontThumbnail.cpp create mode 100644 kcms/kfontinst/thumbnail/FontThumbnail.h create mode 100644 kcms/kfontinst/thumbnail/fontthumbnail.desktop create mode 100644 kcms/kfontinst/viewpart/CMakeLists.txt create mode 100644 kcms/kfontinst/viewpart/COPYING.UNICODE create mode 100644 kcms/kfontinst/viewpart/CharTip.cpp create mode 100644 kcms/kfontinst/viewpart/CharTip.h create mode 100644 kcms/kfontinst/viewpart/FontPreview.cpp create mode 100644 kcms/kfontinst/viewpart/FontPreview.h create mode 100644 kcms/kfontinst/viewpart/FontViewPart.cpp create mode 100644 kcms/kfontinst/viewpart/FontViewPart.h create mode 100644 kcms/kfontinst/viewpart/PreviewSelectAction.cpp create mode 100644 kcms/kfontinst/viewpart/PreviewSelectAction.h create mode 100644 kcms/kfontinst/viewpart/UnicodeBlocks.h create mode 100644 kcms/kfontinst/viewpart/UnicodeCategories.h create mode 100644 kcms/kfontinst/viewpart/UnicodeScripts.h create mode 100644 kcms/kfontinst/viewpart/download-unicode-files.sh create mode 100644 kcms/kfontinst/viewpart/generate-unicode-tables.pl create mode 100644 kcms/kfontinst/viewpart/kfontviewpart.desktop create mode 100644 kcms/kfontinst/viewpart/kfontviewpart.rc create mode 100644 kcms/krdb/AUTHORS create mode 100644 kcms/krdb/CMakeLists.txt create mode 100644 kcms/krdb/Messages.sh create mode 100644 kcms/krdb/ad/AAAAAAGeneral.ad create mode 100644 kcms/krdb/ad/AAAMotif.ad create mode 100644 kcms/krdb/ad/AAATk.ad create mode 100644 kcms/krdb/ad/AAAXaw.ad create mode 100644 kcms/krdb/ad/AcroRead.ad create mode 100644 kcms/krdb/ad/CMakeLists.txt create mode 100644 kcms/krdb/ad/Editres.ad create mode 100644 kcms/krdb/ad/Emacs.ad create mode 100644 kcms/krdb/ad/GV.ad create mode 100644 kcms/krdb/ad/ML.ad create mode 100644 kcms/krdb/ad/Nedit.ad create mode 100644 kcms/krdb/ad/Netscape.ad create mode 100644 kcms/krdb/ad/README create mode 100644 kcms/krdb/ad/RVPlayer.ad create mode 100644 kcms/krdb/ad/WPerfect.ad create mode 100644 kcms/krdb/ad/XCalc.ad create mode 100644 kcms/krdb/ad/XOsview.ad create mode 100644 kcms/krdb/ad/XTerm.ad create mode 100644 kcms/krdb/ad/XV.ad create mode 100644 kcms/krdb/ad/Xawtv.ad create mode 100644 kcms/krdb/ad/Xdvi.ad create mode 100644 kcms/krdb/ad/Xpdf.ad create mode 100755 kcms/krdb/ad/krdb create mode 100644 kcms/krdb/krdb.cpp create mode 100644 kcms/krdb/krdb.h create mode 100644 kcms/krdb/krdb_clearlibrarypath.cpp create mode 100644 kcms/krdb/krdb_libpathwipe.upd create mode 100644 kcms/krdb/pics/CMakeLists.txt create mode 100644 kcms/krdb/pics/lo-energy.png create mode 100644 kcms/krdb/pics/logo.png create mode 100644 kcms/krdb/pics/mini-world.png create mode 100644 kcms/krdb/themes/CMakeLists.txt create mode 100644 kcms/krdb/themes/HighContrastDark-big/CMakeLists.txt create mode 100644 kcms/krdb/themes/HighContrastDark-big/HighContrastDark-big.preview.png create mode 100644 kcms/krdb/themes/HighContrastDark-big/HighContrastDark-big.xml create mode 100644 kcms/krdb/themes/HighContrastDark/CMakeLists.txt create mode 100644 kcms/krdb/themes/HighContrastDark/HighContrastDark.preview.png create mode 100644 kcms/krdb/themes/HighContrastDark/HighContrastDark.xml create mode 100644 kcms/krdb/themes/HighContrastLight-big/CMakeLists.txt create mode 100644 kcms/krdb/themes/HighContrastLight-big/HighContrastLight-big.preview.png create mode 100644 kcms/krdb/themes/HighContrastLight-big/HighContrastLight-big.xml create mode 100644 kcms/krdb/themes/HighContrastLight/CMakeLists.txt create mode 100644 kcms/krdb/themes/HighContrastLight/HighContrastLight.preview.png create mode 100644 kcms/krdb/themes/HighContrastLight/HighContrastLight.xml create mode 100644 kcms/krdb/themes/KDE_Classic/CMakeLists.txt create mode 100644 kcms/krdb/themes/KDE_Classic/KDE_Classic.preview.png create mode 100644 kcms/krdb/themes/KDE_Classic/KDE_Classic.xml create mode 100644 kcms/krdb/themes/Keramik/CMakeLists.txt create mode 100644 kcms/krdb/themes/Keramik/Keramik.preview.png create mode 100644 kcms/krdb/themes/Keramik/Keramik.xml create mode 100644 kcms/krdb/themes/Plastik/CMakeLists.txt create mode 100644 kcms/krdb/themes/Plastik/Plastik.preview.png create mode 100644 kcms/krdb/themes/Plastik/Plastik.xml create mode 100644 kcms/krdb/themes/Platinum/CMakeLists.txt create mode 100644 kcms/krdb/themes/Platinum/Platinum.preview.png create mode 100644 kcms/krdb/themes/Platinum/Platinum.xml create mode 100644 kcms/krdb/themes/Redmond/CMakeLists.txt create mode 100644 kcms/krdb/themes/Redmond/Redmond.preview.png create mode 100644 kcms/krdb/themes/Redmond/Redmond.xml create mode 100644 kcms/krdb/themes/Sunshine/CMakeLists.txt create mode 100644 kcms/krdb/themes/Sunshine/Sunshine.preview.png create mode 100644 kcms/krdb/themes/Sunshine/Sunshine.xml create mode 100644 kcms/krdb/themes/YellowOnBlue-big/CMakeLists.txt create mode 100644 kcms/krdb/themes/YellowOnBlue-big/YellowOnBlue-big.preview.png create mode 100644 kcms/krdb/themes/YellowOnBlue-big/YellowOnBlue-big.xml create mode 100644 kcms/krdb/themes/YellowOnBlue/CMakeLists.txt create mode 100644 kcms/krdb/themes/YellowOnBlue/YellowOnBlue.preview.png create mode 100644 kcms/krdb/themes/YellowOnBlue/YellowOnBlue.xml create mode 100644 kcms/launch/CMakeLists.txt create mode 100644 kcms/launch/Messages.sh create mode 100644 kcms/launch/interface_util.h create mode 100644 kcms/launch/kcmlaunch.cpp create mode 100644 kcms/launch/kcmlaunch.desktop create mode 100644 kcms/launch/kcmlaunch.h create mode 100644 kcms/standard_actions/CMakeLists.txt create mode 100644 kcms/standard_actions/Messages.sh create mode 100644 kcms/standard_actions/standard_actions.desktop create mode 100644 kcms/standard_actions/standard_actions_module.cpp create mode 100644 kcms/standard_actions/standard_actions_module.h create mode 100644 kcms/style/CMakeLists.txt create mode 100644 kcms/style/Messages.sh create mode 100644 kcms/style/finetuning.ui create mode 100644 kcms/style/kcmstyle.cpp create mode 100644 kcms/style/kcmstyle.h create mode 100644 kcms/style/kcmstyle.notifyrc create mode 100644 kcms/style/style.desktop create mode 100644 kcms/style/styleconfdialog.cpp create mode 100644 kcms/style/styleconfdialog.h create mode 100644 kcms/style/stylepreview.ui create mode 100644 ktouchpadenabler/CMakeLists.txt create mode 100644 ktouchpadenabler/COPYING create mode 100644 ktouchpadenabler/Messages.sh create mode 100644 ktouchpadenabler/ktouchpadenabler.desktop create mode 100644 ktouchpadenabler/ktouchpadenabler.kcfg create mode 100644 ktouchpadenabler/ktouchpadenabler_daemon.cpp create mode 100644 ktouchpadenabler/ktouchpadenabler_daemon.h create mode 100644 ktouchpadenabler/settings.kcfgc create mode 100644 runners/CMakeLists.txt create mode 100644 runners/plasma-desktop/CMakeLists.txt create mode 100755 runners/plasma-desktop/Messages.sh create mode 100644 runners/plasma-desktop/plasma-desktop-runner.cpp create mode 100644 runners/plasma-desktop/plasma-desktop-runner.h create mode 100644 runners/plasma-desktop/plasma-runner-plasma-desktop.desktop create mode 100644 solid-actions-kcm/ActionEditor.cpp create mode 100644 solid-actions-kcm/ActionEditor.h create mode 100644 solid-actions-kcm/ActionEditor.ui create mode 100644 solid-actions-kcm/ActionItem.cpp create mode 100644 solid-actions-kcm/ActionItem.h create mode 100644 solid-actions-kcm/ActionModel.cpp create mode 100644 solid-actions-kcm/ActionModel.h create mode 100644 solid-actions-kcm/AddAction.ui create mode 100644 solid-actions-kcm/CMakeLists.txt create mode 100644 solid-actions-kcm/DesktopFileGenerator.cpp create mode 100644 solid-actions-kcm/Messages.sh create mode 100644 solid-actions-kcm/PredicateItem.cpp create mode 100644 solid-actions-kcm/PredicateItem.h create mode 100644 solid-actions-kcm/PredicateModel.cpp create mode 100644 solid-actions-kcm/PredicateModel.h create mode 100644 solid-actions-kcm/SolidActionData.cpp create mode 100644 solid-actions-kcm/SolidActionData.h create mode 100644 solid-actions-kcm/SolidActions.cpp create mode 100644 solid-actions-kcm/SolidActions.h create mode 100644 solid-actions-kcm/SolidActions.ui create mode 100644 solid-actions-kcm/device-actions/CMakeLists.txt create mode 100644 solid-actions-kcm/device-actions/solid-device-AcAdapter.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-AudioInterface.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Battery.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Block.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Button.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Camera.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-DvbInterface.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-NetworkInterface.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-OpticalDisc.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-OpticalDrive.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-PortableMediaPlayer.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Processor.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-SerialInterface.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-SmartCardReader.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-StorageAccess.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-StorageDrive.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-StorageVolume.desktop create mode 100644 solid-actions-kcm/device-actions/solid-device-Video.desktop create mode 100644 solid-actions-kcm/solid-action-template.desktop create mode 100644 solid-actions-kcm/solid-actions.desktop create mode 100644 solid-actions-kcm/solid-device-type.desktop create mode 100644 toolboxes/CMakeLists.txt create mode 100644 toolboxes/desktoptoolbox/Messages.sh create mode 100644 toolboxes/desktoptoolbox/contents/config/main.xml create mode 100644 toolboxes/desktoptoolbox/contents/ui/ActionDelegate.qml create mode 100644 toolboxes/desktoptoolbox/contents/ui/ToolBoxButton.qml create mode 100644 toolboxes/desktoptoolbox/contents/ui/ToolBoxItem.qml create mode 100644 toolboxes/desktoptoolbox/contents/ui/ToolBoxRoot.qml create mode 100644 toolboxes/desktoptoolbox/metadata.desktop create mode 100644 toolboxes/paneltoolbox/contents/ui/main.qml create mode 100644 toolboxes/paneltoolbox/metadata.desktop create mode 100644 toolboxes/plasma-toolbox-paneltoolbox.desktop diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..bf6d52e066 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,109 @@ +project(plasma-desktop) + +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +set(QT_MIN_VERSION "5.2.0") + +find_package(ECM 0.0.11 REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) + +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings) +include(ECMInstallIcons) +include(FeatureSummary) +include(CheckIncludeFiles) + +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS + Quick + DBus + Widgets + X11Extras + Concurrent +) + +find_package(KF5 CONFIG REQUIRED COMPONENTS + Plasma + DocTools + I18n + KCMUtils + NewStuff + KDE4Support + NotifyConfig + Su + Runner +) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + find_package(KDecorations REQUIRED CONFIG) + find_package(LibKWorkspace CONFIG REQUIRED) + find_package(LibTaskManager CONFIG REQUIRED) + find_package(KWinDBusInterface CONFIG REQUIRED) + find_package(ScreenSaverDBusInterface CONFIG REQUIRED) + find_package(KRunnerAppDBusInterface CONFIG REQUIRED) + find_package(KSMServerDBusInterface CONFIG REQUIRED) +endif() + +find_package(KF5Activities ${KF5_VERSION}) +set_package_properties(KF5Activities PROPERTIES DESCRIPTION "management of Plasma activities" + TYPE OPTIONAL + PURPOSE "Needed by activity related plasmoids and the pager." + ) + +find_package(USB) +set(HAVE_LIBUSB ${LIBUSB_FOUND}) +set_package_properties(USB PROPERTIES DESCRIPTION "User level access to USB devices" + URL "http://libusb.sourceforge.net" + TYPE OPTIONAL + PURPOSE "Provides Logitech mouse support in KControl." + ) + +find_package(Fontconfig) +set_package_properties(Fontconfig PROPERTIES DESCRIPTION "Font access configuration library" + URL "http://www.freedesktop.org/wiki/Software/fontconfig" + TYPE OPTIONAL + PURPOSE "Needed to build font configuration and installation tools" + ) + +find_package(X11) +set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" + URL "http://www.x.org" + TYPE OPTIONAL + PURPOSE "Required for building the X11 based workspace" + ) +if(X11_FOUND) + find_package(XCB REQUIRED COMPONENTS XCB XFIXES DAMAGE COMPOSITE SHAPE SYNC RENDER RANDR KEYSYMS IMAGE SHM XTEST) + set_package_properties(XCB PROPERTIES TYPE REQUIRED) + find_package(XCB COMPONENTS ICCCM) + add_feature_info("XCB-ICCCM" XCB_ICCCM_FOUND "Required for building test applications for KWin") +endif() + +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +include(ConfigureChecks.cmake) +configure_file(config-workspace.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-workspace.h) +configure_file(config-unix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-unix.h ) +configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) + +set(PLASMADESKTOP_VERSION_MAJOR 4) +set(PLASMADESKTOP_VERSION_MINOR 95) +set(PLASMADESKTOP_VERSION_PATCH 0) +set(PLASMADESKTOP_VERSION ${PLASMADESKTOP_VERSION_MAJOR}.${PLASMADESKTOP_VERSION_MINOR}.${PLASMADESKTOP_VERSION_PATCH} ) + +set(GENERIC_LIB_SOVERSION ${PLASMADESKTOP_VERSION_MAJOR}) +set(GENERIC_LIB_VERSION "${PLASMADESKTOP_VERSION_MAJOR}.${PLASMADESKTOP_VERSION_MINOR}.${PLASMADESKTOP_VERSION_PATCH}") + +plasma_install_package(desktoppackage org.kde.desktop plasma/shells shell) + +add_subdirectory(doc) +# add_subdirectory(ktouchpadenabler) +# add_subdirectory(solid-actions-kcm) + +# add_subdirectory(runners) +add_subdirectory(containments) +add_subdirectory(toolboxes) +add_subdirectory(applets) +add_subdirectory(kcms) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) +endif() diff --git a/COPYING b/COPYING new file mode 100644 index 0000000000..5185fd3f31 --- /dev/null +++ b/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/COPYING.DOC b/COPYING.DOC new file mode 100644 index 0000000000..4a0fe1c8de --- /dev/null +++ b/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/ConfigureChecks.cmake b/ConfigureChecks.cmake new file mode 100644 index 0000000000..f0a23bf236 --- /dev/null +++ b/ConfigureChecks.cmake @@ -0,0 +1,54 @@ +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) + +find_program(some_x_program NAMES iceauth xrdb xterm) +if (NOT some_x_program) + set(some_x_program /usr/bin/xrdb) + message(WARNING "Warning: Could not determine X binary directory. Assuming /usr/bin.") +endif (NOT some_x_program) +get_filename_component(proto_xbindir "${some_x_program}" PATH) +get_filename_component(XBINDIR "${proto_xbindir}" ABSOLUTE) +get_filename_component(xrootdir "${XBINDIR}" PATH) +set(XLIBDIR "${xrootdir}/lib/X11") + +check_function_exists(getpassphrase HAVE_GETPASSPHRASE) +check_function_exists(vsyslog HAVE_VSYSLOG) +check_function_exists(statvfs HAVE_STATVFS) + +check_include_files(limits.h HAVE_LIMITS_H) +check_include_files(sys/time.h HAVE_SYS_TIME_H) # ksmserver, ksplashml, sftp +check_include_files(stdint.h HAVE_STDINT_H) # kcontrol/kfontinst +check_include_files("sys/stat.h;sys/vfs.h" HAVE_SYS_VFS_H) # statvfs for plasma/solid +check_include_files("sys/stat.h;sys/statvfs.h" HAVE_SYS_STATVFS_H) # statvfs for plasma/solid +check_include_files(sys/param.h HAVE_SYS_PARAM_H) +check_include_files("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H) +check_include_files("sys/types.h;sys/statfs.h" HAVE_SYS_STATFS_H) +check_include_files(unistd.h HAVE_UNISTD_H) +check_include_files(malloc.h HAVE_MALLOC_H) +check_function_exists(statfs HAVE_STATFS) +macro_bool_to_01(FONTCONFIG_FOUND HAVE_FONTCONFIG) # kcontrol/{fonts,kfontinst} +macro_bool_to_01(FREETYPE_FOUND HAVE_FREETYPE) # kcontrol/fonts +macro_bool_to_01(OPENGL_FOUND HAVE_OPENGL) # kwin +macro_bool_to_01(X11_XShm_FOUND HAVE_XSHM) # kwin, ksplash +macro_bool_to_01(X11_XTest_FOUND HAVE_XTEST) # khotkeys, kxkb, kdm +macro_bool_to_01(X11_Xcomposite_FOUND HAVE_XCOMPOSITE) # kicker, kwin +macro_bool_to_01(X11_Xcursor_FOUND HAVE_XCURSOR) # many uses +macro_bool_to_01(X11_Xdamage_FOUND HAVE_XDAMAGE) # kwin +macro_bool_to_01(X11_Xfixes_FOUND HAVE_XFIXES) # klipper, kicker, kwin +macro_bool_to_01(X11_Xinerama_FOUND HAVE_XINERAMA) +macro_bool_to_01(X11_Xrandr_FOUND HAVE_XRANDR) # kwin +macro_bool_to_01(X11_Xrender_FOUND HAVE_XRENDER) # kcontrol/style, kicker +macro_bool_to_01(X11_xf86misc_FOUND HAVE_XF86MISC) # kdesktop and kcontrol/lock +macro_bool_to_01(X11_dpms_FOUND HAVE_DPMS) # kdesktop +macro_bool_to_01(X11_XSync_FOUND HAVE_XSYNC) # kwin + +set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) + +check_function_exists(getpeereid HAVE_GETPEEREID) # kdesu +check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker + +set(CMAKE_REQUIRED_INCLUDES ${X11_Xrandr_INCLUDE_PATH}/Xrandr.h) +set(CMAKE_REQUIRED_LIBRARIES ${X11_Xrandr_LIB}) +check_function_exists(XRRGetScreenSizeRange XRANDR_1_2_FOUND) +macro_bool_to_01(XRANDR_1_2_FOUND HAS_RANDR_1_2) +check_function_exists(XRRGetScreenResourcesCurrent XRANDR_1_3_FOUND) +macro_bool_to_01(XRANDR_1_3_FOUND HAS_RANDR_1_3) diff --git a/HACKING b/HACKING new file mode 100644 index 0000000000..fcea06b952 --- /dev/null +++ b/HACKING @@ -0,0 +1,21 @@ +Understanding the Code +====================== +Various design documents can be found in the design/ directory and API documentation +generated from the headers is hosted at http://api.kde.org. + +Finding the Team +================ +You can find the Plasma team on: + + * our development mailing list at plasma-devel@kde.org + * our irc channel in #plasma on irc.freenode.net + +Coding Style +============ +New code should follow the kdelibs hacking style, as found here: + + http://techbase.kde.org/Policies/Kdelibs_Coding_Style + +Existing code that does not follow this style should be migrated over during +editting. + diff --git a/Mainpage.dox b/Mainpage.dox new file mode 100644 index 0000000000..acf9e85cb8 --- /dev/null +++ b/Mainpage.dox @@ -0,0 +1,21 @@ +/** @mainpage Plasma + +Documentation for the Plasma libraries and utilities. +

+- engines + (classes)\n + Engines for Plasma +- applets + (classes)\n + Plasma Applets +- animators + (classes)\n + Plasma Animators + + +*/ + +// DOXYGEN_SET_PROJECT_NAME = Plasma +// DOXYGEN_SET_RECURSIVE = YES +// DOXYGEN_EXCLUDE = engines applets animators +// vim:ts=4:sw=4:expandtab:filetype=doxygen diff --git a/applets/CMakeLists.txt b/applets/CMakeLists.txt new file mode 100644 index 0000000000..875b426723 --- /dev/null +++ b/applets/CMakeLists.txt @@ -0,0 +1,13 @@ +add_subdirectory(kickoff) +plasma_install_package(trash org.kde.plasma.trash) + +if(NOT WIN32) + # tasks and windowlist depend on libs/taskmanager + add_subdirectory(taskmanager) + plasma_install_package(window-list org.kde.plasma.windowlist) + +if(KF5Activities_FOUND) + add_subdirectory(pager) + add_subdirectory(showActivityManager) +endif() +endif() diff --git a/applets/kickoff/CMakeLists.txt b/applets/kickoff/CMakeLists.txt new file mode 100644 index 0000000000..8d21e41bec --- /dev/null +++ b/applets/kickoff/CMakeLists.txt @@ -0,0 +1,62 @@ + +####################################################################################### +# Package +plasma_install_package(package org.kde.plasma.kickoff) + + +####################################################################################### +# Kickoff Library + +set(libkickoff_SRCS + core/applicationmodel.cpp + core/favoritesmodel.cpp + core/itemhandlers.cpp + core/kickoffabstractmodel.cpp + core/kickoffmodel.cpp + core/kickoffproxymodel.cpp + core/kickoffplugin.cpp + core/krunnermodel.cpp + core/leavemodel.cpp + core/models.cpp + core/recentapplications.cpp + core/recentlyusedmodel.cpp + core/systemmodel.cpp + core/kuserproxy.cpp + core/urlitemlauncher.cpp +) + +qt5_add_dbus_adaptor(libkickoff_SRCS core/org.kde.kickoff.xml core/applicationmodel.h Kickoff::ApplicationModel) +qt5_add_dbus_adaptor(libkickoff_SRCS core/org.kde.kickoff.recent.xml core/recentlyusedmodel.h Kickoff::RecentlyUsedModel) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${plasma-desktop_SOURCE_DIR}) + set(screensaver_xml ${SCREENSAVER_DBUS_INTERFACE}) + set(krunner_xml ${KRUNNERAPP_INTERFACE}) + set(ksmserver_xml ${KSMSERVER_DBUS_INTERFACE}) +else() + set(screensaver_xml ${CMAKE_SOURCE_DIR}/plasma-workspace/ksmserver/screenlocker/dbus/org.freedesktop.ScreenSaver.xml) + set(krunner_xml ${CMAKE_SOURCE_DIR}/plasma-workspace/krunner/dbus/org.kde.krunner.App.xml) + set(ksmserver_xml ${CMAKE_SOURCE_DIR}/plasma-workspace/ksmserver/org.kde.KSMServerInterface.xml) +endif() + +qt5_add_dbus_interface(libkickoff_SRCS ${screensaver_xml} screensaver_interface) +qt5_add_dbus_interface(libkickoff_SRCS ${krunner_xml} krunner_interface) +qt5_add_dbus_interface(libkickoff_SRCS ${ksmserver_xml} ksmserver_interface) + +install(FILES core/qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/kickoff) +add_library(kickoffplugin SHARED ${libkickoff_SRCS}) +target_link_libraries(kickoffplugin + Qt5::Core + Qt5::Qml + Qt5::DBus + KF5::CoreAddons + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::KIOFileWidgets + KF5::Runner + KF5::Solid + KF5::Service + KF5::KDE4Support + PW::KWorkspace) +install(TARGETS kickoffplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/kickoff) + diff --git a/applets/kickoff/DESIGN-GOALS b/applets/kickoff/DESIGN-GOALS new file mode 100644 index 0000000000..4c7adc46bf --- /dev/null +++ b/applets/kickoff/DESIGN-GOALS @@ -0,0 +1,71 @@ + +Project Proposal: Kickoff KDE 4 Rewrite + +This is a re-implementation of the Kickoff menu for KDE 3 originally created +by the OpenSuSE team. + +Overall goals: + +1. Implement the Kickoff user interface using Qt/KDE 4 technology + +2. Make it easy for distributions to modify the menu contents + +3. Make it easy for distributions to add their own branding + +Detailed goals: + +1. Implement the Kickoff user interface using Qt/KDE 4 technology + + -> Clean separation of core and user interface + -> eg. Make good use of Qt 4's model/view classes + -> Use Strigi for search and analysis (or possibly just Xesam interface?) + -> Use Solid for getting data for removable device list + -> Attractive, original, but not overbearing graphical effects + using Qt 4's new painting and animation features. + + To decide on: + + -> Consult the Kickoff/KDE 3 developers and OpenSuSE users about + any desired changes to the user interface. + -> Whether to use Plasma applets and widgets or Qt's widgets and + QAbstractItemView as the base for the view classes. + -> Provision of Plasma data engines for applets to use to query + applications, recent documents, favorites etc. + -> Should facilities be provided for distributions to replace + Strigi with their choice of search engine? + + Ideas to explore in future: + + -> Use Sonnet for spell-checking the user's search query + -> Use Phonon for previews of audio and video content + in the favorites and recently used sections + -> Light KWin integration for interesting effects for revealing, + hiding or rendering the Kickoff launcher on composited '3D' + desktops. + +Goals 2 and 3 are derived from looking at the KDE 3 implementation +of Kickoff and also the way in which distributions customise KDE. +Consulting distribution representatives is important to clarify +these particular goals. + +2. Make it easy for distributions to modify the menu contents + + -> Different distributions may have different tools for system + configuration ( eg. System Settings , YaST , Mandriva's tools ) + -> The available options on the leave page and the way in which + those tools work varies depending on the distribution + +3. Make it easy for distributions to add their own branding + + -> The launcher menu is a highly visible part of the desktop, + distributions are therefore likely to want to brand it with + their own logos, colors, icons etc. + This does not mean infinite theme-ability, but rather a good + out-of-the-box look which distros can easily tweak so that + it is obvious which distribution is being used from looking + at a screenshot, and also to allow distros to make some + obvious cosmetic changes between versions. + + (See the Ubuntu art specs for example which state that each + new version is supposed to have a visual look which is + distinct from the previous version) diff --git a/applets/kickoff/Messages.sh b/applets/kickoff/Messages.sh new file mode 100644 index 0000000000..42f37cc310 --- /dev/null +++ b/applets/kickoff/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_kickoff.pot +rm -f rc.cpp diff --git a/applets/kickoff/STATUS-TODO b/applets/kickoff/STATUS-TODO new file mode 100644 index 0000000000..f837793908 --- /dev/null +++ b/applets/kickoff/STATUS-TODO @@ -0,0 +1,66 @@ + +Current status of Kickoff/KDE 4: +Bugs and missing features (indicated with a '-') +are listed in priority order for each category. +================================================ + +Favorites View + + Works + - Favorites are not remembered correctly between sessions + when Kickoff is run from a Plasma applet + - Missing drag and drop of items from other views into favorites + - Missing drag and drop re-arranging of items + +Applications View + + Works. + + When KDE 3 and KDE 4 versions of an application are available only + the KDE 4 one is shown. + - Oxygen application category icons are not shown next to categories + +My Computer View + + Works. + + Uses Solid to query devices and respond to addition or removal of + devices + - Folders are currently opened in Konqueror. They should open in + Dolphin + +Recently Used (History?) View + + Works + - Missing a suitable icon for the tab + +Leave View + + Log-off, Shutdown and Restart work + - Sleep, Hibernate do not work + - Log-off, Shutdown and Restart show an unnecessary confirmation + dialog which gives users the Log-off/Shutdown/Restart choice again + - Missing icons for the Sleep, Shutdown, Restart actions + +Search View + + Application search by name, generic name or keywords works + - Strigi search doesn't work due to a Strigi problem which Jos' is + presently fixing + * The other search handlers that query Bookmarks, + Contacts etc. should probably be shared with KRunner. This needs + mailing list discussion. + +Presentation + + When used as a Plasma applet the Kickoff window does not + appear and disappear smoothly. (Works okay when standalone + Kickoff application is run) [Also Performance?] + - Missing the custom QTabBar styling to draw the view names + under their icons and draw a pretty gradient + - Missing the "username on computer" text + - Missing the branding logo + + Experimented with multiple columns in the Favorites/My Computer/Recently Used/Leave + views. + +Performance: + - Scrolling up and down in the application view is not as smooth + as it should be in some categories. Perhaps an issue with icons + from certain sources? + - When opening a previously unopened application category there + may be a slight delay and HDD activity causing the scrolling animation + to have few frames (the animation duration is not affected) + - Currently no delayed initialization is performed. The data required + for all tabs is loaded on startup, except the application view where + only the root branch is loaded initially. diff --git a/applets/kickoff/core/applicationmodel.cpp b/applets/kickoff/core/applicationmodel.cpp new file mode 100644 index 0000000000..f1fd904d83 --- /dev/null +++ b/applets/kickoff/core/applicationmodel.cpp @@ -0,0 +1,696 @@ +/* + Copyright 2007 Pino Toscano + Copyright 2007 Robert Knight + + 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 "applicationmodel.h" + +// Qt +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "kickoffadaptor.h" +// Local +#include "models.h" + +#include + +template <> inline +void KConfigGroup::writeEntry(const char *pKey, + const KGlobalSettings::Completion& aValue, + KConfigBase::WriteConfigFlags flags) +{ + writeEntry(pKey, int(aValue), flags); +} + +namespace Kickoff +{ + +class AppNode +{ +public: + AppNode() + : parent(0), + fetched(false), + isDir(false), + isSeparator(false), + subTitleMandatory(false) + { + } + + ~AppNode() + { + qDeleteAll(children); + } + + QList children; + + QIcon icon; + QString iconName; + QString genericName; + QString appName; + QString relPath; + QString desktopEntry; + + AppNode *parent; + DisplayOrder displayOrder; + bool fetched : 1; + bool isDir : 1; + bool isSeparator : 1; + bool subTitleMandatory : 1; +}; + +class ApplicationModelPrivate +{ +public: + ApplicationModelPrivate(ApplicationModel *qq, bool _allowSeparators) + : q(qq), + root(new AppNode()), + duplicatePolicy(ApplicationModel::ShowDuplicatesPolicy), + systemApplicationPolicy(ApplicationModel::ShowApplicationAndSystemPolicy), +// primaryNamePolicy(ApplicationModel::GenericNamePrimary), + displayOrder(NameAfterDescription), + allowSeparators(_allowSeparators), + showRecentlyInstalled(true) + { + systemApplications = Kickoff::systemApplicationList(); + reloadTimer = new QTimer(qq); + reloadTimer->setSingleShot(true); + QObject::connect(reloadTimer, SIGNAL(timeout()), qq, SLOT(delayedReloadMenu())); + } + + ~ApplicationModelPrivate() + { + delete root; + } + + void fillNode(const QString &relPath, AppNode *node); + static QHash iconNameMap(); + + ApplicationModel *q; + QWeakPointer applet; + AppNode *root; + ApplicationModel::DuplicatePolicy duplicatePolicy; + ApplicationModel::SystemApplicationPolicy systemApplicationPolicy; + QStringList systemApplications; + DisplayOrder displayOrder; + bool allowSeparators; + bool showRecentlyInstalled; + QTimer *reloadTimer; + + QStringList newInstalledPrograms; + QHash seenPrograms; +}; + +void ApplicationModelPrivate::fillNode(const QString &_relPath, AppNode *node) +{ + if (_relPath=="new/") { + Q_FOREACH (const QString &it, newInstalledPrograms) { + KService::Ptr p = KService::serviceByStorageId(it); + + if (p->noDisplay()) { + continue; + } + + AppNode *newnode = new AppNode(); + newnode->icon = KIcon(p->icon()); + newnode->appName = p->name(); + newnode->genericName = p->genericName(); + newnode->desktopEntry = p->entryPath(); + newnode->parent = node; + node->children.append(newnode); + } + return; + } + + KServiceGroup::Ptr root = KServiceGroup::group(_relPath); + + if (!root || !root->isValid()) { + return; + } + + const KServiceGroup::List list = root->entries(true /* sorted */, + true /* exclude no display entries */, + allowSeparators /* allow separators */, + true /* sort by generic name */); + + // application name <-> service map for detecting duplicate entries + QHash existingServices; + + // generic name <-> node mapping to determinate duplicate generic names + QHash > genericNames; + + for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) { + QString icon; + QString appName; + QString genericName; + QString relPath = _relPath; + QString desktopEntry; + bool isDir = false; + bool isSeparator = false; + const KSycocaEntry::Ptr p = (*it); + + if (p->isType(KST_KService)) { + const KService::Ptr service = p; + + if (service->noDisplay()) { + continue; + } + + icon = service->icon(); + appName = service->name(); + genericName = service->genericName(); + desktopEntry = service->entryPath(); + + // check for duplicates (eg. KDE 3 and KDE 4 versions of application + // both present) + if (duplicatePolicy == ApplicationModel::ShowLatestOnlyPolicy && + existingServices.contains(appName)) { + if (Kickoff::isLaterVersion(existingServices[appName], service)) { + continue; + } else { + // find and remove the existing entry with the same name + for (int i = node->children.count() - 1; i >= 0; --i) { + AppNode *app = node->children.at(i); + if (app->appName == appName && + app->genericName == genericName && + app->iconName == icon) { + app = node->children.takeAt(i); + const QString s = app->genericName.toLower(); + if (genericNames.contains(s)) { + QList list = genericNames[s]; + for (int j = list.count() - 1; j >= 0; --j) { + if(list.at(j) == app) { + list.takeAt(j); + } + } + genericNames[s] = list; + } + delete app; + } + } + } + } + + if (systemApplicationPolicy == ApplicationModel::ShowSystemOnlyPolicy && + systemApplications.contains(service->desktopEntryName())) { + // don't duplicate applications that are configured to appear in the System tab + // in the Applications tab + continue; + } + + existingServices[appName] = service; + } else if (p->isType(KST_KServiceGroup)) { + const KServiceGroup::Ptr serviceGroup = p; + + if (serviceGroup->noDisplay() || serviceGroup->childCount() == 0) { + continue; + } + + qDebug() << "Service group" << serviceGroup->entryPath() << serviceGroup->icon() << serviceGroup->relPath() << serviceGroup->directoryEntryPath(); + + icon = serviceGroup->icon(); + if (iconNameMap().contains(icon)) { + icon = iconNameMap().value(icon); + } + + desktopEntry = serviceGroup->entryPath(); + genericName = serviceGroup->caption(); + relPath = serviceGroup->relPath(); + appName = serviceGroup->comment(); + isDir = true; + } else if (p->isType(KST_KServiceSeparator)) { + isSeparator = true; + } else { + qWarning() << "KServiceGroup: Unexpected object in list!"; + continue; + } + + AppNode *newnode = new AppNode(); + newnode->iconName = icon; + newnode->icon = KIcon(icon); + newnode->appName = appName; + newnode->genericName = genericName; + newnode->relPath = relPath; + newnode->desktopEntry = desktopEntry; + newnode->isDir = isDir; + newnode->isSeparator = isSeparator; + newnode->parent = node; + node->children.append(newnode); + + if (p->isType(KST_KService)) { + const QString s = genericName.toLower(); + QList list = genericNames.value(s); + list.append(newnode); + genericNames[s] = list; + } + } + + if (showRecentlyInstalled && _relPath.isEmpty() && !newInstalledPrograms.isEmpty()) { + AppNode *newnode = new AppNode(); + newnode->icon = KIcon("chronometer"); + newnode->appName = i18n("Recently Installed"); + newnode->relPath = "new/"; + newnode->isDir = true; + newnode->parent = node; + node->children.prepend(newnode); + } + + // set the subTitleMandatory field for nodes that do not provide a unique generic + // name what may help us on display to show in such cases also the subtitle to + // provide a hint to the user what the duplicate entries are about. + foreach (const QList &list, genericNames) { + if (list.count() > 1) { + foreach (AppNode* n, list) { + n->subTitleMandatory = true; + } + } + } +} + +ApplicationModel::ApplicationModel(QObject *parent, bool allowSeparators) + : KickoffAbstractModel(parent), + d(new ApplicationModelPrivate(this, allowSeparators)) +{ + QHash roles; + roles[Qt::DisplayRole] = "display"; + roles[Qt::DecorationRole] = "decoration"; + roles[Kickoff::SubTitleRole] = "subtitle"; + roles[Kickoff::UrlRole] = "url"; + roles[Kickoff::GroupNameRole] = "group"; + setRoleNames(roles); + QDBusConnection dbus = QDBusConnection::sessionBus(); + (void)new KickoffAdaptor(this); + QDBusConnection::sessionBus().registerObject("/kickoff", this); + dbus.connect(QString(), "/kickoff", "org.kde.plasma", "reloadMenu", this, SLOT(reloadMenu())); + connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), this, SLOT(checkSycocaChange(QStringList))); + + // TODO: remove me again + reloadMenu(); +} + +ApplicationModel::~ApplicationModel() +{ + delete d; +} + +bool ApplicationModel::canFetchMore(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return false; + + AppNode *node = static_cast(parent.internalPointer()); + return node->isDir && !node->fetched; +} + +// void ApplicationModel::setNameDisplayOrder(DisplayOrder displayOrder) +// { +// d->displayOrder = displayOrder; +// } +// +// DisplayOrder ApplicationModel::nameDisplayOrder() const +// { +// return d->displayOrder; +// } + +void ApplicationModel::setShowRecentlyInstalled(bool showRecentlyInstalled) +{ + if (d->showRecentlyInstalled != showRecentlyInstalled) { + d->showRecentlyInstalled = showRecentlyInstalled; + reloadMenu(); + } +} + +bool ApplicationModel::showRecentlyInstalled() const +{ + return d->showRecentlyInstalled; +} + +int ApplicationModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return 1; +} + +QVariant ApplicationModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + AppNode *node = static_cast(index.internalPointer()); + + switch (role) { + case Qt::DisplayRole: + if (node->genericName.isEmpty()) { + return node->appName; + } else { + return node->genericName; + } + case Kickoff::SubTitleRole: + if (node->appName.isEmpty() || node->appName == node->genericName) { + return QString(); //return empty string to avoid errors in QML assigning null to Text + } else { + return node->appName; + } + case Kickoff::UrlRole: + if (node->isDir) { + return QString::fromLatin1("applications://%1").arg(node->desktopEntry); + } else { + return node->desktopEntry; + } + break; + case Kickoff::SubTitleMandatoryRole: + return node->subTitleMandatory; + break; + case Kickoff::SeparatorRole: + return node->isSeparator; + break; + case Qt::DecorationRole: + return node->icon; + break; + case Kickoff::RelPathRole: + return node->relPath; + break; + case Kickoff::IconNameRole: + return node->iconName; + break; + default: + ; + } + return QVariant(); +} + +void ApplicationModel::fetchMore(const QModelIndex &parent) +{ + if (!parent.isValid()) { + return; + } + + AppNode *node = static_cast(parent.internalPointer()); + if (!node->isDir) { + return; + } + + // FIXME? QML's QQmlAdaptorModel (the "backend" used for VisualDataModel) always hard-resets + // the model when the source model (this one) changes layout, which breaks kickoff's + // navigation as opening a category for the first time calls this and then calls + // layoutChanged() --> QML's VisualDataModel is reset, that in turn invalidates + // VDM's rootIndex and when that happens, Kickoff is switched to the root level. + // Disabling the layout signals makes Kickoff's navigation work properly. + +// emit layoutAboutToBeChanged(QList() << parent); + d->fillNode(node->relPath, node); + node->fetched = true; +// changePersistentIndex(parent, parent); +// emit layoutChanged(QList() << parent); +} + +bool ApplicationModel::hasChildren(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return true; + } + + AppNode *node = static_cast(parent.internalPointer()); + return node->isDir; +} + +QVariant ApplicationModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || section != 0) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + return i18n("All Applications"); + break; + default: + return QVariant(); + } +} + +QModelIndex ApplicationModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || column != 0) + return QModelIndex(); + + AppNode *node = d->root; + if (parent.isValid()) + node = static_cast(parent.internalPointer()); + + if (row >= node->children.count()) + return QModelIndex(); + else + return createIndex(row, 0, node->children.at(row)); +} + +QModelIndex ApplicationModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) { + return QModelIndex(); + } + + AppNode *node = static_cast(index.internalPointer()); + if (node->parent->parent) { + int id = node->parent->parent->children.indexOf(node->parent); + + if (id >= 0 && id < node->parent->parent->children.count()) { + return createIndex(id, 0, node->parent); + } + } + + return QModelIndex(); +} + +int ApplicationModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return d->root->children.count(); + } + + AppNode *node = static_cast(parent.internalPointer()); + return node->children.count(); +} + +void ApplicationModel::setDuplicatePolicy(DuplicatePolicy policy) +{ + if (d->duplicatePolicy != policy) { + d->duplicatePolicy = policy; + reloadMenu(); + } +} + +void ApplicationModel::setSystemApplicationPolicy(SystemApplicationPolicy policy) +{ + if (d->systemApplicationPolicy != policy) { + d->systemApplicationPolicy = policy; + reloadMenu(); + } +} + +void ApplicationModel::delayedReloadMenu() +{ + if (!d->reloadTimer->isActive()) { + d->reloadTimer->start(200); + } +} + +void ApplicationModel::reloadMenu() +{ + beginResetModel(); + delete d->root; + d->root = new AppNode(); + createNewProgramList(); + d->fillNode(QString(), d->root); + endResetModel(); +} + +void ApplicationModel::checkSycocaChange(const QStringList &changes) +{ + if (changes.contains("services") || changes.contains("apps")) { + reloadMenu(); + } +} + +ApplicationModel::DuplicatePolicy ApplicationModel::duplicatePolicy() const +{ + return d->duplicatePolicy; +} + +ApplicationModel::SystemApplicationPolicy ApplicationModel::systemApplicationPolicy() const +{ + return d->systemApplicationPolicy; +} + +void ApplicationModel::setApplet(Plasma::Applet *applet) +{ + if (d->applet.data() != applet) { + d->applet = applet; + createNewProgramList(); + } +} + +void ApplicationModel::createNewProgramList() +{ + if (!d->applet) { + return; + } + + d->newInstalledPrograms.clear(); + if (!d->showRecentlyInstalled) { + return; + } + + //FIXME + KConfigGroup kickoffrc = d->applet.data()->config(); + foreach (const QString &it, kickoffrc.keyList()) { + d->seenPrograms.insert(it, QDate::fromString(kickoffrc.readEntry(it), Qt::ISODate)); + } + + bool initialize = (d->seenPrograms.isEmpty()); + + bool seenProgramsChanged = createNewProgramListForPath(QString()); + + if (initialize) { + // on first start, set all entries' dates to empty (means: they are not new) + for (QHash::Iterator it = d->seenPrograms.begin(); it != d->seenPrograms.end(); ++it) + *it = QDate(); + + d->newInstalledPrograms.clear(); + } + + if (seenProgramsChanged) { + for (QHash::Iterator it = d->seenPrograms.begin(); it != d->seenPrograms.end(); ++it) { + kickoffrc.writeEntry(it.key(), it.value().toString(Qt::ISODate)); + } + kickoffrc.sync(); + } +} + +bool ApplicationModel::createNewProgramListForPath(const QString &relPath) +{ + bool seenProgramsChanged = false; + + KServiceGroup::Ptr group = KServiceGroup::group(relPath); + if (!group || !group->isValid()) { + return false; + } + + const KServiceGroup::List list = group->entries(); + + KServiceGroup::List::ConstIterator it = list.begin(); + for (; it != list.end(); ++it) { + KSycocaEntry::Ptr e = (*it); + + if (e->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr g(e); + if (!g->noDisplay()) { + if (createNewProgramListForPath(g->relPath())) + seenProgramsChanged = true; + } + } else if (e->isType(KST_KService)) { + KService::Ptr s(e); + if (s->isApplication() && !s->noDisplay()) { + QString shortStorageId = s->storageId().remove(".desktop"); + QHash::Iterator it_find = d->seenPrograms.find(shortStorageId); + if (it_find == d->seenPrograms.end()) { + seenProgramsChanged = true; + d->seenPrograms.insert(shortStorageId, QDate::currentDate()); + if (!d->newInstalledPrograms.contains(s->storageId())) { + d->newInstalledPrograms += s->storageId(); + } + } + else { + QDate date = it_find.value(); + if (date.isValid()) { + if (date.daysTo(QDate::currentDate()) < 3) { + if (!d->newInstalledPrograms.contains(s->storageId())) { + d->newInstalledPrograms += s->storageId(); + } + } + else { + seenProgramsChanged = true; + (*it_find) = QDate(); // this entry is not new anymore + } + } + } + } + } + } + return seenProgramsChanged; +} + +/** + * FIXME This is a temporary workaround to map the icon names found + * in the desktop directory files (from /usr/share/desktop-directories) + * into the Oxygen icon names. (Only applies if the Gnome menu files + * are also installed) + * + * This list was compiled from Kubuntu 7.04 with the gnome-menus + * package present. + * + * This needs to be discussed on kde-core-devel and fixed + */ +QHash ApplicationModelPrivate::iconNameMap() +{ + static QHash map; + if (map.isEmpty()) { + map.insert("gnome-util", "applications-accessories"); + // accessibility Oxygen icon was missing when this list was compiled + map.insert("accessibility-directory", "applications-other"); + map.insert("gnome-devel", "applications-development"); + map.insert("package_edutainment", "applications-education"); + map.insert("gnome-joystick", "applications-games"); + map.insert("gnome-graphics", "applications-graphics"); + map.insert("gnome-globe", "applications-internet"); + map.insert("gnome-multimedia", "applications-multimedia"); + map.insert("gnome-applications", "applications-office"); + map.insert("gnome-system", "applications-system"); + } + return map; +} + +} // namespace Kickoff + + +#include "applicationmodel.moc" diff --git a/applets/kickoff/core/applicationmodel.h b/applets/kickoff/core/applicationmodel.h new file mode 100644 index 0000000000..ad5b4cb034 --- /dev/null +++ b/applets/kickoff/core/applicationmodel.h @@ -0,0 +1,131 @@ +/* + Copyright 2007 Pino Toscano + Copyright 2007 Robert Knight + + 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 APPLICATIONMODEL_H +#define APPLICATIONMODEL_H + +#include "kickoffabstractmodel.h" +#include "models.h" + +namespace Plasma +{ + class Applet; +} // namespace Plasma + +namespace Kickoff +{ + +class ApplicationModelPrivate; + +/** + * ApplicationModel provides a tree model containing all of the user's installed graphical programs. + * The applications are arranged into categories, based on the information in their .desktop files. + */ +class ApplicationModel : public KickoffAbstractModel +{ + Q_OBJECT + +public: + ApplicationModel(QObject *parent = 0, bool allowSeparators = false); + virtual ~ApplicationModel(); + + /** + * This enum describes the policy for + * handling duplicate applications (that is, + * two applications with the same name in the same group) + */ + enum DuplicatePolicy { + /** Display duplicate entries. */ + ShowDuplicatesPolicy, + /** + * Show only the entry for the most recent + * version of the application. + * + * Currently only a crude heuristic to determine whether the + * application is from KDE 3 or KDE 4 is used to determine + * recent-ness. + * + * eg. If MyGame/KDE 3 and MyGame/KDE 4 are found + * show only MyGame/KDE 4 + */ + ShowLatestOnlyPolicy + }; + + /** + * This enum describes the policy for + * handling applications that are configured to appear + * in the System tab. + */ + enum SystemApplicationPolicy { + /** Display entries in Applications tab and System tab. */ + ShowApplicationAndSystemPolicy, + /** Display entry only in System tab. */ + ShowSystemOnlyPolicy + }; + + /** + * Sets the policy for handling duplicate applications. + * See DuplicatePolicy + */ + void setDuplicatePolicy(DuplicatePolicy policy); + /** See setDuplicatePolicy() */ + DuplicatePolicy duplicatePolicy() const; + + /** + * Sets the policy for handling System applications. + * See SystemApplicationPolicy + */ + void setSystemApplicationPolicy(SystemApplicationPolicy policy); + /** See setSystemApplicationPolicy() */ + SystemApplicationPolicy systemApplicationPolicy() const; + + // reimplemented from QAbstractItemModel + virtual bool canFetchMore(const QModelIndex &parent) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual void fetchMore(const QModelIndex &parent); + virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex &index) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + + void setApplet(Plasma::Applet *applet); + void setShowRecentlyInstalled(bool showRecentlyInstalled); + bool showRecentlyInstalled() const; + +public Q_SLOTS: + void reloadMenu(); + void delayedReloadMenu(); + void checkSycocaChange(const QStringList &changes); + +private: + friend class ApplicationModelPrivate; + ApplicationModelPrivate *const d; + + void createNewProgramList(); + bool createNewProgramListForPath(const QString &relPath); + + Q_DISABLE_COPY(ApplicationModel) +}; + +} + +#endif diff --git a/applets/kickoff/core/favoritesmodel.cpp b/applets/kickoff/core/favoritesmodel.cpp new file mode 100644 index 0000000000..5f5e98adec --- /dev/null +++ b/applets/kickoff/core/favoritesmodel.cpp @@ -0,0 +1,376 @@ +/* + Copyright 2007 Robert Knight + + 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 "favoritesmodel.h" +#include "krunnermodel.h" + +// Qt +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include + + + +using namespace Kickoff; + +class FavoritesModel::Private +{ +public: + Private(FavoritesModel *parent) + : q(parent), + displayOrder(NameAfterDescription) + { + init(); + } + + void init() + { + } + + void addFavoriteItem(const QString& url) + { + QStandardItem *item = StandardItemFactory::createItemForUrl(url, displayOrder); + item->setData(i18n("Favorites"), Kickoff::GroupNameRole); + q->appendRow(item); + } + + void moveFavoriteItem(int startRow, int destRow) + { + if (destRow == startRow) { + return; + } + + QStandardItem *item = q->takeItem(startRow); + q->removeRow(startRow); + q->insertRow(destRow, item); + } + + void removeFavoriteItem(const QString& url) + { + Q_UNUSED(url) + QModelIndexList matches = q->match(q->index(0, 0), UrlRole, + url, -1, + Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap | Qt::MatchRecursive)); + + qDebug() << "Removing item matches" << matches; + + foreach (const QModelIndex& index, matches) { + QStandardItem *item = q->itemFromIndex(index); + if (item->parent()) { + item->parent()->removeRow(item->row()); + } else { + qDeleteAll(q->takeRow(item->row())); + } + } + } + + static void loadFavorites() + { + globalFavoriteList.clear(); + globalFavoriteSet.clear(); + + KConfigGroup favoritesGroup = componentData().config()->group("Favorites"); + QList favoriteList = favoritesGroup.readEntry("FavoriteURLs", QList()); + if (favoriteList.isEmpty()) { + favoriteList = defaultFavorites(); + } + + foreach (const QString &favorite, favoriteList) { + FavoritesModel::add(favorite); + } + } + + static QList defaultFavorites() + { + QList applications; + applications << "konqbrowser" << "KMail2" << "kdesystemsettings" << "dolphin" << "konsole" << "kate" << "kwrite" << "kinfocenter"; + + QList desktopFiles; + + foreach (const QString& application, applications) { + KService::Ptr service = KService::serviceByStorageId(application + ".desktop"); + if (service) { + desktopFiles << service->entryPath(); + } + } + + return desktopFiles; + } + + static void saveFavorites() + { + KConfigGroup favoritesGroup = componentData().config()->group("Favorites"); + favoritesGroup.writeEntry("FavoriteURLs", globalFavoriteList); + favoritesGroup.config()->sync(); + } + + static QList globalFavoriteList; + static QSet globalFavoriteSet; + static QSet models; + + FavoritesModel * const q; + DisplayOrder displayOrder; +}; + +QList FavoritesModel::Private::globalFavoriteList; +QSet FavoritesModel::Private::globalFavoriteSet; +QSet FavoritesModel::Private::models; + +FavoritesModel::FavoritesModel(QObject *parent) + : KickoffModel(parent) + , d(new Private(this)) +{ + Private::models << this; + if (Private::models.count() == 1 && Private::globalFavoriteList.isEmpty()) { + Private::loadFavorites(); + } else { + foreach (const QString &url, Private::globalFavoriteList) { + d->addFavoriteItem(url); + } + } + +} + +FavoritesModel::~FavoritesModel() +{ + Private::models.remove(this); + + if (Private::models.isEmpty()) { + Private::saveFavorites(); + } + + delete d; +} + +void FavoritesModel::add(const QString& url) +{ + QString handledUrl; + KService::Ptr service = Kickoff::serviceForUrl(url); + if (service) { + handledUrl = service->entryPath(); + } else { + handledUrl = url; + } + + Private::globalFavoriteList << handledUrl; + Private::globalFavoriteSet << handledUrl; + + foreach (FavoritesModel* model, Private::models) { + model->d->addFavoriteItem(handledUrl); + } + + // save after each add in case we crash + Private::saveFavorites(); +} + +void FavoritesModel::move(int startRow, int destRow) +{ + // just move the item +// Private::globalFavoriteList.move(startRow, destRow); + + foreach (FavoritesModel* model, Private::models) { + qDebug() << "Move : " << startRow << destRow << model->rowCount(); + if (destRow >= model->rowCount()) { + destRow = model->rowCount() - 1; + } + if (startRow >= model->rowCount()) { + startRow = model->rowCount() - 1; + } + qDebug() << "Move : " << startRow << destRow << model->rowCount(); + Private::globalFavoriteList.move(startRow, destRow); + model->d->moveFavoriteItem(startRow, destRow); + } + + // save after each add in case we crash + Private::saveFavorites(); +} + +void FavoritesModel::remove(const QString& url) +{ + Private::globalFavoriteList.removeAll(url); + Private::globalFavoriteSet.remove(url); + + foreach (FavoritesModel* model, Private::models) { + model->d->removeFavoriteItem(url); + } + + // save after each remove in case of crash or other mishaps + Private::saveFavorites(); +} + +bool FavoritesModel::isFavorite(const QString& url) +{ + QString handledUrl; + KService::Ptr service = Kickoff::serviceForUrl(url); + if (service) { + handledUrl = service->entryPath(); + } else { + handledUrl = url; + } + + return Private::globalFavoriteSet.contains(handledUrl); +} + +int FavoritesModel::numberOfFavorites() +{ + foreach (FavoritesModel* model, Private::models) { + return model->d->q->rowCount() - 1; + } + + return 0; +} + +void FavoritesModel::sortFavorites(Qt::SortOrder order) +{ + if(Private::models.isEmpty()) { + return; + } + + foreach (FavoritesModel *model, Private::models) { + model->d->q->sort(0, order); + } + + Private::globalFavoriteList.clear(); + + FavoritesModel *model = *Private::models.begin(); + QStandardItem *childData; + for (int i = 0; i <= numberOfFavorites(); i++) { + childData = model->d->q->item(i, 0); + Private::globalFavoriteList.append(childData->data(Kickoff::UrlRole).toString()); + } + Private::saveFavorites(); +} + +void FavoritesModel::sortFavoritesAscending() +{ + sortFavorites(Qt::AscendingOrder); +} + +void FavoritesModel::sortFavoritesDescending() +{ + sortFavorites(Qt::DescendingOrder); +} + +bool FavoritesModel::dropMimeData(const QString& text, const QVariantList& urls, + int row, int column) +{ + qDebug() << "Dropping into row: " << row << urls; + // FIXME: pass DropAction by qml + Qt::DropAction action = Qt::MoveAction; + if (action == Qt::IgnoreAction) { + return true; + } + + if (column > 0 || row > numberOfFavorites()) { + qDebug() << "Exit " << numberOfFavorites(); + return false; + } + + if (action == Qt::MoveAction) { + QModelIndex modelIndex; + QStandardItem *startItem; + int startRow = -1; + int destRow = row; + qDebug() << "Moving ..." << startRow << destRow; + + // look for the favorite that was dragged + bool conv = false; + startRow = text.toInt(&conv, 10); + + if (!conv) { + bool dropped = false; + foreach (const QVariant &varUrl, urls) { + if (!varUrl.value().isValid()) { + continue; + } + const QString path = varUrl.value().toLocalFile(); + if (!KDesktopFile::isDesktopFile(path)) { + continue; + } + KDesktopFile dFile(path); + if (dFile.hasApplicationType() && !dFile.noDisplay()) { + FavoritesModel::add(path); + dropped = true; + } + } + qDebug() << " now move the item to it's new location " << startRow << destRow; + return dropped; + } + + if (destRow < 0) { + qDebug() << "Returning here" << startRow << destRow; + return false; + } + + // now move the item to it's new location + FavoritesModel::move(startRow, destRow); + + return true; + } + + return true; +} + +QVariant FavoritesModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || section != 0) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + return i18nc("@title:column", "Favorites"); + break; + default: + return QVariant(); + } +} + +void FavoritesModel::setNameDisplayOrder(DisplayOrder displayOrder) +{ + if (d->displayOrder == displayOrder) { + return; + } + + d->displayOrder = displayOrder; + + foreach (FavoritesModel* model, Private::models) { + model->clear(); + model->d->init(); + } + + Private::loadFavorites(); +} + +DisplayOrder FavoritesModel::nameDisplayOrder() const +{ + return d->displayOrder; +} + +#include "favoritesmodel.moc" diff --git a/applets/kickoff/core/favoritesmodel.h b/applets/kickoff/core/favoritesmodel.h new file mode 100644 index 0000000000..27a0626524 --- /dev/null +++ b/applets/kickoff/core/favoritesmodel.h @@ -0,0 +1,72 @@ +/* + Copyright 2007 Robert Knight + + 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 FAVORITESMODEL_H +#define FAVORITESMODEL_H + +#include "kickoffmodel.h" +#include "models.h" + +namespace Kickoff +{ + +/** + * A model which provides an ordered list of 'favorite' items chosen by the user. + * The items may represent documents, folders, applications, devices or anything else + * identified by a URL. + * + * The information persists between sessions. + */ +class FavoritesModel : public KickoffModel +{ + Q_OBJECT + +public: + FavoritesModel(QObject *parent = NULL); + virtual ~FavoritesModel(); + + /** Add a new item for @p url to the user's favorites list. */ + Q_INVOKABLE static void add(const QString& url); + /** Remove the item associated with @p url from the user's favorites list. */ + Q_INVOKABLE static void remove(const QString& url); + /** Returns true if @p url is in the list of the user's favorite URLs. */ + Q_INVOKABLE static void move(int startRow, int destRow); + static int numberOfFavorites(); + static void sortFavorites(Qt::SortOrder order); + Q_INVOKABLE static bool isFavorite(const QString& url); + + using QAbstractItemModel::dropMimeData; + Q_INVOKABLE virtual bool dropMimeData(const QString& text, const QVariantList& urls, + int row, int column); + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + void setNameDisplayOrder(DisplayOrder displayOrder); + DisplayOrder nameDisplayOrder() const; + +public Q_SLOTS: + void sortFavoritesAscending(); + void sortFavoritesDescending(); + +private: + class Private; + Private * const d; +}; + +} + +#endif // FAVORITESMODEL_H diff --git a/applets/kickoff/core/itemhandlers.cpp b/applets/kickoff/core/itemhandlers.cpp new file mode 100644 index 0000000000..b461e1cabb --- /dev/null +++ b/applets/kickoff/core/itemhandlers.cpp @@ -0,0 +1,191 @@ +/* + Copyright 2007 Robert Knight + + 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 "itemhandlers.h" + +// Qt +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include + +// KDE Base +#include + +// Local +#include "recentapplications.h" + +// DBus +#include "krunner_interface.h" +#include "screensaver_interface.h" +#include "ksmserver_interface.h" +#include +#include + +using namespace Kickoff; + +bool ServiceItemHandler::openUrl(const KUrl& url) +{ + int result = KToolInvocation::startServiceByDesktopPath(url.pathOrUrl(), QStringList(), 0, 0, 0, "", true); + + if (result == 0) { + KService::Ptr service = KService::serviceByDesktopPath(url.pathOrUrl()); + + if (service) { + RecentApplications::self()->add(service); + } else { + qWarning() << "Failed to find service for" << url; + return false; + } + } + + return result == 0; +} +LeaveItemHandler::LeaveItemHandler(QObject *parent) + : QObject (parent) +{ +} + +bool LeaveItemHandler::openUrl(const KUrl& url) +{ + m_logoutAction = url.path().remove('/'); + + if (m_logoutAction == "sleep") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(suspendRAM())); + return true; + } else if (m_logoutAction == "hibernate") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(suspendDisk())); + return true; + } else if (m_logoutAction == "lock") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(lock())); + return true; + } else if (m_logoutAction == "switch") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(switchUser())); + return true; + } else if (m_logoutAction == "logout" || m_logoutAction == "logoutonly" || + m_logoutAction == "restart" || m_logoutAction == "shutdown") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(logout())); + return true; + } else if (m_logoutAction == "savesession") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(saveSession())); + return true; + } else if (m_logoutAction == "standby") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(standby())); + return true; + } else if (m_logoutAction == "suspendram") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(suspendRAM())); + return true; + } else if (m_logoutAction == "suspenddisk") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(suspendDisk())); + return true; + } else if (m_logoutAction == "run") { + // decouple dbus call, otherwise we'll run into a dead-lock + QTimer::singleShot(0, this, SLOT(runCommand())); + return true; + } + + return false; +} + +void LeaveItemHandler::runCommand() +{ + if (KAuthorized::authorize("run_command")) { + QString interface("org.kde.krunner"); + org::kde::krunner::App krunner(interface, "/App", QDBusConnection::sessionBus()); + krunner.display(); + } +} + +void LeaveItemHandler::logout() +{ + KWorkSpace::ShutdownConfirm confirm = KWorkSpace::ShutdownConfirmDefault; + KWorkSpace::ShutdownType type = KWorkSpace::ShutdownTypeNone; + + if (m_logoutAction == "logout" || m_logoutAction == "logoutonly") { + type = KWorkSpace::ShutdownTypeNone; + } else if (m_logoutAction == "lock") { + qDebug() << "Locking screen"; + } else if (m_logoutAction == "switch") { + qDebug() << "Switching user"; + } else if (m_logoutAction == "restart") { + type = KWorkSpace::ShutdownTypeReboot; + } else if (m_logoutAction == "shutdown") { + type = KWorkSpace::ShutdownTypeHalt; + } + + KWorkSpace::requestShutDown(confirm, type); +} + +void LeaveItemHandler::lock() +{ + QString interface("org.freedesktop.ScreenSaver"); + org::freedesktop::ScreenSaver screensaver(interface, "/ScreenSaver", QDBusConnection::sessionBus()); + screensaver.Lock(); +} + +void LeaveItemHandler::switchUser() +{ + QString interface("org.kde.krunner"); + org::kde::krunner::App krunner(interface, "/App", QDBusConnection::sessionBus()); + krunner.switchUser(); +} + +void LeaveItemHandler::saveSession() +{ + QString interface("org.kde.ksmserver"); + + org::kde::KSMServerInterface ksmserver(interface, "/KSMServer", QDBusConnection::sessionBus()); + if (ksmserver.isValid()) { + ksmserver.saveCurrentSession(); + } +} + +void LeaveItemHandler::standby() +{ + // FIXME: Use standby from KDE Power Management System's interface + suspendRAM(); +} + +void LeaveItemHandler::suspendRAM() +{ + Solid::PowerManagement::requestSleep(Solid::PowerManagement::SuspendState, 0, 0); +} + +void LeaveItemHandler::suspendDisk() +{ + Solid::PowerManagement::requestSleep(Solid::PowerManagement::HibernateState, 0, 0); +} + +#include "itemhandlers.moc" diff --git a/applets/kickoff/core/itemhandlers.h b/applets/kickoff/core/itemhandlers.h new file mode 100644 index 0000000000..8f054901d8 --- /dev/null +++ b/applets/kickoff/core/itemhandlers.h @@ -0,0 +1,59 @@ +/* + Copyright 2007 Robert Knight + + 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 ITEMHANDLERS_H +#define ITEMHANDLERS_H + +#include + +#include "urlitemlauncher.h" + +namespace Kickoff +{ + +class ServiceItemHandler : public UrlItemHandler +{ +public: + virtual bool openUrl(const KUrl& url); +}; +class LeaveItemHandler : public QObject, public UrlItemHandler +{ + Q_OBJECT +public: + explicit LeaveItemHandler(QObject *parent = 0); + virtual bool openUrl(const KUrl& url); + +private Q_SLOTS: + void runCommand(); + void logout(); + void lock(); + void switchUser(); + void saveSession(); + void standby(); + void suspendRAM(); + void suspendDisk(); + +private: + QString m_logoutAction; +}; + +} + +#endif // ITEMHANDLERS_H + diff --git a/applets/kickoff/core/kickoffabstractmodel.cpp b/applets/kickoff/core/kickoffabstractmodel.cpp new file mode 100644 index 0000000000..7c51b0f58b --- /dev/null +++ b/applets/kickoff/core/kickoffabstractmodel.cpp @@ -0,0 +1,92 @@ +/* + Copyright 2008 Marco Martin + + 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 "kickoffabstractmodel.h" + +// Qt +#include + +// KDE +#include +#include + +// Local +#include "models.h" + +using namespace Kickoff; + +KickoffAbstractModel::KickoffAbstractModel(QObject *parent) + : QAbstractItemModel(parent) +{} + +KickoffAbstractModel::~KickoffAbstractModel() +{} + +Qt::ItemFlags KickoffAbstractModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); + + if (index.isValid()) { + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + } else { + return 0; + } +} + +QMimeData *KickoffAbstractModel::mimeData(const QModelIndexList &indexes) const +{ + KUrl::List urls; + QByteArray itemData; + + foreach(const QModelIndex &index, indexes) { + KUrl itemUrl = KUrl(data(index, UrlRole).toString()); + if (itemUrl.isValid()) { + urls << itemUrl; + } + } + + QMimeData *mimeData = new QMimeData(); + + if (!urls.isEmpty()) { + urls.populateMimeData(mimeData); + } + + return mimeData; +} + +QStringList KickoffAbstractModel::mimeTypes() const +{ + QStringList types; + types << QLatin1String("text/uri-list"); + return types; +} + +Qt::DropActions KickoffAbstractModel::supportedDropActions() const +{ + return 0; +} + +Qt::DropActions KickoffAbstractModel::supportedDragActions() const +{ + return Qt::CopyAction; +} + +#include "kickoffabstractmodel.moc" + diff --git a/applets/kickoff/core/kickoffabstractmodel.h b/applets/kickoff/core/kickoffabstractmodel.h new file mode 100644 index 0000000000..be5ce219a6 --- /dev/null +++ b/applets/kickoff/core/kickoffabstractmodel.h @@ -0,0 +1,53 @@ +/* + Copyright 2008 Marco Martin + + 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 KICKOFFABSTRACTMODEL_H +#define KICKOFFABSTRACTMODEL_H + +// Qt +#include + +// KDE + +namespace Kickoff +{ + +/** + * Base model for Kickoff models based on QAbstractItemModel, enables drag and drop support + */ +class KickoffAbstractModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + /** Construct a new KickoffModel with the specified parent. */ + KickoffAbstractModel(QObject *parent = 0); + virtual ~KickoffAbstractModel(); + + //Reimplementations + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QMimeData *mimeData(const QModelIndexList &indexes) const; + virtual QStringList mimeTypes() const; + virtual Qt::DropActions supportedDropActions() const; + virtual Qt::DropActions supportedDragActions() const; +}; + +} + +#endif // KICKOFFABSTRACTMODEL_H diff --git a/applets/kickoff/core/kickoffmodel.cpp b/applets/kickoff/core/kickoffmodel.cpp new file mode 100644 index 0000000000..86a9b4db52 --- /dev/null +++ b/applets/kickoff/core/kickoffmodel.cpp @@ -0,0 +1,99 @@ +/* + Copyright 2008 Marco Martin + + 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 "kickoffmodel.h" + +// Qt +#include + +// KDE +#include +#include + +// Local +#include "models.h" + +using namespace Kickoff; + +KickoffModel::KickoffModel(QObject *parent) + : QStandardItemModel(parent) +{ + QHash roles; + roles[Qt::DisplayRole] = "display"; + roles[Qt::DecorationRole] = "decoration"; + roles[Kickoff::SubTitleRole] = "subtitle"; + roles[Kickoff::UrlRole] = "url"; + roles[GroupNameRole] = "group"; + setRoleNames(roles); +} + +KickoffModel::~KickoffModel() +{} + +Qt::ItemFlags KickoffModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index); + + if (index.isValid()) { + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + } else { + return 0; + } +} + +QMimeData *KickoffModel::mimeData(const QModelIndexList &indexes) const +{ + KUrl::List urls; + + foreach (const QModelIndex &index, indexes) { + KUrl itemUrl = KUrl(data(index, UrlRole).toString()); + if (itemUrl.isValid()) { + urls << itemUrl; + } + } + + QMimeData *mimeData = new QMimeData(); + + if (!urls.isEmpty()) { + urls.populateMimeData(mimeData); + } + + return mimeData; +} + +QStringList KickoffModel::mimeTypes() const +{ + QStringList types; + types << QLatin1String("text/uri-list"); + return types; +} + +Qt::DropActions KickoffModel::supportedDropActions() const +{ + return Qt::MoveAction; +} + +Qt::DropActions KickoffModel::supportedDragActions() const +{ + return Qt::CopyAction; +} + +#include "kickoffmodel.moc" + diff --git a/applets/kickoff/core/kickoffmodel.h b/applets/kickoff/core/kickoffmodel.h new file mode 100644 index 0000000000..dd91f9be6d --- /dev/null +++ b/applets/kickoff/core/kickoffmodel.h @@ -0,0 +1,55 @@ +/* + Copyright 2008 Marco Martin + + 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 KICKOFFMODEL_H +#define KICKOFFMODEL_H + +// Qt +#include + +// KDE + +namespace Kickoff +{ + +/** + * Base model for Kickoff models based on QStandardItemModel, enables drag and drop support + */ +class KickoffModel : public QStandardItemModel +{ + Q_OBJECT + +public: + /** Construct a new KickoffModel with the specified parent. */ + KickoffModel(QObject *parent = 0); + virtual ~KickoffModel(); + + //Reimplementations + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QMimeData *mimeData(const QModelIndexList &indexes) const; + virtual QStringList mimeTypes() const; + virtual Qt::DropActions supportedDropActions() const; + virtual Qt::DropActions supportedDragActions() const; + +private: +}; + +} + +#endif // KICKOFFMODEL_H diff --git a/applets/kickoff/core/kickoffplugin.cpp b/applets/kickoff/core/kickoffplugin.cpp new file mode 100644 index 0000000000..69945e994e --- /dev/null +++ b/applets/kickoff/core/kickoffplugin.cpp @@ -0,0 +1,45 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 "kickoffplugin.h" +#include "applicationmodel.h" +#include "favoritesmodel.h" +#include "krunnermodel.h" +#include "leavemodel.h" +#include "recentlyusedmodel.h" +#include "systemmodel.h" +#include "kuserproxy.h" +#include "urlitemlauncher.h" + +#include + +void KickoffPlugin::registerTypes (const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.kickoff")); + qmlRegisterType(uri, 0, 1, "ApplicationModel"); + qmlRegisterType(uri, 0, 1, "FavoritesModel"); + qmlRegisterType(uri, 0, 1, "KRunnerModel"); + qmlRegisterType(uri, 0, 1, "LeaveModel"); + qmlRegisterType(uri, 0, 1, "RecentlyUsedModel"); + qmlRegisterType(uri, 0, 1, "SystemModel"); + qmlRegisterType(uri, 0, 1, "Launcher"); + qmlRegisterType(uri, 0, 1, "KUser"); +} + +#include "kickoffplugin.moc" diff --git a/applets/kickoff/core/kickoffplugin.h b/applets/kickoff/core/kickoffplugin.h new file mode 100644 index 0000000000..de839b3931 --- /dev/null +++ b/applets/kickoff/core/kickoffplugin.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 KICKOFFPLUGIN_H +#define KICKOFFPLUGIN_H + +#include +#include + + +class KickoffPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") +public: + virtual void registerTypes(const char *uri); +}; + +#endif // KICKOFFPLUGIN_H diff --git a/applets/kickoff/core/kickoffproxymodel.cpp b/applets/kickoff/core/kickoffproxymodel.cpp new file mode 100644 index 0000000000..4976bda9a8 --- /dev/null +++ b/applets/kickoff/core/kickoffproxymodel.cpp @@ -0,0 +1,92 @@ +/* + Copyright 2008 Marco Martin + + 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 "kickoffproxymodel.h" + +// Qt +#include + +// KDE +#include +#include + +// Local +#include "models.h" + +using namespace Kickoff; + +KickoffProxyModel::KickoffProxyModel(QObject *parent) + : QAbstractProxyModel(parent) +{} + +KickoffProxyModel::~KickoffProxyModel() +{} + +Qt::ItemFlags KickoffProxyModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QAbstractProxyModel::flags(index); + + if (index.isValid()) { + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; + } else { + return 0; + } +} + +QMimeData *KickoffProxyModel::mimeData(const QModelIndexList &indexes) const +{ + KUrl::List urls; + QByteArray itemData; + + foreach(const QModelIndex &index, indexes) { + KUrl itemUrl = KUrl(data(index, UrlRole).toString()); + if (itemUrl.isValid()) { + urls << itemUrl; + } + } + + QMimeData *mimeData = new QMimeData(); + + if (!urls.isEmpty()) { + urls.populateMimeData(mimeData); + } + + return mimeData; +} + +QStringList KickoffProxyModel::mimeTypes() const +{ + QStringList types; + types << QLatin1String("text/uri-list"); + return types; +} + +Qt::DropActions KickoffProxyModel::supportedDropActions() const +{ + return 0; +} + +Qt::DropActions KickoffProxyModel::supportedDragActions() const +{ + return Qt::CopyAction; +} + +#include "kickoffproxymodel.moc" + diff --git a/applets/kickoff/core/kickoffproxymodel.h b/applets/kickoff/core/kickoffproxymodel.h new file mode 100644 index 0000000000..f1af64041e --- /dev/null +++ b/applets/kickoff/core/kickoffproxymodel.h @@ -0,0 +1,53 @@ +/* + Copyright 2008 Marco Martin + + 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 KICKOFFPROXYMODEL_H +#define KICKOFFPROXYMODEL_H + +// Qt +#include + +// KDE + +namespace Kickoff +{ + +/** + * Base model for Kickoff models based on QAbstractProxyModel, enables drag and drop support + */ +class KickoffProxyModel : public QAbstractProxyModel +{ + Q_OBJECT + +public: + /** Construct a new KickoffModel with the specified parent. */ + KickoffProxyModel(QObject *parent = 0); + virtual ~KickoffProxyModel(); + + //Reimplementations + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QMimeData *mimeData(const QModelIndexList &indexes) const; + virtual QStringList mimeTypes() const; + virtual Qt::DropActions supportedDropActions() const; + virtual Qt::DropActions supportedDragActions() const; +}; + +} + +#endif // KICKOFFPROXYMODEL_H diff --git a/applets/kickoff/core/krunnermodel.cpp b/applets/kickoff/core/krunnermodel.cpp new file mode 100644 index 0000000000..db2adab23c --- /dev/null +++ b/applets/kickoff/core/krunnermodel.cpp @@ -0,0 +1,289 @@ +/* + Copyright 2009 Ivan Cukic + + 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 "krunnermodel.h" + +// Qt +#include +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +//#include +//#include +#include +#include + + +// Local +#include "recentapplications.h" + +#define DELAY_TIME 50 + +using namespace Kickoff; + +Plasma::RunnerManager * _runnerManager = NULL; +Plasma::RunnerManager * runnerManager() { + if (_runnerManager == NULL) { + KConfigGroup conf = + componentData().config()->group("KRunner"); + + conf.writeEntry("loadAll", false); + _runnerManager = new Plasma::RunnerManager(conf); + + // initializing allowed runners + QStringList allowed; + allowed + << "places" + << "shell" + << "services" + << "bookmarks" + << "recentdocuments" + << "locations" + << "baloosearch"; + + _runnerManager->setAllowedRunners(allowed); + + conf.sync(); + + // runner: "konquerorsessions" "Konqueror Sessions" + // runner: "desktopsessions" "Desktop Sessions" + // runner: "places" "Places" + // runner: "windows" "Windows" + // runner: "plasma-desktop" "Plasma Desktop Shell" + // runner: "services" "Applications" + // runner: "PowerDevil" "PowerDevil" + // runner: "browserhistory" "Web Browser History" + // runner: "shell" "Command Line" + // runner: "katesessions" "Kate Sessions" + // runner: "locations" "Locations" + // runner: "webshortcuts" "Web Shortcuts" + // runner: "kabccontacts" "Contacts" + // runner: "konsolesessions" "Konsole Sessions" + // runner: "recentdocuments" "Recent Documents" + // runner: "calculator" "Calculator" + // runner: "amarok" "Amarok" + // runner: "wikipedia" "Wikipedia" + // runner: "kopete" "Kopete Contact Runner" + // runner: "bookmarks" "Bookmarks" + // runner: "unitconverter" "Unit Converter" + } + return _runnerManager; +} + +KService::Ptr Kickoff::serviceForUrl(const KUrl & url) +{ + QString runner = url.host(); + QString id = url.path(); + + if (id.startsWith(QLatin1Char('/'))) { + id = id.remove(0, 1); + } + + if (runner != QLatin1String("services")) { + return KService::Ptr(NULL); + } + + // URL path example: services_kde4-kate.desktop + // or: services_firefox.desktop + id.remove("services_"); + + return KService::serviceByStorageId(id); +} + + +class ResultItem { +public: + ResultItem() + { + } + + ResultItem(QIcon _icon, QString _name, QString _description, QVariant _data) + : icon(_icon), + name(_name), + description(_description), + data(_data) + { + } + + QIcon icon; + QString name, description; + QVariant data; +}; + +bool KRunnerItemHandler::openUrl(const KUrl& url) +{ + QString runner = url.host(); + QString id = url.path(); + if (id.startsWith(QLatin1Char('/'))) { + id = id.remove(0, 1); + } + + // Since krunner:// urls can't be added to recent applications, + // we find the local .desktop entry. + + KService::Ptr service = serviceForUrl(url); + if (service) { + RecentApplications::self()->add(service); + } else { + qWarning() << "Failed to find service for" << url; + } + + runnerManager()->run(id); + return true; +} + +class KRunnerModel::Private { +public: + Private() + { + } + + ~Private() + { + } + + QBasicTimer searchDelay; + QString searchQuery; + DisplayOrder displayOrder; +}; + +KRunnerModel::KRunnerModel(QObject *parent) + : KickoffModel(parent) + , d(new Private()) +{ + connect(runnerManager(), + SIGNAL(matchesChanged(QList)), + this, + SLOT(matchesChanged(QList))); + + UrlItemLauncher::addGlobalHandler(UrlItemLauncher::ProtocolHandler, "krunner", new KRunnerItemHandler); +} + +KRunnerModel::~KRunnerModel() +{ + delete d; +} + +void KRunnerModel::setQuery(const QString& query) +{ + runnerManager()->reset(); + clear(); + + d->searchQuery = query.trimmed(); + + if (d->searchQuery.isEmpty()) { + return; + } + + d->searchDelay.start(DELAY_TIME, this); +} + +void KRunnerModel::timerEvent(QTimerEvent * event) +{ + KickoffModel::timerEvent(event); + + if (event->timerId() == d->searchDelay.timerId()) { + d->searchDelay.stop(); + runnerManager()->launchQuery(d->searchQuery); + }; +} + +void KRunnerModel::setNameDisplayOrder(DisplayOrder displayOrder) +{ + d->displayOrder = displayOrder; +} + +DisplayOrder KRunnerModel::nameDisplayOrder() const +{ + return d->displayOrder; +} + +void KRunnerModel::matchesChanged(const QList< Plasma::QueryMatch > & m) +{ + QList< Plasma::QueryMatch > matches = m; + + qSort(matches.begin(), matches.end()); + + clear(); + + while (matches.size()) { + Plasma::QueryMatch match = matches.takeLast(); + qDebug() << "matches " << QString("krunner://") + match.runner()->id() + "/" + match.id(); + appendRow( + StandardItemFactory::createItem( + match.icon(), + match.text(), + match.subtext(), + QString("krunner://") + match.runner()->id() + "/" + match.id() + ) + ); + } +} + +Qt::ItemFlags KRunnerModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = KickoffModel::flags(index); + + if (index.isValid()) { + KUrl url = data(index, UrlRole).toString(); + QString host = url.host(); + if (host != "services") { + flags &= ~ ( Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled ); + } + } else { + flags = 0; + } + + return flags; +} + +QMimeData * KRunnerModel::mimeData(const QModelIndexList &indexes) const +{ + KUrl::List urls; + + foreach (const QModelIndex & index, indexes) { + KUrl url = data(index, UrlRole).toString(); + + KService::Ptr service = serviceForUrl(url); + + if (service) { + urls << KUrl(service->entryPath()); + } + } + + QMimeData *mimeData = new QMimeData(); + + if (!urls.isEmpty()) { + urls.populateMimeData(mimeData); + } + + return mimeData; + +} + +#include "krunnermodel.moc" diff --git a/applets/kickoff/core/krunnermodel.h b/applets/kickoff/core/krunnermodel.h new file mode 100644 index 0000000000..3916829b1a --- /dev/null +++ b/applets/kickoff/core/krunnermodel.h @@ -0,0 +1,76 @@ +/* + Copyright 2009 Ivan Cukic + + 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 KRUNNERMODEL_H +#define KRUNNERMODEL_H + +#include "models.h" +#include "kickoffmodel.h" +#include "urlitemlauncher.h" + +namespace Plasma { + class QueryMatch; +} + +namespace Kickoff { + + KService::Ptr serviceForUrl(const KUrl & url); + +class KRunnerItemHandler : public UrlItemHandler { +public: + virtual bool openUrl(const KUrl& url); +}; + +class KRunnerModel : public KickoffModel +{ + Q_OBJECT + +public: + KRunnerModel(QObject *parent = NULL); + virtual ~KRunnerModel(); + void setNameDisplayOrder(DisplayOrder displayOrder); + DisplayOrder nameDisplayOrder() const; + + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QMimeData *mimeData(const QModelIndexList &indexes) const; + // virtual QStringList mimeTypes() const; + // virtual Qt::DropActions supportedDropActions() const; + // virtual Qt::DropActions supportedDragActions() const; + +private: + void timerEvent(QTimerEvent * event); + +public Q_SLOTS: + void setQuery(const QString& query); + +private Q_SLOTS: + void matchesChanged(const QList< Plasma::QueryMatch > & matches); + +Q_SIGNALS: + void resultsAvailable(); + +private: + class Private; + Private * const d; +}; + +} + +#endif // KRUNNERMODEL_H + diff --git a/applets/kickoff/core/kuserproxy.cpp b/applets/kickoff/core/kuserproxy.cpp new file mode 100644 index 0000000000..50b56fa1f4 --- /dev/null +++ b/applets/kickoff/core/kuserproxy.cpp @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright 2013 Marco Martin * + * Copyright 2014 Sebastian Kugler * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 + +#include "kuserproxy.h" +#include +#include +#include + +#include + +#include + +KUserProxy::KUserProxy (QObject *parent) + : QObject(parent) +{ +} + +KUserProxy::~KUserProxy() +{ +} + +QString KUserProxy::fullName() const +{ + return m_user.property(KUser::FullName).toString(); +} + +QString KUserProxy::loginName() const +{ + return m_user.loginName(); +} + +QString KUserProxy::faceIconPath() const +{ + const QString u = m_user.faceIconPath(); + const QFile f(u); + if (f.exists(u)) { + // We need to return a file URL, not a simple path + return QUrl::fromLocalFile(u).toString(); + } + return QString(); +} + +QString KUserProxy::os() +{ + if (m_os.isEmpty()) { + m_os = i18n("Plasma by KDE"); + QFile osfile("/etc/os-release"); + if (osfile.exists()) { + if (!osfile.open(QIODevice::ReadOnly | QIODevice::Text)) { + return QString(); + } + + QTextStream in(&osfile); + while(!in.atEnd()) { + QString line = in.readLine(); + if (line.startsWith("PRETTY_NAME")) { + QStringList fields = line.split("PRETTY_NAME=\""); + if (fields.count() == 2) { + osfile.close(); + QString pretty = fields.at(1); + pretty.chop(1); + m_os = pretty; + return pretty; + } + } + } + osfile.close(); + } + } + return m_os; +} + +QString KUserProxy::host() const +{ + char hostname[256]; + hostname[0] = '\0'; + if (!gethostname(hostname, sizeof(hostname))) { + hostname[sizeof(hostname)-1] = '\0'; + } + return QString(hostname); +} + diff --git a/applets/kickoff/core/kuserproxy.h b/applets/kickoff/core/kuserproxy.h new file mode 100644 index 0000000000..ec77217d39 --- /dev/null +++ b/applets/kickoff/core/kuserproxy.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright 2014 Sebastian Kügler * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 KUSERPROXY_H +#define KUSERPROXY_H + +#include + +#include + +class KUserProxy : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString fullName READ fullName CONSTANT) + Q_PROPERTY(QString loginName READ loginName CONSTANT) + Q_PROPERTY(QString faceIconPath READ faceIconPath CONSTANT) + Q_PROPERTY(QString os READ os CONSTANT) + Q_PROPERTY(QString host READ host CONSTANT) + +public: + KUserProxy(QObject *parent = 0); + ~KUserProxy(); + + QString fullName() const; + QString loginName() const; + QString faceIconPath() const; + QString os(); + QString host() const; + +private: + KUser m_user; + QString m_os; +}; + +#endif //KUSERPROXY_H + diff --git a/applets/kickoff/core/leavemodel.cpp b/applets/kickoff/core/leavemodel.cpp new file mode 100644 index 0000000000..6a21f43022 --- /dev/null +++ b/applets/kickoff/core/leavemodel.cpp @@ -0,0 +1,212 @@ +/* + Copyright 2007 Robert Knight + + 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 "leavemodel.h" + +// Qt +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include + +// Local +#include "models.h" +#include "itemhandlers.h" + +using namespace Kickoff; + +class LeaveModel::Private +{ +}; + +QStandardItem* LeaveModel::createStandardItem(const QString& url) +{ + //Q_ASSERT(KUrl(url).scheme() == "leave"); + QStandardItem *item = new QStandardItem(); + const QString basename = QFileInfo(url).baseName(); + if (basename == "logoutonly") { + item->setText(i18n("Log out")); + item->setIcon(KIcon("system-log-out")); + item->setData(i18n("End session"), Kickoff::SubTitleRole); + } else if (basename == "lock") { + item->setText(i18n("Lock")); + item->setIcon(KIcon("system-lock-screen")); + item->setData(i18n("Lock screen"), Kickoff::SubTitleRole); + } else if (basename == "switch") { + item->setText(i18n("Switch user")); + item->setIcon(KIcon("system-switch-user")); + item->setData(i18n("Start a parallel session as a different user"), Kickoff::SubTitleRole); + } else if (basename == "shutdown") { + item->setText(i18n("Shut down")); + item->setIcon(KIcon("system-shutdown")); + item->setData(i18n("Turn off computer"), Kickoff::SubTitleRole); + } else if (basename == "restart") { + item->setText(i18nc("Restart computer", "Restart")); + item->setIcon(KIcon("system-reboot")); + item->setData(i18n("Restart computer"), Kickoff::SubTitleRole); + } else if (basename == "savesession") { + item->setText(i18n("Save Session")); + item->setIcon(KIcon("document-save")); + item->setData(i18n("Save current session for next login"), Kickoff::SubTitleRole); + } else if (basename == "standby") { + item->setText(i18nc("Puts the system on standby", "Standby")); + item->setIcon(KIcon("system-suspend")); + item->setData(i18n("Pause without logging out"), Kickoff::SubTitleRole); + } else if (basename == "suspenddisk") { + item->setText(i18n("Hibernate")); + item->setIcon(KIcon("system-suspend-hibernate")); + item->setData(i18n("Suspend to disk"), Kickoff::SubTitleRole); + } else if (basename == "suspendram") { + item->setText(i18n("Sleep")); + item->setIcon(KIcon("system-suspend")); + item->setData(i18n("Suspend to RAM"), Kickoff::SubTitleRole); + } else { + item->setText(basename); + item->setData(url, Kickoff::SubTitleRole); + } + item->setData(url, Kickoff::UrlRole); + return item; +} + +LeaveModel::LeaveModel(QObject *parent) + : QStandardItemModel(parent) + , d(0) +{ + QHash roles; + roles[Qt::DisplayRole] = "display"; + roles[Qt::DecorationRole] = "decoration"; + roles[Kickoff::SubTitleRole] = "subtitle"; + roles[Kickoff::UrlRole] = "url"; + roles[GroupNameRole] = "group"; + setRoleNames(roles); + updateModel(); + Kickoff::UrlItemLauncher::addGlobalHandler(Kickoff::UrlItemLauncher::ProtocolHandler, "leave", new Kickoff::LeaveItemHandler); +} + +QVariant LeaveModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || section != 0) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + return i18n("Leave"); + break; + default: + return QVariant(); + } +} + +void LeaveModel::updateModel() +{ + clear(); + + // Session Options + const QString session = i18n("Session"); + + // Logout + const bool canLogout = KAuthorized::authorizeKAction("logout") && KAuthorized::authorize("logout"); + if (canLogout) { + QStandardItem *logoutOption = createStandardItem("leave:/logoutonly"); + logoutOption->setData(session, Kickoff::GroupNameRole); + appendRow(logoutOption); + } + + // Lock + if (KAuthorized::authorizeKAction("lock_screen")) { + QStandardItem *lockOption = createStandardItem("leave:/lock"); + lockOption->setData(session, Kickoff::GroupNameRole); + appendRow(lockOption); + } + + // Save Session + if (canLogout) { + KConfigGroup c(KSharedConfig::openConfig("ksmserverrc", KConfig::NoGlobals), "General"); + if (c.readEntry("loginMode") == "restoreSavedSession") { + QStandardItem *saveSessionOption = createStandardItem("leave:/savesession"); + saveSessionOption->setData(session, Kickoff::GroupNameRole); + appendRow(saveSessionOption); + } + } + + // Switch User + if (KDisplayManager().isSwitchable() && KAuthorized::authorize(QLatin1String("switch_user"))) { + QStandardItem *switchUserOption = createStandardItem("leave:/switch"); + switchUserOption->setData(session, Kickoff::GroupNameRole); + appendRow(switchUserOption); + } + + // System Options + +//FIXME: the proper fix is to implement the KWorkSpace methods for Windows +#ifndef Q_WS_WIN + const QString system = i18n("System"); + QSet< Solid::PowerManagement::SleepState > spdMethods = Solid::PowerManagement::supportedSleepStates(); + if (spdMethods.contains(Solid::PowerManagement::StandbyState)) { + QStandardItem *standbyOption = createStandardItem("leave:/standby"); + standbyOption->setData(system, Kickoff::GroupNameRole); + appendRow(standbyOption); + } + + if (spdMethods.contains(Solid::PowerManagement::SuspendState)) { + QStandardItem *suspendramOption = createStandardItem("leave:/suspendram"); + suspendramOption->setData(system, Kickoff::GroupNameRole); + appendRow(suspendramOption); + } + + if (spdMethods.contains(Solid::PowerManagement::HibernateState)) { + QStandardItem *suspenddiskOption = createStandardItem("leave:/suspenddisk"); + suspenddiskOption->setData(system, Kickoff::GroupNameRole); + appendRow(suspenddiskOption); + } + + if (canLogout) { + if (KWorkSpace::canShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeReboot)) { + // Restart + QStandardItem *restartOption = createStandardItem("leave:/restart"); + restartOption->setData(system, Kickoff::GroupNameRole); + appendRow(restartOption); + } + + if (KWorkSpace::canShutDown(KWorkSpace::ShutdownConfirmDefault, KWorkSpace::ShutdownTypeHalt)) { + // Shutdown + QStandardItem *shutDownOption = createStandardItem("leave:/shutdown"); + shutDownOption->setData(system, Kickoff::GroupNameRole); + appendRow(shutDownOption); + } + } +#endif +} + +LeaveModel::~LeaveModel() +{ + delete d; +} + +#include "leavemodel.moc" + diff --git a/applets/kickoff/core/leavemodel.h b/applets/kickoff/core/leavemodel.h new file mode 100644 index 0000000000..ed933173b6 --- /dev/null +++ b/applets/kickoff/core/leavemodel.h @@ -0,0 +1,48 @@ +/* + Copyright 2007 Robert Knight + + 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 LEAVEMODEL_H +#define LEAVEMODEL_H + +#include + +namespace Kickoff +{ + +class LeaveModel : public QStandardItemModel +{ + Q_OBJECT + +public: + LeaveModel(QObject *parent = NULL); + ~LeaveModel(); + + static QStandardItem* createStandardItem(const QString& url); + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + void updateModel(); + +private: + class Private; + Private * const d; +}; + +} + +#endif // LEAVEMODEL_H diff --git a/applets/kickoff/core/models.cpp b/applets/kickoff/core/models.cpp new file mode 100644 index 0000000000..b9f435c892 --- /dev/null +++ b/applets/kickoff/core/models.cpp @@ -0,0 +1,214 @@ +/* + Copyright 2007 Robert Knight + + 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 "models.h" +#include "leavemodel.h" + +// Qt +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Kickoff; + +namespace Kickoff +{ + +Q_GLOBAL_STATIC_WITH_ARGS(KUrl, homeUrl, (QDir::homePath())) +Q_GLOBAL_STATIC_WITH_ARGS(KUrl, remoteUrl, ("remote:/")) +K_GLOBAL_STATIC(StandardItemFactoryData, factoryData) + +StandardItemFactoryData* deviceFactoryData() +{ + return factoryData; +} +} // namespace Kickoff + +QStandardItem *StandardItemFactory::createItemForUrl(const QString& urlString, DisplayOrder displayOrder) +{ + KUrl url(urlString); + + QStandardItem *item = 0; + + // Match files ending with ".desktop" and being local or having a relative + // path. For instance applications that still installs .desktop files at + // /usr/share/applnk, like KVirc 3 + if (urlString.endsWith(QLatin1String(".desktop")) && (url.isLocalFile() || url.isRelative())) { + // .desktop files may be services (type field == 'Application' or 'Service') + // or they may be other types such as links. + // + // first look in the KDE service database to see if this file is a service, + // otherwise represent it as a generic .desktop file + KService::Ptr service = KService::serviceByDesktopPath(url.toLocalFile()); + if (service) { + return createItemForService(service, displayOrder); + } + + item = new QStandardItem; + KDesktopFile desktopFile(url.toLocalFile()); + item->setText(QFileInfo(urlString.mid(0, urlString.lastIndexOf('.'))).completeBaseName()); + item->setIcon(KIcon(desktopFile.readIcon())); + + //FIXME: desktopUrl is a hack around borkage in KRecentDocuments which + // stores a path in the URL field! + KUrl desktopUrl(desktopFile.desktopGroup().readPathEntry("URL", QString())); + if (!desktopUrl.url().isEmpty()) { + item->setData(desktopUrl.url(), Kickoff::UrlRole); + } else { + // desktopUrl.url() is empty if the file doesn't exist so set the + // url role to that which was passed so that the item can still be + // manually removed + item->setData(urlString, Kickoff::UrlRole); + } + + QString subTitle = desktopUrl.isLocalFile() ? desktopUrl.toLocalFile() : desktopUrl.prettyUrl(); + item->setData(subTitle, Kickoff::SubTitleRole); + + setSpecialUrlProperties(desktopUrl, item); + } else if (url.scheme() == "leave") { + item = LeaveModel::createStandardItem(urlString); + } else { + item = new QStandardItem; + const QString subTitle = url.isLocalFile() ? url.toLocalFile() : url.prettyUrl(); + QString basename = QFileInfo(url.prettyUrl()).completeBaseName(); + if (basename.isNull()) { + basename = subTitle; + } + + item->setText(basename); + //FIXME +// item->setIcon(KIcon(KMimeType::iconNameForUrl(url))); + item->setData(url.url(), Kickoff::UrlRole); + item->setData(subTitle, Kickoff::SubTitleRole); + + setSpecialUrlProperties(url, item); + } + + return item; +} + +void StandardItemFactory::setSpecialUrlProperties(const KUrl& url, QStandardItem *item) +{ + // specially handled URLs + if (homeUrl() && url == *homeUrl()) { + item->setText(i18n("Home Folder")); + item->setIcon(KIcon("user-home")); + } else if (remoteUrl() && url == *remoteUrl()) { + item->setText(i18n("Network Folders")); + } +} + +QStandardItem *StandardItemFactory::createItem(const QIcon & icon, const QString & title, + const QString & description, const QString & url) +{ + QStandardItem *appItem = new QStandardItem; + + appItem->setText(title); + appItem->setIcon(icon); + appItem->setData(description, Kickoff::SubTitleRole); + appItem->setData(url, Kickoff::UrlRole); + + return appItem; +} + +QStandardItem *StandardItemFactory::createItemForService(KService::Ptr service, DisplayOrder displayOrder) +{ + QStandardItem *appItem = new QStandardItem; + + QString genericName = service->genericName(); + QString appName = service->name(); + bool nameFirst = displayOrder == NameBeforeDescription; + appItem->setText(nameFirst || genericName.isEmpty() ? appName : genericName); + appItem->setIcon(KIcon(service->icon())); + appItem->setData(service->entryPath(), Kickoff::UrlRole); + + if (nameFirst) { + if (!genericName.isEmpty()) { + appItem->setData(genericName, Kickoff::SubTitleRole); + } + } else if (!genericName.isEmpty()) { + // we only set the subtitle to appname if the generic name is empty because if + // the generic name IS empty, then the app name is used as the title role + // and we don't want it repeated twice. + appItem->setData(appName, Kickoff::SubTitleRole); + } + + return appItem; +} + +bool Kickoff::isLaterVersion(KService::Ptr first , KService::Ptr second) +{ + // a very crude heuristic using the .desktop path names + // which only understands kde3 vs kde4 + bool firstIsKde4 = first->entryPath().contains("kde4"); + bool secondIsKde4 = second->entryPath().contains("kde4"); + + return firstIsKde4 && !secondIsKde4; +} + +QStringList Kickoff::systemApplicationList() +{ + KConfigGroup appsGroup = componentData().config()->group("SystemApplications"); + QStringList apps; + apps << "systemsettings"; + apps = appsGroup.readEntry("DesktopFiles", apps); + return apps; +} + +#if 0 +void Kickoff::swapModelIndexes(QModelIndex& first, QModelIndex& second) +{ + Q_ASSERT(first.isValid()); + Q_ASSERT(second.isValid()); + + QAbstractItemModel *firstModel = const_cast(first.model()); + QAbstractItemModel *secondModel = const_cast(second.model()); + + Q_ASSERT(firstModel && secondModel); + + QMap firstIndexData = firstModel->itemData(first); + QMap secondIndexData = secondModel->itemData(second); + + firstModel->setItemData(first, secondIndexData); + secondModel->setItemData(second, firstIndexData); +} +#endif + +K_GLOBAL_STATIC_WITH_ARGS(KComponentData, kickoffComponent, ("kickoff", QByteArray(), KComponentData::SkipMainComponentRegistration)) +KComponentData Kickoff::componentData() +{ + return *kickoffComponent; +} + + + diff --git a/applets/kickoff/core/models.h b/applets/kickoff/core/models.h new file mode 100644 index 0000000000..05fe321611 --- /dev/null +++ b/applets/kickoff/core/models.h @@ -0,0 +1,140 @@ +/* + Copyright 2007 Robert Knight + + 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 MODELS_H +#define MODELS_H + +// Qt + +// KDE +#include +#include + +class QStandardItem; +class KUrl; +class QModelIndex; + +namespace Solid +{ +class Device; +} + +namespace Kickoff +{ +class StandardItemFactoryData +{ +public: + QHash deviceByUrl; +}; + +StandardItemFactoryData* deviceFactoryData(); + +/** + * List of applications contained in the DesktopFiles key in the + * SystemApplications group, used to populate the System model + * @return list of desktop entry names + */ +QStringList systemApplicationList(); + +/** + * Additional data roles for data which the Kickoff models supply with their items + * for use when rendering the items and launching them. + */ +enum DataRole { + /** A sub title to be displayed below the text from the item's Qt::DisplayRole data */ + SubTitleRole = Qt::UserRole + 1, + FirstDataRole = SubTitleRole, + /** The URL to be opened when executing the item. */ + UrlRole = Qt::UserRole + 2, + /** The Solid device identifier for items which represent devices. */ + DeviceUdiRole = Qt::UserRole + 3, + /** The amount of space (in Kilobytes) used for items which represent storage. */ + DiskUsedSpaceRole = Qt::UserRole + 4, + /** The amount of free space (in Kilobytes) for items which represent storage. */ + DiskFreeSpaceRole = Qt::UserRole + 5, + SubTitleMandatoryRole = Qt::UserRole + 6, + /** Is item a separator. **/ + SeparatorRole = Qt::UserRole + 7, + /** relative path of the item */ + RelPathRole = Qt::UserRole + 8, + IconNameRole = Qt::UserRole + 9, + GroupNameRole = IconNameRole, + LastDataRole = Qt::UserRole + 10 +}; + +/** + * This enum describes the policy for displaying + * Name of Application - Description + * Description - Name of Application + */ +enum DisplayOrder { + NameAfterDescription, + NameBeforeDescription +}; + +/** + * Factory for creating QStandardItems with appropriate text, icons, URL + * and other Kickoff-specific information for a given URL or Service. + */ +class StandardItemFactory +{ +public: + static QStandardItem *createItemForUrl(const QString& url, DisplayOrder displayOrder); + static QStandardItem *createItemForService(KService::Ptr service, + DisplayOrder displayOrder); + static QStandardItem *createItem(const QIcon & icon, const QString & title, + const QString & description, const QString & url); + +private: + static void setSpecialUrlProperties(const KUrl& url, QStandardItem *item); +}; + +/** + * Abstract base class for delegates which provide information about a model + * item's state in a particular view. + */ +class ItemStateProvider +{ +public: + virtual ~ItemStateProvider() {} + + /** + * Returns true if a @p index should be drawn in the view or + * false if it should be hidden. + */ + virtual bool isVisible(const QModelIndex& index) const = 0; +}; + +// returns true if 'first' represents a more recent version of +// an application than 'second' +// +// eg. isLaterVersion(myapp_kde4,myapp_kde3) returns true +bool isLaterVersion(KService::Ptr first , KService::Ptr second); + +#if 0 +/** Swaps the data for two indexes in a QAbstractItemModel */ +void swapModelIndexes(QModelIndex& first, QModelIndex& second); +#endif + +// returns the Kickoff component data, this is mainly used +// to access the Kickoff shared config data +KComponentData componentData(); +} + +#endif //MODELS_H diff --git a/applets/kickoff/core/org.kde.kickoff.recent.xml b/applets/kickoff/core/org.kde.kickoff.recent.xml new file mode 100644 index 0000000000..d013f62279 --- /dev/null +++ b/applets/kickoff/core/org.kde.kickoff.recent.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/applets/kickoff/core/org.kde.kickoff.xml b/applets/kickoff/core/org.kde.kickoff.xml new file mode 100644 index 0000000000..b0f5d097ab --- /dev/null +++ b/applets/kickoff/core/org.kde.kickoff.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/applets/kickoff/core/qmldir b/applets/kickoff/core/qmldir new file mode 100644 index 0000000000..b95a24e990 --- /dev/null +++ b/applets/kickoff/core/qmldir @@ -0,0 +1 @@ +plugin kickoffplugin diff --git a/applets/kickoff/core/recentapplications.cpp b/applets/kickoff/core/recentapplications.cpp new file mode 100644 index 0000000000..910868de60 --- /dev/null +++ b/applets/kickoff/core/recentapplications.cpp @@ -0,0 +1,195 @@ +/* + Copyright 2007 Robert Knight + + 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 "recentapplications.h" + +// Qt +#include +#include + +// KDE +#include +#include + +#include + +// Local +#include "models.h" + +using namespace Kickoff; + +class RecentApplications::Private +{ +public: + class ServiceInfo; + + Private() : defaultMaxServices(DEFAULT_MAX_SERVICES) { + KConfigGroup recentGroup = componentData().config()->group("RecentlyUsed"); + QList recentApplications = recentGroup.readEntry("Applications", QList()); + defaultMaxServices = maxServices = qMax(0, recentGroup.readEntry("MaxApplications", defaultMaxServices)); + + // TESTING + // the actual last date/time is not currently recorded, instead we just use + // the current date/time and adjust it by one second after each item is added + // to preserve the order of the applications in the list loaded from the KConfig + // source + QDateTime dateTime = QDateTime::currentDateTime(); + foreach(const QString& application, recentApplications) { + ServiceInfo info; + info.storageId = application; + info.startCount = 1; + info.lastStartedTime = dateTime; + addEntry(info.storageId, info); + dateTime = dateTime.addSecs(1); + } + }; + ~Private() { + KConfigGroup recentGroup = componentData().config()->group("RecentlyUsed"); + + QList services = serviceInfo.values(); + qSort(services.begin(), services.end()); + + // TESTING + // only the desktop file used is currently recorded, information such + // as start count and date/time of last used is lost + QList recentApplications; + foreach(const ServiceInfo& info, services) { + recentApplications << info.storageId; + } + + recentGroup.writeEntry("Applications", recentApplications); + recentGroup.config()->sync(); + } + void addEntry(const QString& id, ServiceInfo& info) { + // if this service is already in the list then remove the existing + // queue entry (so that there are no duplicates in the queue) + if (serviceInfo.contains(id)) { + qDebug() << "Duplicate entry added. Removing existing entry from queue."; + serviceQueue.erase(serviceInfo[id].queueIter); + } + + serviceQueue.append(id); + info.queueIter = --serviceQueue.end(); + serviceInfo.insert(id, info); + } + + void removeExpiredEntries() { + // if more than the maximum number of services have been added + // remove the least recently used service + while (serviceQueue.count() > maxServices) { + QString removeId = serviceQueue.takeFirst(); + qDebug() << "More than the maximal " << maxServices << " services added. Removing" << removeId << "from queue."; + serviceInfo.remove(removeId); + emit instance.applicationRemoved(KService::serviceByStorageId(removeId)); + } + } + + class ServiceInfo + { + public: + ServiceInfo() : startCount(0) {} + + QString storageId; + int startCount; + QDateTime lastStartedTime; + QLinkedList::iterator queueIter; + + bool operator<(const ServiceInfo& rhs) const { + return this->lastStartedTime < rhs.lastStartedTime; + } + }; + + static const int DEFAULT_MAX_SERVICES = 5; + int defaultMaxServices, maxServices; + // queue to keep track of the order in which services have been used + // (most recently used at the back) + QLinkedList serviceQueue; + QHash serviceInfo; + RecentApplications instance; +}; +K_GLOBAL_STATIC(RecentApplications::Private, privateSelf) + +RecentApplications *RecentApplications::self() +{ + return &privateSelf->instance; +} + +RecentApplications::RecentApplications() +{ +} + +QList RecentApplications::recentApplications() const +{ + QList services = privateSelf->serviceInfo.values(); + qSort(services.begin(), services.end(), qGreater()); + + QList servicePtrs; + foreach(const Private::ServiceInfo& info, services) { + KService::Ptr s = KService::serviceByStorageId(info.storageId); + + if (s) { + servicePtrs << s; + } + } + return servicePtrs; +} +int RecentApplications::startCount(KService::Ptr service) const +{ + return privateSelf->serviceInfo[service->storageId()].startCount; +} +QDateTime RecentApplications::lastStartedTime(KService::Ptr service) const +{ + return privateSelf->serviceInfo[service->storageId()].lastStartedTime; +} +void RecentApplications::setMaximum(int maximum) +{ + Q_ASSERT(maximum >= 0); + privateSelf->maxServices = maximum; + privateSelf->removeExpiredEntries(); +} +int RecentApplications::maximum() const +{ + return privateSelf->maxServices; +} +int RecentApplications::defaultMaximum() const +{ + return privateSelf->defaultMaxServices; +} +void RecentApplications::add(KService::Ptr service) +{ + Private::ServiceInfo info = privateSelf->serviceInfo.value(service->storageId()); + info.storageId = service->storageId(); + info.startCount++; + info.lastStartedTime = QDateTime::currentDateTime(); + + privateSelf->addEntry(info.storageId, info); + + qDebug() << "Recent app added" << info.storageId << info.startCount; + emit applicationAdded(service, info.startCount); + + privateSelf->removeExpiredEntries(); +} +void RecentApplications::clear() +{ + privateSelf->serviceInfo.clear(); + emit cleared(); +} + +#include "recentapplications.moc" diff --git a/applets/kickoff/core/recentapplications.h b/applets/kickoff/core/recentapplications.h new file mode 100644 index 0000000000..b73d5265c5 --- /dev/null +++ b/applets/kickoff/core/recentapplications.h @@ -0,0 +1,91 @@ +/* + Copyright 2007 Robert Knight + + 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 RECENTAPPLICATIONS_H +#define RECENTAPPLICATIONS_H + +// Qt +#include +#include + +// KDE +#include + +namespace Kickoff +{ + +/** + * Singleton class which can be used to keep track of recently started applications + * in the Kickoff launcher. + * + * RecentApplications information persists between sessions. + */ +class RecentApplications : public QObject +{ + Q_OBJECT +public: + class Private; + friend class Private; + + static RecentApplications *self(); + + /** + * List of service pointers for recently started applications in the order in which + * they were started, with the most recently used application first. + */ + QList recentApplications() const; + /** Returns the number of times an application represented by @p service has been started. */ + int startCount(KService::Ptr service) const; + /** Returns the last time and date with the application represented by @p service was started. */ + QDateTime lastStartedTime(KService::Ptr service) const; + + /** Sets the maximum number of recently used applications to remember. */ + void setMaximum(int max); + /** Returns the maximum number of recently used applications that are remembered. */ + int maximum() const; + /** Returns the default maximum number of recently used applications that are remembered as defined + either in the configfile as "MaxApplications" or via the DEFAULT_MAX_SERVICES macro. */ + int defaultMaximum() const; + +public Q_SLOTS: + /** + * Registers the startup of an application. This should be called whenever a new application + * or service is started. + */ + void add(KService::Ptr service); + /** Clear the list of recent applications. */ + void clear(); + +Q_SIGNALS: + /** Emitted after add() has been called. */ + void applicationAdded(KService::Ptr service, int startCount); + /** Emitted after remove() has been called. */ + void applicationRemoved(KService::Ptr service); + /** Emitted after clear() has been called. */ + void cleared(); + +private: + RecentApplications(); +}; + +} + +#endif // RECENTAPPLICATIONS_H + + diff --git a/applets/kickoff/core/recentlyusedmodel.cpp b/applets/kickoff/core/recentlyusedmodel.cpp new file mode 100644 index 0000000000..eb7abeb285 --- /dev/null +++ b/applets/kickoff/core/recentlyusedmodel.cpp @@ -0,0 +1,282 @@ +/* + Copyright 2007 Robert Knight + Copyright 2011 Martin Gräßlin + + 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 "recentlyusedmodel.h" + +// Qt + +// KDE +#include +#include +#include +#include +#include +#include + +// Local +#include "recentapplications.h" +#include "recentadaptor.h" + +using namespace Kickoff; + +class RecentlyUsedModel::Private +{ +public: + Private(RecentlyUsedModel *parent, RecentType recenttype, int maxRecentApps) + : q(parent), + recenttype(recenttype), + maxRecentApps(maxRecentApps >= 0 ? maxRecentApps : Kickoff::RecentApplications::self()->defaultMaximum()), + displayOrder(NameAfterDescription), + applicationTitle(i18n("Applications")), + documentTitle(i18n("Documents")), + recentApplicationCount(0) + { + } + + bool removeExistingItem(const QString& path) { + if (!itemsByPath.contains(path)) { + return false; + } + + QStandardItem *existingItem = itemsByPath[path]; + qDebug() << "Removing existing item" << existingItem; + QModelIndex index = q->indexFromItem(existingItem); + if (!index.isValid()) { + qDebug() << "Now Index for our existing item"; + return false; + } + q->takeRow(index.row()); + itemsByPath.remove(path); + delete existingItem; + return true; + } + + void addRecentApplication(KService::Ptr service, bool append) { + // remove existing item if any + if (removeExistingItem(service->entryPath())) { + --recentApplicationCount; + } + + QStandardItem *appItem = StandardItemFactory::createItemForService(service, displayOrder); + appItem->setData(applicationTitle, Kickoff::GroupNameRole); + itemsByPath.insert(service->entryPath(), appItem); + + if (append) { + q->insertRow(recentApplicationCount, appItem); + } else { + q->insertRow(0, appItem); + } + ++recentApplicationCount; + + while (recentApplicationCount > maxRecentApps) { + --recentApplicationCount; + QList row = q->takeRow(recentApplicationCount); + + //don't leave pending stuff in itemsByPath + if (!row.isEmpty()) { + itemsByPath.remove(row.first()->data(UrlRole).toString()); + qDeleteAll(row.begin(), row.end()); + } + } + } + + void addRecentDocument(const QString& desktopPath, bool append) { + // remove existing item if any + KDesktopFile desktopFile(desktopPath); + KUrl documentUrl = desktopFile.readUrl(); + + removeExistingItem(documentUrl.url()); + + QStandardItem *documentItem = StandardItemFactory::createItemForUrl(desktopPath, displayOrder); + documentItem->setData(true, Kickoff::SubTitleMandatoryRole); + documentItem->setData(documentTitle, Kickoff::GroupNameRole); + itemsByPath.insert(desktopPath, documentItem); + + //qDebug() << "Document item" << documentItem << "text" << documentItem->text() << "url" << documentUrl.url(); + if (append) { + q->appendRow(documentItem); + } else { + q->insertRow(0, documentItem); + } + } + + void loadRecentDocuments() + { + // create branch for documents and add existing items + const QStringList documents = KRecentDocument::recentDocuments(); + foreach(const QString& document, documents) { + addRecentDocument(document, true); + } + } + + void loadRecentApplications() + { + const QList services = RecentApplications::self()->recentApplications(); + for(int i = 0; i < maxRecentApps && i < services.count(); ++i) { + addRecentApplication(services[i], true); + } + } + + RecentlyUsedModel * const q; + RecentType recenttype; + int maxRecentApps; + + QHash itemsByPath; + DisplayOrder displayOrder; + QString applicationTitle; + QString documentTitle; + int recentApplicationCount; +}; + +RecentlyUsedModel::RecentlyUsedModel(QObject *parent, RecentType recenttype, int maxRecentApps) + : KickoffModel(parent), + d(new Private(this, recenttype, maxRecentApps)) +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + (void)new RecentAdaptor(this); + QDBusConnection::sessionBus().registerObject("/kickoff/RecentAppDoc", this); + dbus.connect(QString(), "/kickoff/RecentAppDoc", "org.kde.plasma", "clearRecentDocumentsAndApplications", this, SLOT(clearRecentDocumentsAndApplications())); + + if (recenttype != DocumentsOnly) { + d->loadRecentApplications(); + + // listen for changes to the list of recent applications + connect(RecentApplications::self(), SIGNAL(applicationAdded(KService::Ptr,int)), + this, SLOT(recentApplicationAdded(KService::Ptr,int))); + connect(RecentApplications::self(), SIGNAL(applicationRemoved(KService::Ptr)), + this, SLOT(recentApplicationRemoved(KService::Ptr))); + connect(RecentApplications::self(), SIGNAL(cleared()), + this, SLOT(recentApplicationsCleared())); + } + + if (recenttype != ApplicationsOnly) { + d->loadRecentDocuments(); + + // listen for changes to the list of recent documents + KDirWatch *recentDocWatch = new KDirWatch(this); + recentDocWatch->addDir(KRecentDocument::recentDocumentDirectory(), KDirWatch::WatchFiles); + connect(recentDocWatch, SIGNAL(created(QString)), this, SLOT(recentDocumentAdded(QString))); + connect(recentDocWatch, SIGNAL(deleted(QString)), this, SLOT(recentDocumentRemoved(QString))); + } +} + +RecentlyUsedModel::~RecentlyUsedModel() +{ + delete d; +} + +QVariant RecentlyUsedModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || section != 0) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + if (d->recenttype == DocumentsAndApplications) { + return i18n("Recently Used"); + } else if (d->recenttype == DocumentsOnly) { + return i18n("Recently Used Documents"); + } else if (d->recenttype == ApplicationsOnly) { + return i18n("Recently Used Applications"); + } + default: + return QVariant(); + } +} + +void RecentlyUsedModel::setNameDisplayOrder(DisplayOrder displayOrder) +{ + if (d->displayOrder == displayOrder) { + return; + } + + d->displayOrder = displayOrder; + + d->itemsByPath.clear(); + clear(); + + if (d->recenttype != DocumentsOnly) { + d->loadRecentApplications(); + } + + if (d->recenttype != ApplicationsOnly) { + d->loadRecentDocuments(); + } +} + +DisplayOrder RecentlyUsedModel::nameDisplayOrder() const +{ + return d->displayOrder; +} + +void RecentlyUsedModel::recentDocumentAdded(const QString& path) +{ + qDebug() << "Recent document added" << path; + d->addRecentDocument(path, false); +} +void RecentlyUsedModel::recentDocumentRemoved(const QString& path) +{ + qDebug() << "Recent document removed" << path; + d->removeExistingItem(path); +} + +void RecentlyUsedModel::recentApplicationAdded(KService::Ptr service, int) +{ + if (service) { + d->addRecentApplication(service, false); + } +} + +void RecentlyUsedModel::recentApplicationRemoved(KService::Ptr service) +{ + if (service) { + d->removeExistingItem(service->entryPath()); + } +} + +void RecentlyUsedModel::recentApplicationsCleared() +{ + while (d->recentApplicationCount != 0) { + delete takeItem(0); + takeRow(0); + --d->recentApplicationCount; + } +} + +void RecentlyUsedModel::clearRecentApplications() +{ + RecentApplications::self()->clear(); +} +void RecentlyUsedModel::clearRecentDocuments() +{ + KRecentDocument::clear(); +} + +void RecentlyUsedModel::clearRecentDocumentsAndApplications() +{ + clearRecentDocuments(); + clearRecentApplications(); +} + + +#include "recentlyusedmodel.moc" + diff --git a/applets/kickoff/core/recentlyusedmodel.h b/applets/kickoff/core/recentlyusedmodel.h new file mode 100644 index 0000000000..44bcc9f091 --- /dev/null +++ b/applets/kickoff/core/recentlyusedmodel.h @@ -0,0 +1,78 @@ +/* + Copyright 2007 Robert Knight + + 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 RECENTLYUSEDMODEL_H +#define RECENTLYUSEDMODEL_H + +#include "kickoffmodel.h" +#include "models.h" + +// Qt + +// KDE +#include + +namespace Kickoff +{ + +/** + * Model for the Recently Used view which provides a tree of recently used + * applications and documents. + */ +class RecentlyUsedModel : public KickoffModel +{ + Q_OBJECT + +public: + + /** Defines what the model should display. */ + enum RecentType { + DocumentsAndApplications, ///< display recently used documents and applications. + DocumentsOnly, ///< documents only. recently used applications will not be displayed. + ApplicationsOnly ///< applications only, recently used documents will not be displayed. + }; + + /** Construct a new RecentlyUsedModel with the specified parent. */ + explicit RecentlyUsedModel(QObject *parent = 0, RecentType recenttype = DocumentsAndApplications, int maxRecentApps = -1); + virtual ~RecentlyUsedModel(); + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + void setNameDisplayOrder(DisplayOrder displayOrder); + DisplayOrder nameDisplayOrder() const; + +public Q_SLOTS: + void clearRecentApplications(); + void clearRecentDocuments(); + void clearRecentDocumentsAndApplications(); + +private Q_SLOTS: + void recentDocumentAdded(const QString& path); + void recentDocumentRemoved(const QString& path); + void recentApplicationAdded(KService::Ptr, int startCount); + void recentApplicationRemoved(KService::Ptr); + void recentApplicationsCleared(); + +private: + class Private; + Private * const d; +}; + +} + +#endif // RECENTLYUSEDMODEL_H diff --git a/applets/kickoff/core/systemmodel.cpp b/applets/kickoff/core/systemmodel.cpp new file mode 100644 index 0000000000..32caa0abae --- /dev/null +++ b/applets/kickoff/core/systemmodel.cpp @@ -0,0 +1,489 @@ +/* + Copyright 2007 Robert Knight + Copyright 2007 Kevin Ottens + Copyright 2011 Martin Gräßlin + + 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 "systemmodel.h" + +// Qt +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Local +#include "models.h" +#include "systemmodel.h" + +using namespace Kickoff; + +static const int OFFSET = 100; + +class SystemModel::Private +{ +public: + Private(SystemModel *parent) + : q(parent), + placesModel(new KFilePlacesModel(parent)), + refreshRequested(false) + { + q->setSourceModel(placesModel); + + connect(placesModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + q, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); + connect(placesModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + q, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int))); + connect(placesModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + q, SLOT(sourceRowsInserted(QModelIndex,int,int))); + connect(placesModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + q, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); + connect(placesModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), + q, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + + connect(KSycoca::self(), SIGNAL(databaseChanged(QStringList)), q, SLOT(reloadApplications())); + } + + SystemModel * const q; + KFilePlacesModel *placesModel; + KService::List appsList; + QMap usageByMountpoint; + QWeakPointer usageFinder; + bool refreshRequested; +}; + +SystemModel::SystemModel(QObject *parent) + : KickoffProxyModel(parent) + , d(new Private(this)) +{ + qRegisterMetaType("UsageInfo"); + QHash roles; + roles[Qt::DisplayRole] = "display"; + roles[Qt::DecorationRole] = "decoration"; + roles[Kickoff::SubTitleRole] = "subtitle"; + roles[Kickoff::UrlRole] = "url"; + roles[Kickoff::GroupNameRole] = "group"; + setRoleNames(roles); +} + +SystemModel::~SystemModel() +{ + delete d; +} + +QModelIndex SystemModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + if (!sourceIndex.isValid()) { + return QModelIndex(); + } + + if (d->placesModel->isHidden(sourceIndex)) { + // hidden items not in our model + return QModelIndex(); + } + if (d->placesModel->isDevice(sourceIndex)) { + if (d->placesModel->data(sourceIndex, KFilePlacesModel::FixedDeviceRole).toBool()) { + // fixed devices not in our list + return QModelIndex(); + } + } + int count = d->appsList.size() -1; + if (KAuthorized::authorize("run_command")) { + ++count; + } + for (int i=0; iplacesModel->rowCount(); ++i) { + if (i == sourceIndex.row()) { + break; + } + const QModelIndex index = d->placesModel->index(i, 0); + if (d->placesModel->isHidden(index)) { + continue; + } + if (d->placesModel->isDevice(index)) { + if (!d->placesModel->data(index, KFilePlacesModel::FixedDeviceRole).toBool()) { + ++count; + } + } else { + // visible place + ++count; + } + } + return index(count, 0); +} + +QModelIndex SystemModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if (!proxyIndex.isValid()) { + return QModelIndex(); + } + if (proxyIndex.internalId() == 0) { + // application index + return QModelIndex(); + } + return d->placesModel->index(proxyIndex.internalId() - OFFSET, 0); +} + +QModelIndex SystemModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent) + int count = d->appsList.size()-1; + if (KAuthorized::authorize("run_command")) { + ++count; + } + if (row <= count) { + return createIndex(row, column); + } + // find the source + for (int i=0; iplacesModel->rowCount(); ++i) { + const QModelIndex index = d->placesModel->index(i, 0); + if (d->placesModel->isHidden(index)) { + continue; + } + if (d->placesModel->isDevice(index)) { + if (!d->placesModel->data(index, KFilePlacesModel::FixedDeviceRole).toBool()) { + ++count; + } + } else { + // visible place + ++count; + } + if (row == count) { + return createIndex(row, column, i + OFFSET); + } + } + return QModelIndex(); +} + +QModelIndex SystemModel::parent(const QModelIndex &item) const +{ + Q_UNUSED(item) + return QModelIndex(); +} + +int SystemModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + int count = d->appsList.size(); + if (KAuthorized::authorize("run_command")) { + ++count; + } + for (int i=0; iplacesModel->rowCount(); ++i) { + const QModelIndex index = d->placesModel->index(i, 0); + if (d->placesModel->isHidden(index)) { + continue; + } + if (d->placesModel->isDevice(index)) { + if (!d->placesModel->data(index, KFilePlacesModel::FixedDeviceRole).toBool()) { + ++count; + } + } else { + // visible place + ++count; + } + } + + return count; +} + +int SystemModel::columnCount(const QModelIndex &/*parent*/) const +{ + return 1; +} + +QVariant SystemModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (index.internalId() == 0) { + if (role == GroupNameRole) { + return i18n("Applications"); + } + if (d->appsList.count() < index.row()) { + return QVariant(); + } else if (d->appsList.count() == index.row()) { + // "Run Command" + switch (role) { + case Qt::DisplayRole: + return i18n("Run Command..."); + case Qt::DecorationRole: + return KIcon("system-run"); + case SubTitleRole: + return i18n("Run a command or a search query"); + case UrlRole: + return "run:/"; + default: + return QVariant(); + } + } + + KService::Ptr service = d->appsList[index.row()]; + + switch (role) { + case Qt::DisplayRole: + return service->name(); + case Qt::DecorationRole: + return KIcon(service->icon()); + case SubTitleRole: + return service->genericName(); + case UrlRole: + return service->entryPath(); + default: + return QVariant(); + } + } + + if (role == UrlRole) { + return d->placesModel->url(mapToSource(index)).url(); + } + if (role == SubTitleRole) { + QModelIndex sourceIndex = mapToSource(index); + + if (d->placesModel->isDevice(sourceIndex)) { + Solid::Device dev = d->placesModel->deviceForIndex(sourceIndex); + Solid::StorageAccess *access = dev.as(); + + if (access) { + return access->filePath(); + } + } else { + KUrl url = d->placesModel->url(sourceIndex); + return url.isLocalFile() ? url.toLocalFile() : url.prettyUrl(); + } + + return QVariant(); + } + if (role == GroupNameRole) { + if (d->placesModel->isDevice(mapToSource(index))) { + return i18n("Removable Storage"); + } else { + return i18n("Places"); + } + } + return d->placesModel->data(mapToSource(index), role); +} + +QVariant SystemModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation != Qt::Horizontal || section != 0) { + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + return i18n("Computer"); + break; + default: + return QVariant(); + } +} + +UsageFinder::UsageFinder(QObject *parent) + : QThread(parent) +{ + +} + +void UsageFinder::add(int index, const QString &mountPoint) +{ + //NOTE: this is not particularly perfect for a threaded object ;) + // but the assumption here is that add is called before run() + m_toCheck.append(qMakePair(index, mountPoint)); +} + +void UsageFinder::run() +{ + typedef QPair CheckPair; + foreach (CheckPair check, m_toCheck) { + KDiskFreeSpaceInfo freeSpace = KDiskFreeSpaceInfo::freeSpaceInfo(check.second); + if (freeSpace.isValid()) { + UsageInfo info; + info.used = freeSpace.used() / 1024; + info.available = freeSpace.available() / 1024; + emit usageInfo(check.first, check.second, info); + } + } +} + +bool SystemModel::hasChildren(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + // return always false, else the model states that items in appsList are having children + return false; +} + +void SystemModel::refreshUsageInfo() +{ + if (d->usageFinder) { + d->refreshRequested = true; + } else { + QTimer::singleShot(100, this, SLOT(startUsageInfoFetch())); + } +} + +void SystemModel::setUsageInfo(int index, const QString &mountPoint, const UsageInfo &usageInfo) +{ + QModelIndex sourceIndex = d->placesModel->index(index, 0); + if (sourceIndex.isValid()) { + d->usageByMountpoint[mountPoint] = usageInfo; + QModelIndex index = mapFromSource(sourceIndex); + emit dataChanged(index, index); + } +} + +void SystemModel::stopRefreshingUsageInfo() +{ + d->refreshRequested = false; +} + +void SystemModel::usageFinderFinished() +{ + if (d->refreshRequested) { + d->refreshRequested = false; + QTimer::singleShot(100, this, SLOT(startUsageInfoFetch())); + } +} + +void SystemModel::startUsageInfoFetch() +{ + if (d->usageFinder) { + return; + } + + UsageFinder *usageFinder = new UsageFinder(this); + d->usageFinder = usageFinder; + connect(usageFinder, SIGNAL(finished()), + this, SLOT(usageFinderFinished())); + connect(usageFinder, SIGNAL(finished()), + usageFinder, SLOT(deleteLater())); + connect(usageFinder, SIGNAL(usageInfo(int,QString,UsageInfo)), + this, SLOT(setUsageInfo(int,QString,UsageInfo))); + + bool hasDevices = false; + + for (int i = 0; i < d->placesModel->rowCount(); ++i) { + QModelIndex sourceIndex = d->placesModel->index(i, 0); + if (d->placesModel->isDevice(sourceIndex)) { + Solid::Device dev = d->placesModel->deviceForIndex(sourceIndex); + Solid::StorageAccess *access = dev.as(); + + if (access && !access->filePath().isEmpty()) { + usageFinder->add(i, access->filePath()); + hasDevices = true; + } + } + } + + if (hasDevices) { + usageFinder->start(); + } else { + delete usageFinder; + } +} + +void SystemModel::reloadApplications() +{ + const QStringList apps = Kickoff::systemApplicationList(); + d->appsList.clear(); + + foreach (const QString &app, apps) { + KService::Ptr service = KService::serviceByStorageId(app); + + if (service) { + d->appsList << service; + } + } +} + +void Kickoff::SystemModel::sourceDataChanged(const QModelIndex &start, const QModelIndex &end) +{ + if (start.parent().isValid()) return; + + QModelIndex ourStart = QModelIndex(); + QModelIndex ourEnd = QModelIndex(); + // find our start + for (int i=start.row(); i<=end.row(); ++i) { + const QModelIndex ourIndex = mapFromSource(d->placesModel->index(i, 0)); + if (ourIndex.isValid()) { + ourStart = ourIndex; + break; + } + } + if (!ourStart.isValid()) { + return; + } + // find our end + for (int i=end.row(); i>=start.row(); --i) { + const QModelIndex ourIndex = mapFromSource(d->placesModel->index(i, 0)); + if (ourIndex.isValid()) { + ourEnd = ourIndex; + break; + } + } + if (ourEnd.isValid()) { + emit dataChanged(ourStart, ourEnd); + } +} + +void Kickoff::SystemModel::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + // TODO: can we update without resetting the model? + beginResetModel(); +} + +void Kickoff::SystemModel::sourceRowsInserted(const QModelIndex &parent, int /*start*/, int /*end*/) +{ + Q_UNUSED(parent) + // TODO: can we update without resetting the model? + endResetModel(); +} + +void Kickoff::SystemModel::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + // TODO: can we update without resetting the model? + beginResetModel(); +} + +void Kickoff::SystemModel::sourceRowsRemoved(const QModelIndex &parent, int /*start*/, int /*end*/) +{ + Q_UNUSED(parent) + // TODO: can we update without resetting the model? + endResetModel(); +} + +#include "systemmodel.moc" diff --git a/applets/kickoff/core/systemmodel.h b/applets/kickoff/core/systemmodel.h new file mode 100644 index 0000000000..5da49ad371 --- /dev/null +++ b/applets/kickoff/core/systemmodel.h @@ -0,0 +1,103 @@ +/* + Copyright 2007 Robert Knight + Copyright 2007 Kevin Ottens + + 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 SYSTEMMODEL_H +#define SYSTEMMODEL_H + +#include "kickoffproxymodel.h" + +#include + +namespace Kickoff +{ + +struct UsageInfo { + UsageInfo() + : used(0), + available(0) + {} + + quint64 used; + quint64 available; +}; + +class UsageFinder : public QThread +{ + Q_OBJECT + +public: + UsageFinder(QObject *parent); + void add(int index, const QString &mountPoint); + +Q_SIGNALS: + void usageInfo(int index, const QString &mountPoint, const UsageInfo &usageInfo); + +protected: + void run(); + +private: + QList > m_toCheck; +}; + +/** + * Model which provides a tree of items for important system setup tools (eg. System Settings) , + * folders (eg. the user's home folder and the local network) and fixed and removable storage. + */ +class SystemModel : public KickoffProxyModel +{ + Q_OBJECT + +public: + /** Constructs a new SystemModel with the specified parent. */ + SystemModel(QObject *parent = 0); + virtual ~SystemModel(); + + virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex &item) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const; + void refreshUsageInfo(); + void stopRefreshingUsageInfo(); + +private Q_SLOTS: + void startUsageInfoFetch(); + void reloadApplications(); + void sourceDataChanged(const QModelIndex &start, const QModelIndex &end); + void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void sourceRowsInserted(const QModelIndex &parent, int start, int end); + void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void sourceRowsRemoved(const QModelIndex &parent, int start, int end); + void setUsageInfo(int index, const QString &mountPoint, const UsageInfo &usageInfo); + void usageFinderFinished(); + +private: + class Private; + Private * const d; +}; + +} + +#endif // SYSTEMMODEL_H + diff --git a/applets/kickoff/core/urlitemlauncher.cpp b/applets/kickoff/core/urlitemlauncher.cpp new file mode 100644 index 0000000000..2ed074709c --- /dev/null +++ b/applets/kickoff/core/urlitemlauncher.cpp @@ -0,0 +1,164 @@ +/* + Copyright 2007 Robert Knight + Copyright 2007 Kevin Ottens + + 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 "urlitemlauncher.h" + +// Qt +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include + +// Local +#include "models.h" + +// DBus +#include "krunner_interface.h" + +using namespace Kickoff; + +class HandlerInfo +{ +public: + HandlerInfo() : type(UrlItemLauncher::ProtocolHandler) , handler(0) {} + UrlItemLauncher::HandlerType type; + UrlItemHandler *handler; +}; + +class GenericItemHandler : public UrlItemHandler +{ +public: + virtual bool openUrl(const KUrl& url) { + if (url.protocol() == "run" && KAuthorized::authorize("run_command")) { + QString interface("org.kde.krunner"); + org::kde::krunner::App krunner(interface, "/App", QDBusConnection::sessionBus()); + krunner.display(); + return true; + } + + new KRun(url, 0); + return true; + } +}; + +class UrlItemLauncher::Private +{ +public: + static QHash globalHandlers; + static GenericItemHandler genericHandler; + + static bool openUrl(const QString &urlString) { + qDebug() << "Opening item with URL" << urlString; + + KUrl url(urlString); + HandlerInfo protocolHandler = globalHandlers[url.scheme()]; + if (protocolHandler.type == ProtocolHandler && protocolHandler.handler != 0) { + return protocolHandler.handler->openUrl(url); + } + + QString extension = QFileInfo(url.path()).suffix(); + HandlerInfo extensionHandler = globalHandlers[extension]; + if (extensionHandler.type == ExtensionHandler && extensionHandler.handler != 0) { + return extensionHandler.handler->openUrl(url); + } + + return genericHandler.openUrl(url); + } +}; + +QHash UrlItemLauncher::Private::globalHandlers; +GenericItemHandler UrlItemLauncher::Private::genericHandler; + +UrlItemLauncher::UrlItemLauncher(QObject *parent) + : QObject(parent) + , d(new Private) +{ +} + +UrlItemLauncher::~UrlItemLauncher() +{ + delete d; +} + +bool UrlItemLauncher::openItem(const QModelIndex& index) +{ + QString urlString = index.data(UrlRole).value(); + if (urlString.isEmpty()) { + QString udi = index.data(DeviceUdiRole).toString(); + if (!udi.isEmpty()) { + Solid::Device device(udi); + Solid::StorageAccess *access = device.as(); + + if (access && !access->isAccessible()) { + connect(access, SIGNAL(setupDone(Solid::ErrorType,QVariant,QString)), + this, SLOT(onSetupDone(Solid::ErrorType,QVariant,QString))); + access->setup(); + return true; + } + } + + qDebug() << "Item" << index.data(Qt::DisplayRole) << "has no URL to open."; + return false; + } + + return Private::openUrl(urlString); +} + +bool UrlItemLauncher::openUrl(const QString& url) +{ + return Private::openUrl(url); +} + +void UrlItemLauncher::onSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi) +{ + Q_UNUSED(errorData); + + if (error != Solid::NoError) { + return; + } + + Solid::Device device(udi); + Solid::StorageAccess *access = device.as(); + + Q_ASSERT(access); + + QString urlString = "file://" + access->filePath(); + Private::openUrl(urlString); +} + +// FIXME: the handlers are leaked, as they are added with each new Kickoff instance, +// but never deleted. +void UrlItemLauncher::addGlobalHandler(HandlerType type, const QString& name, UrlItemHandler *handler) +{ + HandlerInfo info; + info.type = type; + info.handler = handler; + Private::globalHandlers.insert(name, info); +} + + +#include "urlitemlauncher.moc" diff --git a/applets/kickoff/core/urlitemlauncher.h b/applets/kickoff/core/urlitemlauncher.h new file mode 100644 index 0000000000..05c414d08e --- /dev/null +++ b/applets/kickoff/core/urlitemlauncher.h @@ -0,0 +1,87 @@ +/* + Copyright 2007 Robert Knight + Copyright 2007 Kevin Ottens + + 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 URLITEMLAUNCHER_H +#define URLITEMLAUNCHER_H + +#include +#include + +class QModelIndex; +class KUrl; + +namespace Kickoff +{ + +/** + * UrlItemHandler is an abstract base class for handlers which can open particular + * types of URL. + * + * @see UrlItemLauncher + */ +class UrlItemHandler +{ +public: + virtual ~UrlItemHandler() {} + virtual bool openUrl(const KUrl& url) = 0; +}; + +/** + * UrlItemLauncher provides facilities to open a item from a Kickoff model based on its UrlRole + * data. + * + * By default, a UrlItemLauncher opens all URLs using the KRun class. Additional handlers can be created + * to handle URLs with particular protocols or extensions differently. Handlers can be + * registered using the static addGlobalHandler() method. + */ +class UrlItemLauncher : public QObject +{ + Q_OBJECT + +public: + UrlItemLauncher(QObject *parent = 0); + virtual ~UrlItemLauncher(); + + enum HandlerType { + ProtocolHandler, + ExtensionHandler + }; + static void addGlobalHandler(HandlerType type, + const QString& name, + UrlItemHandler *handler); + +public Q_SLOTS: + /** Open the specified @p index from a Kickoff model. */ + bool openItem(const QModelIndex& index); + /** Open the specified @p url */ + bool openUrl(const QString& url); + +private Q_SLOTS: + void onSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi); + +private: + class Private; + Private * const d; +}; + +} + +#endif // URLITEMLAUNCHER_H + diff --git a/applets/kickoff/package/contents/config/config.qml b/applets/kickoff/package/contents/config/config.qml new file mode 100644 index 0000000000..74ec528281 --- /dev/null +++ b/applets/kickoff/package/contents/config/config.qml @@ -0,0 +1,29 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.configuration 2.0 + +ConfigModel { + ConfigCategory { + name: "Appearance" + icon: "preferences-desktop-color" + source: "configGeneral.qml" + } +} diff --git a/applets/kickoff/package/contents/config/main.xml b/applets/kickoff/package/contents/config/main.xml new file mode 100644 index 0000000000..3a859e84a1 --- /dev/null +++ b/applets/kickoff/package/contents/config/main.xml @@ -0,0 +1,20 @@ + + + + + + + true + + + false + + + false + + + + diff --git a/applets/kickoff/package/contents/ui/ApplicationsView.qml b/applets/kickoff/package/contents/ui/ApplicationsView.qml new file mode 100644 index 0000000000..156aee6e03 --- /dev/null +++ b/applets/kickoff/package/contents/ui/ApplicationsView.qml @@ -0,0 +1,217 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Gregor Taetzner + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.private.kickoff 0.1 as Kickoff + +Item { + id: appViewContainer + + anchors.fill: parent + + objectName: "ApplicationsView" + + function decrementCurrentIndex() { + applicationsView.decrementCurrentIndex(); + } + + function incrementCurrentIndex() { + applicationsView.incrementCurrentIndex(); + } + + function activateCurrentIndex(start) { + if (!applicationsView.currentItem.modelChildren) + if (!start) + return; + + appViewScrollArea.state = "OutgoingLeft"; + } + + function deactivateCurrentIndex() { + if (crumbModel.count > 0) { // this is not the case when switching from the "Applications" to the "Favorites" tab using the "Left" key + breadcrumbsElement.children[crumbModel.count-1].clickCrumb(); + appViewScrollArea.state = "OutgoingRight"; + return true; + } + return false; + } + + ContextMenu { + id: contextMenu + } + + Item { + id: crumbContainer + + anchors { + top: parent.top + left: parent.left + right: parent.right + } + height: childrenRect.height + + Flickable { + anchors { + top: parent.top + left: parent.left + right: parent.right + } + height: breadcrumbsElement.height + + contentWidth: breadcrumbsElement.width + contentX: contentWidth - width + + PlasmaComponents.ButtonRow { + id: breadcrumbsElement + + exclusive: false + + Breadcrumb { + id: rootBreadcrumb + root: true + text: i18n("All Applications") + depth: 0 + } + Repeater { + model: ListModel { + id: crumbModel + // Array of the category indexes + property var indexes: [] + } + + Breadcrumb { + root: false + text: model.text + } + } + } + } // Flickable + } // crumbContainer + + PlasmaExtras.ScrollArea { + id: appViewScrollArea + + anchors { + top: crumbContainer.bottom + bottom: parent.bottom + rightMargin: -units.largeSpacing + leftMargin: -units.largeSpacing + } + + + width: parent.width + + function moveRight() { + state = ""; + applicationsView.currentItem.activate(); + } + + function moveLeft() { + state = ""; + // newModelIndex set by clicked breadcrumb + applicationsView.model.rootIndex = applicationsView.newModelIndex; + } + + ListView { + id: applicationsView + + property variant newModelIndex + + focus: true + keyNavigationWraps: true + boundsBehavior: Flickable.StopAtBounds + highlight: PlasmaComponents.Highlight {} + + model: VisualDataModel { + id: vmodel + + delegate: KickoffItem { + id: kickoffItem + + appView: true + + PlasmaCore.SvgItem { + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: y + } + height: units.iconSizes.small + width: height + + svg: arrowSvg + elementId: "go-next" + visible: hasModelChildren + } + } + + model: Kickoff.ApplicationModel {} + } // VisualDataModel + + function addBreadcrumb(categoryIndex, title) { + crumbModel.append({"text": title, "depth": crumbModel.count+1}) + crumbModel.indexes.push(categoryIndex); + } + + PlasmaCore.Svg { + id: arrowSvg + + imagePath: "toolbar-icons/go" + } + } // applicationsView + + states: [ + State { + name: "OutgoingLeft" + PropertyChanges { + target: appViewScrollArea + x: -parent.width + opacity: 0.0 + } + }, + State { + name: "OutgoingRight" + PropertyChanges { + target: appViewScrollArea + x: parent.width + opacity: 0.0 + } + } + ] + + transitions: [ + Transition { + to: "OutgoingLeft" + SequentialAnimation { + NumberAnimation { properties: "x,opacity"; easing.type: Easing.InQuad; duration: units.longDuration } + ScriptAction { script: appViewScrollArea.moveRight() } + } + }, + Transition { + to: "OutgoingRight" + SequentialAnimation { + NumberAnimation { properties: "x,opacity"; easing.type: Easing.InQuad; duration: units.longDuration } + ScriptAction { script: appViewScrollArea.moveLeft() } + } + } + ] + } // appViewScrollArea +} // appViewContainer diff --git a/applets/kickoff/package/contents/ui/BaseView.qml b/applets/kickoff/package/contents/ui/BaseView.qml new file mode 100644 index 0000000000..02c392ed00 --- /dev/null +++ b/applets/kickoff/package/contents/ui/BaseView.qml @@ -0,0 +1,65 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.draganddrop 2.0 + + +Item { + property alias model: kickoffListView.model + + function decrementCurrentIndex() { + kickoffListView.decrementCurrentIndex(); + } + + function incrementCurrentIndex() { + kickoffListView.incrementCurrentIndex(); + } + + function activateCurrentIndex() { + kickoffListView.currentItem.activate(); + } + + PlasmaExtras.ScrollArea { + anchors.fill: parent + + ListView { + id: kickoffListView + + anchors.fill: parent + + interactive: contentHeight > height + boundsBehavior: Flickable.StopAtBounds + currentIndex: -1 + keyNavigationWraps: true + highlight: PlasmaComponents.Highlight {} + + delegate: KickoffItem {} + + section { + property: "group" + criteria: ViewSection.FullString + delegate: SectionDelegate {} + } + } + } +} diff --git a/applets/kickoff/package/contents/ui/Breadcrumb.qml b/applets/kickoff/package/contents/ui/Breadcrumb.qml new file mode 100644 index 0000000000..96d99d2ad0 --- /dev/null +++ b/applets/kickoff/package/contents/ui/Breadcrumb.qml @@ -0,0 +1,74 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Item { + id: crumbRoot + + height: crumb.implicitHeight + width: crumb.implicitWidth + arrowSvg.width + + property string text + property bool root: false + property int depth: model.depth + + function clickCrumb() { + crumb.clicked(); + } + + PlasmaComponents.ToolButton { + id: crumb + + anchors.left: arrowSvg.right + + text: crumbRoot.text + enabled: crumbRoot.depth < crumbModel.count + + onClicked: { + // Remove all the breadcrumbs in front of the clicked one + while (crumbModel.count > 0 && crumbRoot.depth < crumbModel.get(crumbModel.count-1).depth) { + crumbModel.remove(crumbModel.count-1) + crumbModel.indexes.pop() + } + + if (crumbRoot.root) { + applicationsView.newModelIndex = 0; + } else { + applicationsView.newModelIndex = crumbModel.indexes[index]; + } + appViewScrollArea.state = "OutgoingRight"; + } + } + + PlasmaCore.SvgItem { + id: arrowSvg + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + height: crumbRoot.height / 2 + width: visible ? height : 0 + + svg: PlasmaCore.Svg { + imagePath: "toolbar-icons/go" + } + elementId: "go-next" + visible: !crumbRoot.root + } +} // crumbRoot \ No newline at end of file diff --git a/applets/kickoff/package/contents/ui/ContextMenu.qml b/applets/kickoff/package/contents/ui/ContextMenu.qml new file mode 100644 index 0000000000..8101dd9477 --- /dev/null +++ b/applets/kickoff/package/contents/ui/ContextMenu.qml @@ -0,0 +1,85 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 + +PlasmaComponents.ContextMenu { + id: contextMenu + + property string title + property variant model + property bool isFavorite: favoritesModel.isFavorite(contextMenu.model.url) + property bool isApp: contextMenu.model.url.indexOf(".desktop") !== -1 + + function openAt(title, model, x, y) { + contextMenu.title = title + contextMenu.model = model + + open(x, y) + } + + /* + * context menu items + */ + PlasmaComponents.MenuItem { + id: titleMenuItem + + text: contextMenu.title + icon: contextMenu.model.decoration + checkable: false + enabled: false + } + PlasmaComponents.MenuItem { + id: titleSeparator + + separator: true + } + PlasmaComponents.MenuItem { + id: addToFavorites + + text: contextMenu.isFavorite ? i18n("Remove From Favorites") : i18n("Add To Favorites") + icon: contextMenu.isFavorite ? "list-remove" : "bookmark-new" + visible: contextMenu.isApp + + onClicked: { + // FIXME: apparently contextMenu.model is empty + if (contextMenu.isFavorite) { + favoritesModel.remove(contextMenu.model.url); + } else { + favoritesModel.add(contextMenu.model.url); + } + } + } + PlasmaComponents.MenuItem { + id: uninstallApp + + text: i18n("Uninstall") + visible: packagekitSource.data["Status"] !== undefined && contextMenu.isApp + + onClicked: { + var service = packagekitSource.serviceForSource("Status") + var operation = service.operationDescription("uninstallApplication") + operation.Url = contextMenu.model.url; + var job = service.startOperationCall(operation) + } + } +} // contextMenu + diff --git a/applets/kickoff/package/contents/ui/FavoritesView.qml b/applets/kickoff/package/contents/ui/FavoritesView.qml new file mode 100644 index 0000000000..15dd4175e6 --- /dev/null +++ b/applets/kickoff/package/contents/ui/FavoritesView.qml @@ -0,0 +1,169 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.draganddrop 2.0 + +import org.kde.plasma.private.kickoff 0.1 as Kickoff + + +Item { + anchors.fill: parent + + objectName: "FavoritesView" + + function decrementCurrentIndex() { + kickoffListView.decrementCurrentIndex(); + } + + function incrementCurrentIndex() { + kickoffListView.incrementCurrentIndex(); + } + + function activateCurrentIndex() { + kickoffListView.currentItem.activate(); + } + + ContextMenu { + id: contextMenu + + PlasmaComponents.MenuItem { + id: actionsSeparator + + separator: true + } + PlasmaComponents.MenuItem { + id: sortFavoritesAscending + + text: i18n("Sort Alphabetically (A to Z)") + icon: "view-sort-ascending" + + onClicked: { + favoritesModel.sortFavoritesAscending(); + } + } + PlasmaComponents.MenuItem { + id: sortFavoritesDescending + + text: i18n("Sort Alphabetically (Z to A)") + icon: "view-sort-descending" + + onClicked: { + favoritesModel.sortFavoritesDescending(); + } + } + } + DropArea { + property string dragUrl: "" + property Item dragItem: null + property int startRow: -1 + property int itemHeight: units.gridUnit * 3 + + + anchors.fill: scrollArea + + function syncTarget(event) { + kickoffListView.currentIndex = kickoffListView.indexAt(event.x, event.y + kickoffListView.contentY + itemHeight) + 1 + if (kickoffListView.currentIndex === -1) { + if (event.y < itemHeight/2) { + kickoffListView.currentIndex = 0 + } + } + if (kickoffListView.currentItem != null && event.y + itemHeight < kickoffListView.currentItem.y) { + dropTarget.y = (kickoffListView.currentIndex) * itemHeight - kickoffListView.contentY + } else { + dropTarget.y = (kickoffListView.count ) * itemHeight + } + } + + onDrop: { + var row = dropTarget.y / itemHeight; + print("Dropping into row : " + startRow + " " + row + " " + (event.y + kickoffListView.contentY) + " " + dragUrl); + row = Math.max(0, row) + row = Math.round(row) + //kickoffListView.model.dropMimeData(event.mimeData.text, [dragUrl], row, 0); + kickoffListView.model.move(startRow, row); + dropTarget.visible = false; + } + onDragEnter: { +// print("Drag enter"); + dragUrl = kickoffListView.currentItem.url; + startRow = kickoffListView.currentIndex; + syncTarget(event); +// print("Dragging " + dragUrl + " from row " + startRow); + dropTarget.visible = true; + } + onDragMove: syncTarget(event); + + onDragLeave: { + dropTarget.visible = false; + } + + Rectangle { + id: dropTarget + + width: parent.width + height: Math.max(2, units.smallSpacing) + + visible: false + color: theme.highlightColor + } + } + + PlasmaExtras.ScrollArea { + id: scrollArea + + anchors.fill: parent + + ListView { + id: kickoffListView + + anchors.fill: parent + currentIndex: -1 + keyNavigationWraps: true + interactive: contentHeight > height + /* + delegate: KQuickControlsAddons.MouseEventListener { + hoverEnabled: true + onContainsMouseChanged: { + if (containsMouse) { + kickoffListView.currentIndex = index; + } + } + KickoffItem { id: koitem; anchors.fill: parent; } + } + */ + delegate: KickoffItem {} + highlight: PlasmaComponents.Highlight {} + + model: favoritesModel + + section { + property: "group" + criteria: ViewSection.FullString + //delegate: SectionDelegate {} + } + } + } + +} diff --git a/applets/kickoff/package/contents/ui/Footer.qml b/applets/kickoff/package/contents/ui/Footer.qml new file mode 100644 index 0000000000..dcc762fd3c --- /dev/null +++ b/applets/kickoff/package/contents/ui/Footer.qml @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Gregor Taetzner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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. + */ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.kquickcontrolsaddons 2.0 + +Item { + id: footer + + height: statusLabel.height + + PlasmaComponents.Label { + id: statusLabel + //text: kickoff.footerText // FIXME: where does this come from? Is it still needed? + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + } + } + + PlasmaCore.SvgItem { + id: brandingButton + svg { + PlasmaCore.Svg { + imagePath: "widgets/branding" + } + } + elementId: "brilliant" + height: Math.min(implicitHeight, parent.height) //don't be bigger than the text or the logo size + width: implicitWidth * (height / implicitHeight) + + anchors { + verticalCenter: parent.verticalCenter + left: statusLabel.right + leftMargin: 4 + } + } +} diff --git a/applets/kickoff/package/contents/ui/Header.qml b/applets/kickoff/package/contents/ui/Header.qml new file mode 100644 index 0000000000..595bd51734 --- /dev/null +++ b/applets/kickoff/package/contents/ui/Header.qml @@ -0,0 +1,225 @@ +/* + * Copyright 2014 Sebastian Kügler + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + +import org.kde.plasma.private.kickoff 0.1 as Kickoff + +Item { + id: header + + height: units.gridUnit * 5 + + property alias query: queryField.text + property Item input: queryField + + Kickoff.KUser { + id: kuser + } + + state: (header.query != "") ? "query" : "hint" + + Timer { + id: labelTimer + interval: 5000 + running: header.state === "hint" && plasmoid.expanded && (header.query === "") + onTriggered: { + if (header.state == "info") { + header.state = "hint"; + } else if (header.state == "hint") { + header.state = "info"; + } + } + } + + Rectangle { color: "orange"; visible: root.debug; anchors.fill: parent; opacity: 0.3 } + + Image { + id: faceIcon + source: kuser.faceIconPath + visible: source != "" + + width: units.gridUnit * 3 + height: width + + anchors { + top: parent.top + left: parent.left + topMargin: units.gridUnit + leftMargin: units.gridUnit + } + + Rectangle { color: "green"; opacity: 0.3; anchors.fill: parent; visible: root.debug; } + } + + PlasmaCore.IconItem { + source: "user-identity" + visible: faceIcon.source == "" + width: units.gridUnit * 3 + height: width + anchors { + top: faceIcon.top + right: faceIcon.right + rightMargin: -units.gridUnit/2 + } + } + + PlasmaExtras.Heading { + id: nameLabel + + level: 2 + text: kuser.fullName + elide: Text.ElideRight + verticalAlignment: Text.AlignTop + height: paintedHeight + + anchors { + left: faceIcon.right + top: faceIcon.top + right: parent.right + leftMargin: units.gridUnit + rightMargin: units.gridUnit + } + } + + Item { + id: searchWidget + + property int animationDuration: units.longDuration + property real normalOpacity: .6 + property int yOffset: height / 2 + + height: infoLabel.height + anchors { + left: nameLabel.left + top: nameLabel.bottom + right: nameLabel.right + } + + PlasmaComponents.Label { + id: infoLabel + anchors { + left: parent.left + right: parent.right + } + verticalAlignment: Text.AlignBottom + text: kuser.os != "" ? i18n("%2@%3 (%1)", kuser.os, kuser.loginName, kuser.host) : i18n("%1@%2", kuser.loginName, kuser.host) + elide: Text.ElideRight + + Behavior on opacity { NumberAnimation { duration: searchWidget.animationDuration; easing.type: Easing.InOutQuad; } } + Behavior on y { NumberAnimation { duration: searchWidget.animationDuration; easing.type: Easing.InOutQuad; } } + } + + PlasmaComponents.Label { + id: hintLabel + anchors { + left: parent.left + right: parent.right + } + verticalAlignment: Text.AlignBottom + text: i18n("Type to search...") + Behavior on opacity { NumberAnimation { duration: searchWidget.animationDuration; easing.type: Easing.InOutQuad; } } + Behavior on y { NumberAnimation { duration: searchWidget.animationDuration; easing.type: Easing.InOutQuad; } } + } + + PlasmaComponents.TextField { + id: queryField + anchors.fill: parent + clearButtonShown: true + Behavior on opacity { NumberAnimation { duration: searchWidget.animationDuration / 4 } } + + onTextChanged: { + if (root.state != "Search") { + root.previousState = root.state; + root.state = "Search"; + } + if (text == "") { + root.state = root.previousState; + root.forceActiveFocus(); + header.state = "info"; + } else { + header.state = "query"; + } + } + } + + Connections { + target: plasmoid + onExpandedChanged: { + if (!expanded) { + header.query = ""; + } + } + } + } + + states: [ + State { + name: "info" + PropertyChanges { + target: infoLabel + opacity: searchWidget.normalOpacity + y: 0 + } + PropertyChanges { + target: hintLabel + opacity: 0 + y: searchWidget.yOffset + } + PropertyChanges { + target: queryField + opacity: 0 + } + }, + State { + name: "hint" + PropertyChanges { + target: infoLabel + y: -searchWidget.yOffset + opacity: 0 + } + PropertyChanges { + target: hintLabel + y: 0 + opacity: searchWidget.normalOpacity + } + PropertyChanges { + target: queryField + opacity: 0 + } + }, + State { + name: "query" + PropertyChanges { + target: infoLabel + opacity: 0 + } + PropertyChanges { + target: hintLabel + opacity: 0 + } + PropertyChanges { + target: queryField + opacity: 1 + } + } + ] // states +} diff --git a/applets/kickoff/package/contents/ui/Kickoff.qml b/applets/kickoff/package/contents/ui/Kickoff.qml new file mode 100644 index 0000000000..28db6b0b28 --- /dev/null +++ b/applets/kickoff/package/contents/ui/Kickoff.qml @@ -0,0 +1,404 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Gregor Taetzner + Copyright (C) 2012 Marco Martin + Copyright (C) 2013 David Edmundson + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.plasmoid 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.kquickcontrolsaddons 2.0 + +Item { + + Plasmoid.switchWidth: units.gridUnit * 200 + Plasmoid.switchHeight: units.gridUnit * 300 + + + Plasmoid.fullRepresentation: Item { + id: root + Layout.minimumWidth: units.gridUnit * 26 + Layout.minimumHeight: units.gridUnit * 33 + + property string previousState + property bool switchTabsOnHover: plasmoid.configuration.switchTabsOnHover + property bool showAppsByName: plasmoid.configuration.showAppsByName + property Item currentView: mainStack.currentTab.decrementCurrentIndex ? mainStack.currentTab : mainStack.currentTab.item + + property int pad: units.gridUnit + property bool debug: false + +// implicitWidth: root.minimumWidth +// implicitHeight: root.minimumHeight + + state: "Normal" + focus: true + + PlasmaCore.DataSource { + id: packagekitSource + engine: "packagekit" + connectedSources: ["Status"] + } + + Kickoff.Launcher { + id: launcher + } + + PlasmaCore.Svg { + id: lineSvg + imagePath: "widgets/line" + } + + Timer { + id: clickTimer + + property Item pendingButton + + interval: 250 + + onTriggered: pendingButton.clicked() + } + + Header { + id: header + + anchors { + top: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return undefined; + default: + return parent.top; + } + } + bottom: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return parent.bottom; + default: + return undefined; + } + } + left: parent.left + right: parent.right + } + } + + PlasmaComponents.TabGroup { + id: mainStack + + anchors { + top: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + return tabBar.bottom; + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return parent.top; + default: + return header.bottom; + } + } + bottom: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return header.top; + default: + return tabBar.top; + } + } + left: plasmoid.location == PlasmaCore.Types.LeftEdge ? tabBar.right : parent.left + right: plasmoid.location == PlasmaCore.Types.RightEdge ? tabBar.left : parent.right + leftMargin: units.largeSpacing + rightMargin: units.largeSpacing + } + + //pages + FavoritesView { + id: favoritesPage + } + PlasmaExtras.ConditionalLoader { + id: applicationsPage + when: mainStack.currentTab == applicationsPage + source: Qt.resolvedUrl("ApplicationsView.qml") + } + PlasmaExtras.ConditionalLoader { + id: systemPage + when: mainStack.currentTab == systemPage + source: Qt.resolvedUrl("SystemView.qml") + } + PlasmaExtras.ConditionalLoader { + id: recentlyUsedPage + when: mainStack.currentTab == recentlyUsedPage + source: Qt.resolvedUrl("RecentlyUsedView.qml") + } + PlasmaExtras.ConditionalLoader { + id: leavePage + when: mainStack.currentTab == leavePage + source: Qt.resolvedUrl("LeaveView.qml") + } + PlasmaExtras.ConditionalLoader { + id: searchPage + when: root.state == "Search" + //when: mainStack.currentTab == searchPage || root.state == "Search" + source: Qt.resolvedUrl("SearchView.qml") + } + } // mainStack + + Kickoff.FavoritesModel { + id: favoritesModel + } + + PlasmaComponents.TabBar { + id: tabBar + + width: { + if (!visible) { + return 0; + } + + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return units.gridUnit * 5; + default: + return 0; + } + } + + height: { + if (!visible) { + return 0; + } + + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return 0; + default: + return units.gridUnit * 5; + } + } + + Behavior on width { NumberAnimation { duration: units.longDuration; easing.type: Easing.InQuad; } } + Behavior on height { NumberAnimation { duration: units.longDuration; easing.type: Easing.InQuad; } } + + anchors { + top: { + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return parent.top; + default: + return undefined; + } + } + bottom: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + return undefined; + case PlasmaCore.Types.LeftEdge: + case PlasmaCore.Types.RightEdge: + return header.top; + default: + return parent.bottom; + } + } + left: { + switch (plasmoid.location) { + case PlasmaCore.Types.RightEdge: + return undefined; + default: + return parent.left; + } + } + right: { + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + return undefined; + default: + return parent.right; + } + } + } + + tabPosition: { + switch (plasmoid.location) { + case PlasmaCore.Types.TopEdge: + return Qt.TopEdge; + case PlasmaCore.Types.LeftEdge: + return Qt.LeftEdge; + case PlasmaCore.Types.RightEdge: + return Qt.RightEdge; + default: + return Qt.BottomEdge; + } + } + + currentTab: bookmarkButton + onCurrentTabChanged: root.forceActiveFocus(); + + KickoffButton { + id: bookmarkButton + tab: favoritesPage + iconSource: "bookmarks" + text: i18n("Favorites") + } + KickoffButton { + id: applicationButton + tab: applicationsPage + iconSource: "applications-other" + text: i18n("Applications") + } + KickoffButton { + id: computerButton + tab: systemPage + iconSource: "computer" // TODO: could also be computer-laptop + text: i18n("Computer") + } + KickoffButton { + id: usedButton + tab: recentlyUsedPage + iconSource: "document-open-recent" + text: i18n("Recently Used") + } + KickoffButton { + id: leaveButton + tab: leavePage + iconSource: "system-shutdown" + text: i18n("Leave") + } + } // tabBar + + Keys.forwardTo: [tabBar.layout] + + Keys.onPressed: { + + if (mainStack.currentTab == applicationsPage) { + if (event.key != Qt.Key_Tab) { + root.state = "Applications"; + } + } + + switch(event.key) { + case Qt.Key_Up: { + currentView.decrementCurrentIndex(); + event.accepted = true; + break; + } + case Qt.Key_Down: { + currentView.incrementCurrentIndex(); + event.accepted = true; + break; + } + case Qt.Key_Left: { + if (header.input.focus) { + break; + } + if (!currentView.deactivateCurrentIndex()) { + // FIXME move to the previous tab immediately + root.state = "Normal" + } + event.accepted = true; + break; + } + case Qt.Key_Right: { + if (header.input.focus) { + break; + } + currentView.activateCurrentIndex(); + event.accepted = true; + break; + } + case Qt.Key_Tab: { + root.state == "Applications" ? root.state = "Normal" : root.state = "Applications"; + event.accepted = true; + break; + } + case Qt.Key_Enter: + case Qt.Key_Return: { + currentView.activateCurrentIndex(1); + event.accepted = true; + break; + } + case Qt.Key_Escape: { + if (header.query == "") { + plasmoid.expanded = false; + } else { + header.query = ""; + } + event.accepted = true; + break; + } + default: { // forward key to searchView + if (event.text != "" && !header.input.focus) { + if (event.text == "v" && event.modifiers & Qt.ControlModifier) { + header.input.paste(); + } else { + header.query = ""; + header.query += event.text; + } + header.input.forceActiveFocus(); + event.accepted = true; + } + } + } + } + + states: [ + State { + name: "Normal" + PropertyChanges { + target: root + Keys.forwardTo: [tabBar.layout] + } + }, + State { + name: "Applications" + PropertyChanges { + target: root + Keys.forwardTo: [root] + } + }, + State { + name: "Search" + PropertyChanges { + target: tabBar + visible: false + } + PropertyChanges { + target: mainStack + currentTab: searchPage + } + } + ] // states + + onStateChanged: { + print("root.state changed to : " + state); + } + } +} // root diff --git a/applets/kickoff/package/contents/ui/KickoffButton.qml b/applets/kickoff/package/contents/ui/KickoffButton.qml new file mode 100644 index 0000000000..57d1ba09b1 --- /dev/null +++ b/applets/kickoff/package/contents/ui/KickoffButton.qml @@ -0,0 +1,73 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.kquickcontrolsaddons 2.0 + +PlasmaComponents.TabButton { + id: button + + property string iconSource + property alias text: labelElement.text + + implicitHeight: iconElement.height + labelElement.implicitHeight + iconElement.anchors.topMargin + labelElement.anchors.topMargin + labelElement.anchors.bottomMargin + + MouseArea { + enabled: root.switchTabsOnHover + anchors.fill: parent + hoverEnabled: root.switchTabsOnHover + onEntered: { + clickTimer.pendingButton = button + clickTimer.restart() + } + onExited: clickTimer.running = false + onClicked: button.clicked() + } + + QIconItem { + id: iconElement + + anchors { + topMargin: 5 + top: parent.top + horizontalCenter: parent.horizontalCenter + } + width: units.iconSizes.medium + height: width + + icon: iconSource + } + PlasmaComponents.Label { + id: labelElement + + anchors { + bottom: parent.bottom + top: iconElement.bottom + left: parent.left + right: parent.right + topMargin: 5 + bottomMargin: 5 + } + + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + font.pointSize: theme.smallestFont.pointSize + } +} // button diff --git a/applets/kickoff/package/contents/ui/KickoffItem.qml b/applets/kickoff/package/contents/ui/KickoffItem.qml new file mode 100644 index 0000000000..0a3b01e261 --- /dev/null +++ b/applets/kickoff/package/contents/ui/KickoffItem.qml @@ -0,0 +1,171 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Gregor Taetzner + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.draganddrop 2.0 + +Item { + id: listItem + + width: ListView.view.width + height: listItemDelegate.height // + listItemDelegate.anchors.margins*2 + + property bool dropEnabled: false + property bool modelChildren: hasModelChildren + property bool appView: false + property bool isCurrent: listItem.ListView.view.currentIndex === index; + property string url: model["url"] + + function activate() { + if (hasModelChildren) { + listItem.ListView.view.addBreadcrumb(listItem.ListView.view.model.modelIndex(index), display); + listItem.ListView.view.model.rootIndex = listItem.ListView.view.model.modelIndex(index); + } else { + launcher.openUrl(model["url"]); + plasmoid.expanded = false; + } + } + + Item { + id: listItemDelegate + + anchors { + left: parent.left + right: parent.right + top: parent.top + bottom: parent.bottom + //margins: units.gridUnit / 2 + } + //height: Math.max(elementIcon.height + units.gridUnit/2, titleElement.height + subTitleElement.height + units.gridUnit/2) + height: units.gridUnit * 3 + + DragArea { + anchors.fill: parent + supportedActions: Qt.MoveAction | Qt.LinkAction + delegateImage: decoration + + mimeData { + url: "file://" + model["url"] + source: parent + text: index + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + //anchors.margins: -8 + + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onEntered: { + listItem.ListView.view.currentIndex = index; + } + + onClicked: { + if (mouse.button == Qt.LeftButton) { + if (appView) { + appViewScrollArea.state = "OutgoingLeft"; + } + else { + listItem.activate(); + } + } else if (mouse.button == Qt.RightButton) { + // don't show a context menu for container + if (hasModelChildren || typeof(contextMenu) === "undefined") { + return; + } + + contextMenu.visualParent = mouseArea + contextMenu.openAt(titleElement.text, model, mouse.x, mouse.y); + } + } + } + } + + QIconItem { + id: elementIcon + + anchors { + left: parent.left + leftMargin: (units.gridUnit * 3) - units.iconSizes.medium + verticalCenter: parent.verticalCenter + } + width: units.iconSizes.medium + height: width + + icon: decoration + } + PlasmaComponents.Label { + id: titleElement + + anchors { + top: elementIcon.top + left: elementIcon.right + right: parent.right + leftMargin: units.gridUnit + } + height: paintedHeight + // TODO: games should always show the by name! + text: { + if (hasModelChildren) { + return display; + } else { + plasmoid.configuration.showAppsByName || display.length == 0 ? (subtitle == undefined ? display : subtitle) : + display + } + } + } + PlasmaComponents.Label { + id: subTitleElement + + anchors { + left: titleElement.left + right: parent.right + bottom: parent.bottom + top: titleElement.bottom + } + height: paintedHeight + + text: { + if (hasModelChildren) { + return subtitle; + } else { + plasmoid.configuration.showAppsByName || subtitle == undefined ? (display.length != 0 ? display : subtitle) : subtitle; + } + } + opacity: isCurrent ? 0.6 : 0 + Behavior on opacity { NumberAnimation { duration: units.longDuration /2 } } + font.pointSize: theme.smallestFont.pointSize + elide: Text.ElideMiddle + } +/* + PlasmaComponents.Highlight { + id: itemHighlight + anchors { + fill: parent + margins: -(units.gridUnit/2) + } + opacity: mouseArea.containsMouse ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: theme.shortDuration } } + }*/ + } // listItemDelegate +} // listItem diff --git a/applets/kickoff/package/contents/ui/LeaveView.qml b/applets/kickoff/package/contents/ui/LeaveView.qml new file mode 100644 index 0000000000..97fe7f30d2 --- /dev/null +++ b/applets/kickoff/package/contents/ui/LeaveView.qml @@ -0,0 +1,27 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.private.kickoff 0.1 as Kickoff + + +BaseView { + objectName: "LeaveView" + + model: Kickoff.LeaveModel {} +} diff --git a/applets/kickoff/package/contents/ui/RecentlyUsedView.qml b/applets/kickoff/package/contents/ui/RecentlyUsedView.qml new file mode 100644 index 0000000000..ed30c93db0 --- /dev/null +++ b/applets/kickoff/package/contents/ui/RecentlyUsedView.qml @@ -0,0 +1,51 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.private.kickoff 0.1 as Kickoff +import org.kde.plasma.components 2.0 as PlasmaComponents + + +BaseView { + objectName: "RecentlyUsedView" + + model: Kickoff.RecentlyUsedModel { + id: recentlyUsedModel + } + + ContextMenu { + id: contextMenu + + PlasmaComponents.MenuItem { + id: clearRecentApplications + + text: i18n("Clear Recent Applications") + icon: QIcon("edit-clear-history") + onClicked: recentlyUsedModel.clearRecentApplications(); + visible: contextMenu.isApp + } + PlasmaComponents.MenuItem { + id: clearRecentDocuments + + text: i18n("Clear Recent Documents") + icon: QIcon("edit-clear-history") + onClicked: recentlyUsedModel.clearRecentDocuments(); + visible: !contextMenu.isApp + } + } +} diff --git a/applets/kickoff/package/contents/ui/SearchView.qml b/applets/kickoff/package/contents/ui/SearchView.qml new file mode 100644 index 0000000000..7401fa2eb6 --- /dev/null +++ b/applets/kickoff/package/contents/ui/SearchView.qml @@ -0,0 +1,69 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Gregor Taetzner + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.private.kickoff 0.1 as Kickoff +Item { + id: searchViewContainer + + anchors.fill: parent + + objectName: "SearchView" + + function decrementCurrentIndex() { + searchView.decrementCurrentIndex(); + } + + function incrementCurrentIndex() { + searchView.incrementCurrentIndex(); + } + + function activateCurrentIndex() { + searchView.currentItem.activate(); + } + + PlasmaExtras.ScrollArea { + anchors.fill: parent + + ListView { + id: searchView + + anchors.fill: parent + keyNavigationWraps: true + boundsBehavior: Flickable.StopAtBounds + delegate: KickoffItem {} + highlight: PlasmaComponents.Highlight {} + model: Kickoff.KRunnerModel{} + + Connections { + target: header + + onQueryChanged: { + searchView.model.setQuery(header.query) + } + } + } // searchView + } // ScrollArea + + ContextMenu { + id: contextMenu + } +} diff --git a/applets/kickoff/package/contents/ui/SectionDelegate.qml b/applets/kickoff/package/contents/ui/SectionDelegate.qml new file mode 100644 index 0000000000..f32fceebc4 --- /dev/null +++ b/applets/kickoff/package/contents/ui/SectionDelegate.qml @@ -0,0 +1,64 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + + +Item { + id: sectionDelegate + + width: parent.width + height: childrenRect.height + +// PlasmaCore.SvgItem { +// anchors { +// left: parent.left +// right: parent.right +// } +// height: lineSvg.elementSize("horizontal-line").height +// +// visible: sectionDelegate.y > 0 +// svg: lineSvg +// elementId: "horizontal-line" +// } + PlasmaExtras.Heading { + id: sectionHeading + anchors { +// bottomMargin: units.gridUnit / 4 + left: parent.left + right: parent.right + //leftMargin: units.gridUnit + } + + y: units.gridUnit / 4 + //height: paintedHeight + units.gridUnit / 4 + //opacity: 0.6 + level: 4 + text: section + //horizontalAlignment: Text.AlignHCenter + } + Item { + width: parent.width + height: units.gridUnit / 4 + anchors.left: parent.left + anchors.top: sectionHeading.bottom + } +} // sectionDelegate diff --git a/applets/kickoff/package/contents/ui/SystemView.qml b/applets/kickoff/package/contents/ui/SystemView.qml new file mode 100644 index 0000000000..e0093f0669 --- /dev/null +++ b/applets/kickoff/package/contents/ui/SystemView.qml @@ -0,0 +1,26 @@ +/* + Copyright (C) 2011 Martin Gräßlin + Copyright (C) 2012 Marco Martin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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. +*/ +import QtQuick 2.0 +import org.kde.plasma.private.kickoff 0.1 as Kickoff + +BaseView { + objectName: "SystemView" + + model: Kickoff.SystemModel {} +} diff --git a/applets/kickoff/package/contents/ui/configGeneral.qml b/applets/kickoff/package/contents/ui/configGeneral.qml new file mode 100644 index 0000000000..9462005242 --- /dev/null +++ b/applets/kickoff/package/contents/ui/configGeneral.qml @@ -0,0 +1,56 @@ +/* + * Copyright 2013 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls + +//FIXME this causes a crash in Oxygen style +//QtControls.GroupBox { +Item { + +//FIXME i18n is broken currently +//when fixed delete this +function i18n(arg) { + return arg; +} + width: childrenRect.width + height: childrenRect.height + +//FIXME enable when we're back to being a group box +// flat: true +// title: i18n("Appearance") + + property alias cfg_switchTabsOnHover: switchTabsOnHoverCheckbox.checked + property alias cfg_showAppsByName: showApplicationsByNameCheckbox.checked + property alias cfg_showRecentlyInstalled: showRecentlyInstalledCheckbox.checked + + Column { + QtControls.CheckBox { + id: switchTabsOnHoverCheckbox + text: i18n("Switch tabs on hover:") + } + QtControls.CheckBox { + id: showApplicationsByNameCheckbox + text: i18n("Show applications by name:") + } + QtControls.CheckBox { + id: showRecentlyInstalledCheckbox + text: i18n("Show 'Recently Installed':") + } + } +} diff --git a/applets/kickoff/package/metadata.desktop b/applets/kickoff/package/metadata.desktop new file mode 100644 index 0000000000..c867b93fd2 --- /dev/null +++ b/applets/kickoff/package/metadata.desktop @@ -0,0 +1,184 @@ +[Desktop Entry] +Name=Application Launcher +Name[af]=Programlanseerder +Name[ar]=مطلق التطبيقات +Name[ast]=Llanzador d'aplicaciones +Name[be]=Запуск праграмаў +Name[be@latin]=Uklučeńnie aplikacyi +Name[bg]=Стартиране на програми +Name[bn]=অ্যাপলিকেশন লঞ্চার +Name[bn_IN]=অ্যাপ্লিকেশন সঞ্চালনকারী +Name[bs]=pokretač programa +Name[ca]=Llançador d'aplicacions +Name[ca@valencia]=Llançador d'aplicacions +Name[cs]=Spouštěč aplikací +Name[csb]=Zrëszôcz programów +Name[da]=Startmenu +Name[de]=K-Menü +Name[el]=Εκτέλεση εφαρμογών +Name[en_GB]=Application Launcher +Name[eo]=Aplikaĵolanĉilo +Name[es]=Lanzador de aplicaciones +Name[et]=Rakenduste käivitaja +Name[eu]=Aplikazio-abiarazlea +Name[fa]=راه‌انداز برنامه +Name[fi]=Sovelluskäynnistin +Name[fr]=Lanceur d'application +Name[fy]=In applikaashe starter +Name[ga]=Tosaitheoir Feidhmchlár +Name[gl]=Iniciador de programas +Name[gu]=કાર્યક્રમ ચલાવનાર +Name[he]=משגר יישומים +Name[hi]=अनुप्रयोग चालक +Name[hne]=अनुपरयोग चालू करइया +Name[hr]=Pokretač aplikacija +Name[hsb]=Startowar za aplikacije +Name[hu]=Programindító +Name[ia]=Lanceator de application +Name[id]=Peluncur Aplikasi +Name[is]=Forrita-Ræsir +Name[it]=Avviatore di applicazioni +Name[ja]=Kickoff アプリケーションランチャー +Name[kk]=Қолданбаны жегу +Name[km]=កម្មវិធី​ចាប់ផ្ដើម​កម្មវិធី​ +Name[kn]=ಅನ್ವಯ ಪ್ರಕ್ಷೇಪಕ (ಲಾಚರ್) +Name[ko]=프로그램 실행기 +Name[ku]=Deskpêkerê Sepanan +Name[lt]=Programų paleidiklis +Name[lv]=Programmu palaidējs +Name[mai]=अनुप्रयोग चालक +Name[mk]=Стартувач на апликации +Name[ml]=പ്രയോഗവിക്ഷേപിണി +Name[mr]=अनुप्रयोग प्रक्षेपक +Name[nb]=Programstarter +Name[nds]=Programmoproper +Name[ne]=अनुप्रयोक सुरुआतकर्ता +Name[nl]=Programmastarter +Name[nn]=Programstartar +Name[or]=ପ୍ରୟୋଗ ଆରମ୍ଭକର୍ତ୍ତା +Name[pa]=ਐਪਲੀਕੇਸ਼ ਲਾਂਚਰ +Name[pl]=Aktywator programów +Name[pt]=Lançador de Aplicações +Name[pt_BR]=Lançador de aplicativos +Name[ro]=Lansator de aplicații +Name[ru]=Меню запуска приложений +Name[se]=Prográmmaálggaheaddji +Name[si]=යෙදුම් ඇරඹුම +Name[sk]=Spúšťač aplikácií +Name[sl]=Zaganjalnik programov +Name[sr]=покретач програма +Name[sr@ijekavian]=покретач програма +Name[sr@ijekavianlatin]=pokretač programa +Name[sr@latin]=pokretač programa +Name[sv]=Starta program +Name[ta]=பயன்பாடு ஏவி +Name[te]=అనువర్తనం దించునది +Name[tg]=Оғози барномаҳо +Name[th]=ตัวเรียกใช้งานโปรแกรม +Name[tr]=Uygulama Başlatıcısı +Name[ug]=پروگرامما ئىجرا قىلغۇچ +Name[uk]=Інструмент запуску програм +Name[uz]=Dasturlarni ishga tushiruvchi +Name[uz@cyrillic]=Дастурларни ишга туширувчи +Name[vi]=Trình chạy ứng dụng +Name[wa]=Enondeu di programe +Name[x-test]=xxApplication Launcherxx +Name[zh_CN]=程序启动器 +Name[zh_TW]=應用程式啟動器 +Comment=Launcher to start applications +Comment[af]=Lanseerder om programme te loop +Comment[ar]=مطلق لتشغيل التطبيقات +Comment[ast]=Llanzador pa entamar aplicaciones +Comment[be@latin]=Uklučeńnie aplikacyjaŭ +Comment[bg]=Стартиране на програми +Comment[bn]=বিভিন্ন অ্যাপলিকেশন চালু করার জন্য লঞ্চার +Comment[bs]=Pokretač za programe +Comment[ca]=Llançador per a iniciar aplicacions +Comment[ca@valencia]=Llançador per a iniciar aplicacions +Comment[cs]=Aplikace pro spouštění aplikací +Comment[da]=Til at starte programmer +Comment[de]=Ermöglicht den Aufruf verschiedenster Programme +Comment[el]=Εκτέλεση εφαρμογών +Comment[en_GB]=Launcher to start applications +Comment[eo]=Aplikaĵolanĉilo +Comment[es]=Lanzador para iniciar aplicaciones +Comment[et]=Rakenduste käivitaja +Comment[eu]=Aplikazioak abiarazteko abiarazlea +Comment[fi]=Sovellusten käynnistysvalikko +Comment[fr]=Lanceur pour démarrer des applications +Comment[fy]=Starter om applikaasjes útein te setten +Comment[ga]=Ríomhchlár a thosaíonn feidhmchláir +Comment[gl]=Iniciador para iniciar programas +Comment[gu]=કાર્યક્રમો શરૂ કરનાર +Comment[he]=משגר לפתיחת יישומים +Comment[hi]=अनुप्रयोग प्रारंभ करने के लिए चालक +Comment[hne]=अनुपरयोग ल चालू करे बर लांचर +Comment[hr]=Pokretač aplikacija +Comment[hsb]=Startowar, kiž aplikacije wuwjedźe +Comment[hu]=Alkalmazásindító +Comment[ia]=Lanceator pro initiar applicationes +Comment[id]=Peluncur untuk menjalankan aplikasi +Comment[is]=Flýtiræsing forrita +Comment[it]=Avviatore per far partire le applicazioni +Comment[ja]=アプリケーションを起動します +Comment[kk]=Қолданба жеккіші +Comment[km]=កម្មវិធី​ចាប់ផ្ដើម​ត្រូវ​ចាប់ផ្ដើម​កម្មវិធី +Comment[kn]=ಅನ್ವಯಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲು ಒಂದು ಪ್ರಕ್ಷೇಪಕ (ಲಾಂಚರ್) +Comment[ko]=프로그램을 시작하는 실행기 +Comment[lt]=Programų paleidiklis +Comment[lv]=Poga programmu palaišanai +Comment[mk]=Аплет за стартување апликации +Comment[ml]=പ്രയോഗങ്ങള്‍ ആരംഭിക്കുന്നതിനു് സഹായിക്കുന്ന സംവിധാനം +Comment[mr]=अनुप्रयोग सुरु करण्याकरिता प्रक्षेपक +Comment[nb]=Starter programmer som ikke hører til KDE +Comment[nds]=Röppt Programmen op +Comment[ne]=अनुप्रयोग सुरुआत गर्न सुरुआतकर्ता +Comment[nl]=Applet voor het starten van programma's +Comment[nn]=Moderne programstartar +Comment[pa]=ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਉਣ ਲਈ ਲਾਂਚਰ +Comment[pl]=Aktywator do uruchamiania programów +Comment[pt]=Lançador para iniciar aplicações +Comment[pt_BR]=Lançador para iniciar aplicativos +Comment[ro]=Lansator pentru a porni aplicații +Comment[ru]=Современное меню запуска приложений +Comment[se]=Prográmmaálggaheaddji +Comment[si]=යෙදුම් ආරම්භ කිරීමට ආරම්භකය +Comment[sk]=Aplikácia na spúšťanie aplikácií +Comment[sl]=Zaganjalnik za zagon programov +Comment[sr]=Покретач за програме +Comment[sr@ijekavian]=Покретач за програме +Comment[sr@ijekavianlatin]=Pokretač za programe +Comment[sr@latin]=Pokretač za programe +Comment[sv]=Startprogram för att köra program +Comment[ta]=பயன்பாடுகளை ஏவிடத் தேவையான தளம் +Comment[te]=అనువర్తనాలను ప్రారంభించుటకు లాంచర్ +Comment[tg]=Средство для запуска приложений +Comment[th]=ตัวเรียกใช้งานโปรแกรมให้ทำงาน +Comment[tr]=Uygulamaları başlatmak için çalıştırıcı +Comment[ug]=پروگراممىنى قوزغىتىدىغان ئىجراچى(Launcher) +Comment[uk]=Програма для запуску програм +Comment[uz]=Dasturlarni ishga tushiruvchi vosita +Comment[uz@cyrillic]=Дастурларни ишга туширувчи восита +Comment[vi]=Mục chạy để khởi động ứng dụng +Comment[wa]=Enondeu po lancî des programes +Comment[x-test]=xxLauncher to start applicationsxx +Comment[zh_CN]=应用程序的启动器 +Comment[zh_TW]=應用程式啟動器 +Icon=start-here-kde +Type=Service +X-KDE-ServiceTypes=Plasma/Applet,Plasma/PopupApplet + +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/Kickoff.qml + +X-Plasma-RequiredExtensions=LaunchApp + +X-KDE-PluginInfo-Author=Martin Graesslin +X-KDE-PluginInfo-Email=plasma-devel@kde.org +X-KDE-PluginInfo-Name=org.kde.plasma.kickoff +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=http://userbase.kde.org/Plasma/Kickoff +X-KDE-PluginInfo-Category=Application Launchers +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true diff --git a/applets/pager/CMakeLists.txt b/applets/pager/CMakeLists.txt new file mode 100644 index 0000000000..6e9ae365c7 --- /dev/null +++ b/applets/pager/CMakeLists.txt @@ -0,0 +1,27 @@ +plasma_install_package(package org.kde.plasma.pager) + +set(pager_SRCS + plugin/model.cpp + plugin/pager.cpp + plugin/pagerplugin.cpp) + +add_library(pagerplugin SHARED ${pager_SRCS}) + +target_link_libraries(pagerplugin + KF5::KIOCore + KF5::WindowSystem + KF5::Plasma + KF5::Activities + KF5::KDE4Support + Qt5::Core + Qt5::Qml + Qt5::Quick + Qt5::DBus + taskmanager) + +if (X11_FOUND) + target_link_libraries(pagerplugin Qt5::X11Extras) +endif() + +install(TARGETS pagerplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/pager) +install(FILES plugin/qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/pager) diff --git a/applets/pager/Messages.sh b/applets/pager/Messages.sh new file mode 100644 index 0000000000..65ed909ad8 --- /dev/null +++ b/applets/pager/Messages.sh @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_org.kde.plasma.pager.pot +rm -f rc.cpp \ No newline at end of file diff --git a/applets/pager/package/contents/code/utils.js b/applets/pager/package/contents/code/utils.js new file mode 100644 index 0000000000..296c97766a --- /dev/null +++ b/applets/pager/package/contents/code/utils.js @@ -0,0 +1,6 @@ +.pragma library + +function contains(item, point) { + return point.x >= item.x && point.x <= item.x + item.width + && point.y >= item.y && point.y <= item.y + item.height; +} diff --git a/applets/pager/package/contents/config/config.qml b/applets/pager/package/contents/config/config.qml new file mode 100644 index 0000000000..edf43ea813 --- /dev/null +++ b/applets/pager/package/contents/config/config.qml @@ -0,0 +1,29 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.configuration 2.0 + +ConfigModel { + ConfigCategory { + name: i18n("General") + icon: "user-desktop" + source: "configGeneral.qml" + } +} diff --git a/applets/pager/package/contents/config/main.xml b/applets/pager/package/contents/config/main.xml new file mode 100644 index 0000000000..100893380d --- /dev/null +++ b/applets/pager/package/contents/config/main.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + 2 + + + false + + + + + + + + 0 + + + + + + + diff --git a/applets/pager/package/contents/ui/configGeneral.qml b/applets/pager/package/contents/ui/configGeneral.qml new file mode 100644 index 0000000000..d84d29ebdc --- /dev/null +++ b/applets/pager/package/contents/ui/configGeneral.qml @@ -0,0 +1,143 @@ +/* + * Copyright 2013 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 as Layouts + + +//FIXME this causes a crash in Oxygen style +//QtControls.GroupBox { +Item { + + width: childrenRect.width + height: childrenRect.height + +//FIXME enable when we're back to being a group box +// flat: true +// title: i18n("Appearance") + + property int cfg_displayedText + property alias cfg_showWindowIcons: showRecentlyInstalledCheckbox.checked + property int cfg_currentDesktopSelected + + onCfg_displayedTextChanged: { + switch (cfg_displayedText) { + case 0: + displayedTextGroup.current = desktopNumberRadio; + break; + case 1: + displayedTextGroup.current = desktopNameRadio; + break; + default: + case 2: + displayedTextGroup.current = noTextRadio; + break; + } + } + + onCfg_currentDesktopSelectedChanged: { + switch (cfg_currentDesktopSelected) { + case 0: + currentDesktopSelectedGroup.current = doesNothingRadio; + break; + case 1: + currentDesktopSelectedGroup.current = showsDesktopRadio; + break; + default: + case 2: + currentDesktopSelectedGroup.current = showsDashboardRadio; + break; + } + } + + QtControls.ExclusiveGroup { + id: displayedTextGroup + } + QtControls.ExclusiveGroup { + id: currentDesktopSelectedGroup + } + + Layouts.GridLayout { + columns: 2 + QtControls.Label { + text: i18n("Display Text:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + QtControls.RadioButton { + id: desktopNumberRadio + exclusiveGroup: displayedTextGroup + text: i18n("Desktop number") + onCheckedChanged: if (checked) cfg_displayedText = 0; + } + Item { + width: 2 + height: 2 + Layouts.Layout.rowSpan: 2 + } + QtControls.RadioButton { + id: desktopNameRadio + exclusiveGroup: displayedTextGroup + text: i18n("Desktop name") + onCheckedChanged: if (checked) cfg_displayedText = 1; + } + QtControls.RadioButton { + id: noTextRadio + exclusiveGroup: displayedTextGroup + text: i18n("No text") + onCheckedChanged: if (checked) cfg_displayedText = 2; + } + + QtControls.Label { + text: i18n("Display icons:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + QtControls.CheckBox { + id: showRecentlyInstalledCheckbox + } + + QtControls.Label { + text: i18n("Selecting current desktop:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + QtControls.RadioButton { + id: doesNothingRadio + exclusiveGroup: currentDesktopSelectedGroup + text: i18n("Does nothing") + onCheckedChanged: if (checked) cfg_currentDesktopSelected = 0; + } + Item { + width: 2 + height: 2 + Layouts.Layout.rowSpan: 2 + } + QtControls.RadioButton { + id: showsDesktopRadio + exclusiveGroup: currentDesktopSelectedGroup + text: i18n("Shows desktop") + onCheckedChanged: if (checked) cfg_currentDesktopSelected = 1; + } + QtControls.RadioButton { + id: showsDashboardRadio + exclusiveGroup: currentDesktopSelectedGroup + text: i18n("Shows the dashboard") + onCheckedChanged: if (checked) cfg_currentDesktopSelected = 2; + } + } + +} diff --git a/applets/pager/package/contents/ui/main.qml b/applets/pager/package/contents/ui/main.qml new file mode 100644 index 0000000000..a7346e3a51 --- /dev/null +++ b/applets/pager/package/contents/ui/main.qml @@ -0,0 +1,329 @@ +/* + * Copyright 2012 Luís Gabriel Lima + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 . + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddonsComponents +import org.kde.draganddrop 2.0 +import org.kde.plasma.private.pager 2.0 +import "utils.js" as Utils + +Item { + id: root + + property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + + Layout.minimumWidth: Layout.maximumWidth + Layout.minimumHeight: Layout.maximumHeight + + Layout.maximumWidth: !root.vertical ? pager.preferredSize.width : undefined + Layout.maximumHeight: root.vertical ? pager.preferredSize.height : undefined + + Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation + Layout.fillWidth: root.vertical + Layout.fillHeight: !root.vertical + + property bool dragging: false + property int dragId + + property int dragSwitchDesktopId: -1 + + anchors.fill: parent + //visible: repeater.count > 1 // FIXME: re-enable and fix collapsing + + property color windowActiveOnActiveDesktopColor: theme.textColor + property color windowInactiveOnActiveDesktopColor: theme.textColor + property color windowActiveColor: theme.textColor + property color windowActiveBorderColor: theme.textColor + property color windowInactiveColor: theme.textColor + property color windowInactiveBorderColor: theme.textColor + + function action_addDesktop() { + pager.slotAddDesktop(); + } + + function action_removeDesktop() { + pager.slotRemoveDesktop(); + } + + Connections { + target: theme + onThemeChanged: { + windowActiveOnActiveDesktopColor = theme.textColor + windowActiveOnActiveDesktopColor.a = 0.6 + windowActiveColor = theme.textColor + windowActiveColor.a = 0.5; + windowActiveBorderColor = theme.textColor + //windowActiveBorderColor = 1 + + windowInactiveOnActiveDesktopColor = theme.textColor + windowInactiveOnActiveDesktopColor.a = 0.35; + windowInactiveColor = theme.textColor + windowInactiveColor.a = 0.17; + windowInactiveBorderColor = theme.textColor + windowInactiveBorderColor.a = 0.5 + } + } + Component.onCompleted: { + plasmoid.setAction("addDesktop", i18n("Add Virtual Desktop"), "list-add"); + plasmoid.setAction("removeDesktop", i18n("Remove Virtual Desktop"), "list-remove"); + windowActiveOnActiveDesktopColor = theme.textColor + windowActiveOnActiveDesktopColor.a = 0.6 + windowActiveColor = theme.textColor + windowActiveColor.a = 0.5; + windowActiveBorderColor = theme.textColor + //windowActiveBorderColor = 1 + + windowInactiveOnActiveDesktopColor = theme.textColor + windowInactiveOnActiveDesktopColor.a = 0.35; + windowInactiveColor = theme.textColor + windowInactiveColor.a = 0.17; + windowInactiveBorderColor = theme.textColor + windowInactiveBorderColor.a = 0.5 + } + + Pager { + id: pager + orientation: plasmoid.formFactor == PlasmaCore.Types.Vertical ? Qt.Vertical : Qt.Horizontal + size: Qt.size(root.width, root.height) + showWindowIcons: plasmoid.configuration.showWindowIcons + currentDesktopSelected: plasmoid.configuration.currentDesktopSelected + displayedText: plasmoid.configuration.displayedText + } + + Timer { + id: dragTimer + interval: 1000 + onTriggered: { + if (dragSwitchDesktopId != -1 && dragSwitchDesktopId !== pager.currentDesktop-1) { + pager.changeDesktop(dragSwitchDesktopId); + } + } + } + + Repeater { + id: repeater + model: pager.model + + PlasmaCore.ToolTipArea { + id: desktop + + property int desktopId: index + property string desktopName: model.desktopName ? model.desktopName : "" + property bool active: (desktopId === pager.currentDesktop-1) + + mainText: desktopName + + Component.onCompleted: { + console.log(model.windows) + } + + x: model.x + y: model.y + width: model.width + height: model.height + + PlasmaCore.FrameSvgItem { + anchors.fill: parent + z: 1 // to make sure that the FrameSvg will be placed on top of the windows + imagePath: "widgets/pager" + prefix: (desktopMouseArea.enabled && desktopMouseArea.containsMouse) || (root.dragging && root.dragId == desktopId) ? + "hover" : (desktop.active ? "active" : "normal") + } + + DropArea { + id: droparea + anchors.fill: parent + onDragEnter: { + root.dragSwitchDesktopId = desktop.desktopId; + dragTimer.start(); + } + onDragLeave: { + root.dragSwitchDesktopId = -1; + dragTimer.stop(); + } + onDrop: { + pager.dropMimeData(event.mimeData, desktop.desktopId); + root.dragSwitchDesktopId = -1; + dragTimer.stop(); + } + } + + MouseArea { + id: desktopMouseArea + anchors.fill: parent + onClicked: pager.changeDesktop(desktopId); + } + + Item { + id: clipRect + x: 1 + y: 1 + width: desktop.width - 2 + height: desktop.height - 2 + clip: true + + PlasmaComponents.Label { + id: desktopText + anchors.centerIn: parent + text: pager.displayedText == Pager.Name ? desktop.desktopName + : (pager.displayedText == Pager.Number ? desktop.desktopId+1 : "") + + } + + Repeater { + model: windows + + //update the tooltip whenever we add or remove a window + onCountChanged: { + var tooltipText = i18n("%1 windows", count) + var i; + for (i=0; i < Math.min(count,4); i++) { + tooltipText += "

  • "+ itemAt(i).visibleName +"
  • "; + } + if (i < count) { + tooltipText += "
    " + tooltipText += i18n("and %1 other windows", count-i) + } + + + desktop.subText = tooltipText + } + + Rectangle { + id: windowRect + + property int windowId: model.windowId + property string visibleName: model.visibleName + + /* since we move clipRect with 1, move it back */ + x: model.x - 1 + y: model.y - 1 + width: model.width + height: model.height + color: { + if (desktop.active) { + if (model.active) + return windowActiveOnActiveDesktopColor; + else + return windowInactiveOnActiveDesktopColor; + } else { + if (model.active) + return windowActiveColor; + else + return windowInactiveColor; + } + } + + border.width: 1 + border.color: model.active ? windowActiveBorderColor + : windowInactiveBorderColor + + KQuickControlsAddonsComponents.QPixmapItem { + id: icon + anchors.centerIn: parent + pixmap: model.icon + height: nativeHeight + width: nativeWidth + visible: pager.showWindowIcons && (windowRect.width >= icon.width) && (windowRect.height >= icon.height) + } + + MouseArea { + id: windowMouseArea + anchors.fill: parent + drag.target: windowRect + drag.axis: Drag.XandYAxis + drag.minimumX: -windowRect.width/2 + drag.maximumX: root.width - windowRect.width/2 + drag.minimumY: -windowRect.height/2 + drag.maximumY: root.height - windowRect.height/2 + + // used to save the state of some properties before the dragging + QtObject { + id: saveState + property int x: -1 + property int y: -1 + property variant parent + property int desktop: -1 + property int mouseX: -1 + property int mouseY: -1 + } + + drag.onActiveChanged: { + root.dragging = drag.active; + desktopMouseArea.enabled = !drag.active; + } + + // reparent windowRect to enable the dragging for other desktops + onPressed: { + if (windowRect.parent == root) + return; + + saveState.x = windowRect.x; + saveState.y = windowRect.y + saveState.parent = windowRect.parent; + saveState.desktop = desktop.desktopId; + saveState.mouseX = mouseX; + saveState.mouseY = mouseY; + + var value = root.mapFromItem(clipRect, windowRect.x, windowRect.y); + windowRect.x = value.x; + windowRect.y = value.y + windowRect.parent = root; + } + + onReleased: { + if (root.dragging) { + pager.moveWindow(windowRect.windowId, windowRect.x, windowRect.y, + root.dragId, saveState.desktop); + } else { + // when there is no dragging (just a click), the event is passed + // to the desktop mousearea + desktopMouseArea.clicked(mouse); + } + + windowRect.x = saveState.x; + windowRect.y = saveState.y; + windowRect.parent = saveState.parent; + } + } + + function checkDesktopHover() { + if (!windowMouseArea.drag.active) + return; + + var mouse = root.mapFromItem(windowRect, saveState.mouseX, saveState.mouseY); + for (var i = 0; i < root.children.length; i++) { + var item = root.children[i]; + if (item.desktopId != undefined && Utils.contains(item, mouse)) { + root.dragId = item.desktopId; + return; + } + } + } + + onXChanged: checkDesktopHover(); + onYChanged: checkDesktopHover(); + } + } + } + } + } +} diff --git a/applets/pager/package/metadata.desktop b/applets/pager/package/metadata.desktop new file mode 100644 index 0000000000..fb33932d32 --- /dev/null +++ b/applets/pager/package/metadata.desktop @@ -0,0 +1,170 @@ +[Desktop Entry] +Name=Pager +Name[af]=Pager +Name[ar]=المنادي +Name[ast]=Paxinador +Name[be@latin]=Stały +Name[bg]=Пейджър +Name[bn]=পেজার +Name[bn_IN]=পেজার +Name[bs]=pejdžer +Name[ca]=Paginador +Name[ca@valencia]=Paginador +Name[cs]=Přepínač ploch +Name[csb]=Pager +Name[da]=Skrivebordsvælger +Name[de]=Arbeitsflächen-Umschalter +Name[el]=Πίνακας σελίδων +Name[en_GB]=Pager +Name[eo]=Paĝilo +Name[es]=Paginador +Name[et]=Peiler +Name[eu]=Bilagailua +Name[fa]=پی‌جو +Name[fi]=Sivutin +Name[fr]=Gestionnaire de bureaux +Name[fy]=Semafoan +Name[ga]=Brabhsálaí Leathanach +Name[gl]=Paxinador +Name[gu]=પેજર +Name[hi]=पेजर +Name[hne]=पेजर +Name[hr]=Pager +Name[hsb]=Listowar +Name[hu]=Asztalváltó +Name[ia]=Pager +Name[id]=Pemisah +Name[is]=Flettir +Name[it]=Cambiadesktop +Name[ja]=ページャ +Name[kk]=Ақтарғыш +Name[km]=Pager +Name[kn]=ಪುಟವೀಕ್ಷಕ (ಪೇಜರ್) +Name[ko]=데스크톱 전환기 +Name[ku]=Rûpelker +Name[lt]=Puslapiuotojas +Name[lv]=Lapotājs +Name[mai]=पेजर +Name[mk]=Пејџер +Name[ml]=പേജര്‍ +Name[mr]=पेजर +Name[nb]=Skrivebordsbytter +Name[nds]=Schriefdisch-Översicht +Name[ne]=पेजर +Name[nl]=Pager +Name[nn]=Skrivebordsbytar +Name[oc]=Recebedor d'apèl +Name[or]=ପେଜର +Name[pa]=ਪੇਜ਼ਰ +Name[pl]=Pager +Name[pt]=Paginador +Name[pt_BR]=Paginador +Name[ro]=Paginator +Name[ru]=Переключение рабочих столов +Name[se]=Čállinbeavdemolsojeaddj +Name[si]=පේජරය +Name[sk]=Prepínač plôch +Name[sl]=Pozivnik +Name[sr]=листач +Name[sr@ijekavian]=листач +Name[sr@ijekavianlatin]=listač +Name[sr@latin]=listač +Name[sv]=Skrivbordsvisning +Name[ta]=Pager +Name[te]=పేజర్ +Name[tg]=Пейҷер +Name[th]=สลับหน้าพื้นที่ทำงาน +Name[tr]=Sayfalayıcı +Name[ug]=چاقىرغۇ +Name[uk]=Пейджер +Name[wa]=Pager +Name[x-test]=xxPagerxx +Name[zh_CN]=分页器 +Name[zh_TW]=虛擬桌面管理器 +Comment=Switch between virtual desktops +Comment[ar]=يبدل بين أسطح المكتب الافتراضية +Comment[ast]=Camudar ente escritorios virtuales +Comment[be@latin]=Pieraklučeńnie virtualnych stałoŭ +Comment[bg]=Превключване между работните плотове +Comment[bs]=Prebacujte virtuelne površi +Comment[ca]=Commuta entre escriptoris virtuals +Comment[ca@valencia]=Commuta entre escriptoris virtuals +Comment[cs]=Přepínač mezi virtuálními plochami +Comment[da]=Skift mellem virtuelle skriveborde +Comment[de]=Ermöglicht Ihnen das Wechseln zwischen virtuellen Arbeitsflächen. +Comment[el]=Εναλλαγή μεταξύ εικονικών επιφανειών εργασίας +Comment[en_GB]=Switch between virtual desktops +Comment[eo]=Komuti inter virtualaj labortabloj +Comment[es]=Cambiar entre escritorios virtuales +Comment[et]=Lülitumine virtuaalsete töölaudade vahel +Comment[eu]=Aldatu alegiazko mahaigain batetik bestera +Comment[fi]=Vaihda virtuaalityöpöytää +Comment[fr]=Passe d'un bureau virtuel à l'autre +Comment[fy]=Wikselje tusken firuele buroblêden +Comment[ga]=Athraigh an deasc fhíorúil +Comment[gl]=Troca entre escritorios virtuais +Comment[gu]=વર્ચ્યુઅલ ડેસ્કટોપ્સની વચ્ચે બદલો +Comment[he]=משמש למעבר בין שולחנות עבודה וירטואלים +Comment[hi]=आभासी डेस्कटॉप्स के बीच स्विच करें +Comment[hne]=आभासी डेस्कटाप मं स्विच करव +Comment[hr]=Mijenjanje virtualnih radnih površina +Comment[hsb]=Mjez wirtuelnymi dźěłowymi powjerchami tam a sem skakać +Comment[hu]=Virtuális asztalok közötti váltásra szolgáló elem +Comment[ia]=Commuta inter scriptorios virtual +Comment[id]=Berpindah di antara desktop virtual +Comment[is]=Skiptir milli sýndarskjáborða +Comment[it]=Passa ad altri desktop virtuali +Comment[ja]=仮想デスクトップを切り替えます +Comment[kk]=Виртуалды үстелдерді ақтару +Comment[km]=ប្ដូរ​រវាង​ផ្ទៃតុ​និម្មិត +Comment[kn]=ವಾಸ್ತವಪ್ರಾಯ ಗಣಕತೆರೆಗಳ ನಡುವೆ ಅಂತರಿಸು +Comment[ko]=가상 데스크톱 사이를 전환합니다 +Comment[lt]=Persijungti tarp virtualių darbastalių +Comment[lv]=Pārslēgties starp virtuālām darbvirsmām +Comment[mk]=Менување меѓу виртуелни раб. површини +Comment[ml]=വര്‍ച്ചുവല്‍ പണിയിടങ്ങള്‍ തമ്മില്‍ മാറുക +Comment[mr]=आभासी डेस्कटॉप बदला +Comment[nb]=Bytt mellom virtuelle skrivebord +Comment[nds]=Twischen Schriefdischen wesseln +Comment[nl]=Schakel tussen virtuele bureaubladen +Comment[nn]=Byt mellom virtuelle skrivebord +Comment[or]=ଆଭାସୀ ଡ଼େସ୍କଟପଗୁଡ଼ିକ ମଧ୍ଯରେ ଅଦଳ ବଦଳ କରନ୍ତୁ +Comment[pa]=ਵੁਰਚੁਅਲ ਡੈਸਕਟਾਪਾਂ ਵਿੱਚ ਸਵਿੱਚ ਕਰੋ +Comment[pl]=Przełączenie między wirtualnymi pulpitami +Comment[pt]=Mudar de ecrã virtual +Comment[pt_BR]=Alterna entre áreas de trabalho virtuais +Comment[ro]=Comută între birouri virtuale +Comment[ru]=Переключение между рабочими столами +Comment[si]=අතත්‍ය වැඩතල අතර මාරුවන්න +Comment[sk]=Prepínanie medzi virtuálnymi plochami +Comment[sl]=Preklapljajte med navideznimi namizji +Comment[sr]=Пребацујте виртуелне површи +Comment[sr@ijekavian]=Пребацујте виртуелне површи +Comment[sr@ijekavianlatin]=Prebacujte virtuelne površi +Comment[sr@latin]=Prebacujte virtuelne površi +Comment[sv]=Byt mellan virtuella skrivbord +Comment[ta]=Switch between virtual desktops +Comment[te]=వర్చ్యువల్ రంగస్థలముల మధ్యన మారుము +Comment[tg]=Переключение между рабочими столами +Comment[th]=สลับไปมาระหว่างพื้นที่ทำงานเสมือน +Comment[tr]=Sanal masaüstleri arasında gezin +Comment[ug]=مەۋھۇم ئۈستەلئۈستىلىرىنى ئالماشتۇر +Comment[uk]=Перемкніть віртуальні стільниці +Comment[wa]=Passer d' on forveyou scribanne a èn ôte +Comment[x-test]=xxSwitch between virtual desktopsxx +Comment[zh_CN]=在虚拟桌面间切换 +Comment[zh_TW]=在虛擬桌面間切換 +Icon=user-desktop +Type=Service +X-Plasma-API=declarativeappletscript +X-KDE-ServiceTypes=Plasma/Applet +X-Plasma-MainScript=ui/main.qml +X-KDE-PluginInfo-Author=The Plasma Team +X-KDE-PluginInfo-Email=plasma-devel@kde.org +X-KDE-PluginInfo-Name=org.kde.plasma.pager +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=http://userbase.kde.org/Plasma/Pager +X-KDE-PluginInfo-Category=Windows and Tasks +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true diff --git a/applets/pager/plugin/model.cpp b/applets/pager/plugin/model.cpp new file mode 100644 index 0000000000..1b80baa0e4 --- /dev/null +++ b/applets/pager/plugin/model.cpp @@ -0,0 +1,250 @@ +/* + * Copyright 2012 Luís Gabriel Lima + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 "model.h" + +RectangleModel::RectangleModel(QObject *parent) + : QAbstractListModel(parent) +{ + setRoleNames(roles()); +} + +QHash RectangleModel::roles() const +{ + QHash rectRoles; + rectRoles[WidthRole] = "width"; + rectRoles[HeightRole] = "height"; + rectRoles[XRole] = "x"; + rectRoles[YRole] = "y"; + return rectRoles; +} + +void RectangleModel::clear() +{ + m_rects.clear(); +} + +void RectangleModel::append(const QRectF &rect) +{ + m_rects.append(rect); +} + +QRectF &RectangleModel::rectAt(int index) +{ + return m_rects[index]; +} + +int RectangleModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return m_rects.count(); +} + +QVariant RectangleModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() > m_rects.count()) + return QVariant(); + + const QRectF &rect = m_rects[index.row()]; + switch(role) { + case WidthRole: + return rect.width(); + case HeightRole: + return rect.height(); + case XRole: + return rect.x(); + case YRole: + return rect.y(); + default: + return QVariant(); + } +} + + +WindowModel::WindowModel(QObject *parent) + : RectangleModel(parent) +{ + setRoleNames(roles()); +} + +QHash WindowModel::roles() const +{ + QHash rectRoles = RectangleModel::roles(); + rectRoles[IdRole] = "windowId"; + rectRoles[ActiveRole] = "active"; + rectRoles[IconRole] = "icon"; + rectRoles[VisibleNameRole] = "visibleName"; + return rectRoles; +} + +void WindowModel::clear() +{ + beginResetModel(); + RectangleModel::clear(); + m_ids.clear(); + m_active.clear(); + m_icons.clear(); + m_visibleNames.clear(); + endResetModel(); +} + +void WindowModel::append(WId windowId, const QRectF &rect, bool active, + const QPixmap &icon, const QString &name) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_ids.append(windowId); + RectangleModel::append(rect); + m_active.append(active); + m_icons.append(icon); + m_visibleNames.append(name); + endInsertRows(); +} + +WId WindowModel::idAt(int index) const +{ + return m_ids[index]; +} + +QString WindowModel::visibleNameAt(int index) const +{ + return m_visibleNames[index]; +} + +QVariant WindowModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= rowCount()) + return QVariant(); + + if (role >= RectangleModel::WidthRole && role < IdRole) + return RectangleModel::data(index, role); + + switch (role) { + case IdRole: + return int(m_ids[index.row()]); + case ActiveRole: + return m_active[index.row()]; + case IconRole: + return m_icons[index.row()]; + case VisibleNameRole: + return m_visibleNames[index.row()]; + default: + return QVariant(); + } +} + + +PagerModel::PagerModel(QObject *parent) + : QAbstractListModel(parent) +{ + setRoleNames(roles()); +} + +WindowModel *PagerModel::windowsAt(int index) const +{ + if (index < 0 || index >= m_windows.count()) + return 0; + + return qobject_cast(m_windows[index]); +} + +QHash PagerModel::roles() const +{ + QHash rectRoles = m_desktops.roles(); + rectRoles[WindowsRole] = "windows"; + rectRoles[DesktopNameRole] = "desktopName"; + return rectRoles; +} + +void PagerModel::clearDesktopRects() +{ + beginResetModel(); + m_desktops.clear(); + m_names.clear(); + endResetModel(); +} + +void PagerModel::appendDesktopRect(const QRectF &rect, const QString &name) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_desktops.append(rect); + m_names.append(name); + endInsertRows(); +} + +QRectF& PagerModel::desktopRectAt(int index) +{ + return m_desktops.rectAt(index); +} + +void PagerModel::clearWindowRects() +{ + int removeIndex = -1; + for (int i = 0; i < m_windows.count(); i++) { + windowsAt(i)->clear(); + + if (i >= rowCount()) + removeIndex = (removeIndex == -1) ? i : -1; + } + + if (removeIndex != -1) { + // remove the windows model if the number of desktop has decreased + for (int i = m_windows.count()-1; i >= removeIndex; i--) { + windowsAt(i)->deleteLater(); + m_windows.removeAt(i); + } + } + + // append more windows model if the number of desktop has increased + for (int i = m_windows.count(); i < rowCount(); i++) + m_windows.append(new WindowModel(this)); +} + +void PagerModel::appendWindowRect(int desktopId, WId windowId, const QRectF &rect, + bool active, const QPixmap &icon, const QString &name) +{ + WindowModel *windows = windowsAt(desktopId); + if (!windows) + return; + + windows->append(windowId, rect, active, icon, name); + + QModelIndex i = index(desktopId); + emit dataChanged(i, i); +} + +QVariant PagerModel::data(const QModelIndex &index, int role) const +{ + if (role >= RectangleModel::WidthRole && role < WindowsRole) + return m_desktops.data(index, role); + + if (index.row() < 0 || index.row() >= m_windows.count()) + return QVariant(); + + switch (role) { + case WindowsRole: + return QVariant::fromValue(m_windows[index.row()]); + case DesktopNameRole: + return m_names[index.row()]; + default: + return QVariant(); + } +} + +int PagerModel::rowCount(const QModelIndex &index) const +{ + return m_desktops.rowCount(index); +} diff --git a/applets/pager/plugin/model.h b/applets/pager/plugin/model.h new file mode 100644 index 0000000000..9382247308 --- /dev/null +++ b/applets/pager/plugin/model.h @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Luís Gabriel Lima + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 MODEL_H +#define MODEL_H + +#include +#include +#include // For WId +#include + +class RectangleModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum RectangleRoles { + WidthRole = Qt::UserRole + 1, + HeightRole, + XRole, + YRole + }; + + RectangleModel(QObject *parent = 0); + + virtual QHash roles() const; + virtual void clear(); + void append(const QRectF &rect); + QRectF &rectAt(int index); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +private: + QList m_rects; +}; + + +class WindowModel : public RectangleModel +{ + Q_OBJECT +public: + enum WindowRole { + IdRole = RectangleModel::YRole + 1, + ActiveRole, + IconRole, + VisibleNameRole + }; + + WindowModel(QObject *parent = 0); + + QHash roles() const; + void clear(); + void append(WId, const QRectF &, bool active, const QPixmap &icon, const QString &name); + WId idAt(int index) const; + QString visibleNameAt(int index) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +private: + QList m_ids; + QList m_active; + QList m_icons; + QStringList m_visibleNames; +}; + + +class PagerModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum PagerRoles { + WindowsRole = RectangleModel::YRole + 1, + DesktopNameRole + }; + + PagerModel(QObject *parent = 0); + + QHash roles() const; + + void clearDesktopRects(); + void appendDesktopRect(const QRectF &rect, const QString &name); + QRectF &desktopRectAt(int index); + + void clearWindowRects(); + void appendWindowRect(int desktopId, WId, const QRectF &, bool active, + const QPixmap &icon, const QString &name); + WindowModel *windowsAt(int index) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + +private: + RectangleModel m_desktops; + QList m_windows; + QStringList m_names; +}; + +#endif // MODEL_H diff --git a/applets/pager/plugin/pager.cpp b/applets/pager/plugin/pager.cpp new file mode 100644 index 0000000000..59f13fcd23 --- /dev/null +++ b/applets/pager/plugin/pager.cpp @@ -0,0 +1,601 @@ +/*************************************************************************** + * Copyright (C) 2007 by Daniel Laidig * + * Copyright (C) 2012 by Luís Gabriel Lima * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "pager.h" + +#include + +#include +#include +#include +#include +#if HAVE_X11 +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#if HAVE_X11 +#include +#endif + +#include +#include + +#include + +#include + +const int FAST_UPDATE_DELAY = 100; +const int UPDATE_DELAY = 500; +const int MAXDESKTOPS = 20; +// random(), find a less magic one if you can. -sreich +const qreal MAX_TEXT_WIDTH = 800; + +Pager::Pager(QObject *parent) + : QObject(parent), + m_displayedText(None), + m_currentDesktopSelected(DoNothing), + m_rows(2), + m_columns(0), + m_currentDesktop(0), + m_orientation(Qt::Horizontal), + m_addDesktopAction(0), + m_removeDesktopAction(0), + m_showWindowIcons(false), + m_desktopDown(false), + m_validSizes(false), + m_desktopWidget(QApplication::desktop()) +#if HAVE_X11 + , m_isX11(QX11Info::isPlatformX11()) +#endif +{ + // initialize with a decent default + m_desktopCount = qMax(1, KWindowSystem::numberOfDesktops()); + + m_pagerModel = new PagerModel(this); + + createMenu(); + + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + connect(m_timer, SIGNAL(timeout()), this, SLOT(recalculateWindowRects())); + + connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(currentDesktopChanged(int))); + connect(KWindowSystem::self(), SIGNAL(windowAdded(WId)), this, SLOT(startTimerFast())); + connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), this, SLOT(startTimerFast())); + connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(startTimerFast())); + connect(KWindowSystem::self(), SIGNAL(numberOfDesktopsChanged(int)), this, SLOT(numberOfDesktopsChanged(int))); + connect(KWindowSystem::self(), SIGNAL(desktopNamesChanged()), this, SLOT(desktopNamesChanged())); + connect(KWindowSystem::self(), SIGNAL(stackingOrderChanged()), this, SLOT(startTimerFast())); + connect(KWindowSystem::self(), SIGNAL(windowChanged(WId,const ulong*)), this, SLOT(windowChanged(WId,const ulong*))); + connect(KWindowSystem::self(), SIGNAL(showingDesktopChanged(bool)), this, SLOT(startTimer())); + connect(m_desktopWidget, SIGNAL(screenCountChanged(int)), SLOT(desktopsSizeChanged())); + connect(m_desktopWidget, SIGNAL(resized(int)), SLOT(desktopsSizeChanged())); + + // connect to KWin's reloadConfig signal to get updates on the desktop layout + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.connect(QString(), "/KWin", "org.kde.KWin", "reloadConfig", + this, SLOT(configChanged())); + + recalculateGridSizes(m_rows); + + setCurrentDesktop(KWindowSystem::currentDesktop()); + + KActivities::Consumer *act = new KActivities::Consumer(this); + connect(act, SIGNAL(currentActivityChanged(QString)), this, SLOT(currentActivityChanged(QString))); + m_currentActivity = act->currentActivity(); +} + +Pager::~Pager() +{ +} + + + +void Pager::setCurrentDesktop(int desktop) +{ + if (m_currentDesktop != desktop) { + m_currentDesktop = desktop; + emit currentDesktopChanged(); + } +} + +void Pager::setShowWindowIcons(bool show) +{ + if (m_showWindowIcons != show) { + m_showWindowIcons = show; + emit showWindowIconsChanged(); + } +} + +Qt::Orientation Pager::orientation() const +{ + return m_orientation; +} + +void Pager::setOrientation(Qt::Orientation orientation) +{ + if (m_orientation == orientation) { + return; + } + + m_orientation = orientation; + emit orientationChanged(); + + // whenever we switch to/from vertical form factor, swap the rows and columns around + if (m_columns != m_rows) { + // pass in columns as the new rows + recalculateGridSizes(m_columns); + recalculateWindowRects(); + } +} + +QSizeF Pager::size() const +{ + return m_size; +} + +QSize Pager::preferredSize() const +{ + return m_preferredSize; +} + +void Pager::setSize(const QSizeF &size) +{ + if (m_size == size) { + return; + } + + m_size = size; + emit sizeChanged(); + + m_validSizes = false; + + startTimer(); +} + +Pager::CurrentDesktopSelected Pager::currentDesktopSelected() const +{ + return m_currentDesktopSelected; +} + +void Pager::setCurrentDesktopSelected(CurrentDesktopSelected cur) +{ + if (m_currentDesktopSelected == cur) { + return; + } + + m_currentDesktopSelected = cur; + emit currentDesktopSelectedChanged(); +} + +Pager::DisplayedText Pager::displayedText() const +{ + return m_displayedText; +} + +void Pager::setDisplayedText(Pager::DisplayedText disp) +{ + if (m_displayedText == disp) { + return; + } + + m_displayedText = disp; + emit displayedTextChanged(); +} + +void Pager::createMenu() +{ +#if HAVE_X11 + m_addDesktopAction = new QAction(SmallIcon("list-add"),i18n("&Add Virtual Desktop"), this); + m_actions.append(m_addDesktopAction); + connect(m_addDesktopAction, SIGNAL(triggered(bool)), this , SLOT(slotAddDesktop())); + m_removeDesktopAction = new QAction(SmallIcon("list-remove"),i18n("&Remove Last Virtual Desktop"), this); + m_actions.append(m_removeDesktopAction); + connect(m_removeDesktopAction, SIGNAL(triggered(bool)), this , SLOT(slotRemoveDesktop())); + + if (m_desktopCount <= 1) { + m_removeDesktopAction->setEnabled(false); + } else if (m_desktopCount >= MAXDESKTOPS) { + m_addDesktopAction->setEnabled(false); + } +#endif +} + +QList Pager::contextualActions() +{ + return m_actions; +} + +#if HAVE_X11 +void Pager::slotAddDesktop() +{ + if (!m_isX11) { + return; + } + NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops); + info.setNumberOfDesktops(info.numberOfDesktops() + 1); +} + +void Pager::slotRemoveDesktop() +{ + if (!m_isX11) { + return; + } + NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops); + int desktops = info.numberOfDesktops(); + if (desktops > 1) { + info.setNumberOfDesktops(info.numberOfDesktops() - 1); + } +} +#endif + +void Pager::recalculateGridSizes(int rows) +{ + // recalculate the number of rows and columns in the grid + rows = qBound(1, rows, m_desktopCount); + // avoid weird cases like having 3 rows for 4 desktops, where the last row is unused + int columns = m_desktopCount / rows; + if (m_desktopCount % rows > 0) { + columns++; + } + + rows = m_desktopCount / columns; + if (m_desktopCount % columns > 0) { + rows++; + } + + // update the grid size + m_rows = rows; + m_columns = columns; + + updateSizes(); +} + +void Pager::updateSizes() +{ + const int padding = 2; // Space between miniatures of desktops + const int textMargin = 3; // Space between name of desktop and border + + const qreal leftMargin = 0; + const qreal topMargin = 0; + const qreal rightMargin = 0; + const qreal bottomMargin = 0; + + QRect totalRect; + for (int x = 0; x < m_desktopWidget->screenCount(); x++) { + totalRect |= m_desktopWidget->screenGeometry(x); + } + + const qreal ratio = (qreal) totalRect.width() / + (qreal) totalRect.height(); + + + qreal itemHeight; + qreal itemWidth; + qreal preferredItemHeight; + qreal preferredItemWidth; + + if (orientation() == Qt::Vertical) { + + itemWidth = (m_size.width() - leftMargin - rightMargin - + padding * (m_columns - 1)) / m_columns; + + itemHeight = itemWidth / ratio; + + } else { + // work out the preferred size based on the height of the geometry + preferredItemHeight = (m_size.height() - topMargin - bottomMargin - + padding * (m_rows - 1)) / m_rows; + preferredItemWidth = preferredItemHeight * ratio; + + if (m_displayedText == Name) { + // When containment is in this position we are not limited by low width and we can + // afford increasing width of applet to be able to display every name of desktops + for (int i = 0; i < m_desktopCount; i++) { + QFontMetricsF metrics(KGlobalSettings::taskbarFont()); + QSizeF textSize = metrics.size(Qt::TextSingleLine, KWindowSystem::desktopName(i+1)); + if (textSize.width() + textMargin * 2 > preferredItemWidth) { + preferredItemWidth = textSize.width() + textMargin * 2; + } + } + } + + itemWidth = (m_size.width() - leftMargin - rightMargin - + padding * (m_columns - 1)) / m_columns; + if (itemWidth > preferredItemWidth) { + itemWidth = preferredItemWidth; + } + itemHeight = preferredItemHeight; + if (itemWidth < itemHeight * ratio) { + itemWidth = itemHeight * ratio; + } + } + + m_widthScaleFactor = itemWidth / totalRect.width(); + m_heightScaleFactor = itemHeight / totalRect.height(); + + m_pagerModel->clearDesktopRects(); + + int pw = (int)(leftMargin + (itemWidth + padding) * m_columns + rightMargin); + int ph = (int)(topMargin + (itemHeight + padding) * m_rows + bottomMargin); + + if (orientation() == Qt::Vertical) { + pw = m_size.width(); + } else { + ph = m_size.height(); + } + + m_preferredSize = QSize(pw, ph); + emit preferredSizeChanged(); + + QRectF itemRect(QPointF(leftMargin, topMargin) , QSizeF(itemWidth, itemHeight)); + for (int i = 0; i < m_desktopCount; i++) { + itemRect.moveLeft(leftMargin + (i % m_columns) * (itemWidth + padding)); + itemRect.moveTop(topMargin + (i / m_columns) * (itemHeight + padding)); + + QString name = KWindowSystem::desktopName(i + 1); + m_pagerModel->appendDesktopRect(itemRect, name); + } + + m_validSizes = true; +} + +void Pager::recalculateWindowRects() +{ + if (!m_validSizes) { + updateSizes(); + } + + QList windows = KWindowSystem::stackingOrder(); + m_pagerModel->clearWindowRects(); + +#if HAVE_X11 + foreach (WId window, windows) { + KWindowInfo info = KWindowSystem::windowInfo(window, NET::WMGeometry | NET::WMFrameExtents | + NET::WMWindowType | NET::WMDesktop | + NET::WMState | NET::XAWMState | NET::WMVisibleName); + NET::WindowType type = info.windowType(NET::NormalMask | NET::DialogMask | NET::OverrideMask | + NET::UtilityMask | NET::DesktopMask | NET::DockMask | + NET::TopMenuMask | NET::SplashMask | NET::ToolbarMask | + NET::MenuMask); + + // the reason we don't check for -1 or Net::Unknown here is that legitimate windows, such + // as some java application windows, may not have a type set for them. + // apparently sane defaults on properties is beyond the wisdom of x11. + if (type == NET::Desktop || type == NET::Dock || type == NET::TopMenu || + type == NET::Splash || type == NET::Menu || type == NET::Toolbar || + info.hasState(NET::SkipPager) || info.isMinimized()) { + continue; + } + + //check activity + NETWinInfo netInfo(QX11Info::connection(), window, QX11Info::appRootWindow(), 0, NET::WM2Activities); + QString result(netInfo.activities()); + if (!result.isEmpty() && result != "00000000-0000-0000-0000-000000000000") { + QStringList activities = result.split(','); + if (!activities.contains(m_currentActivity)) { + continue; + } + } + + for (int i = 0; i < m_desktopCount; i++) { + if (!info.isOnDesktop(i+1)) { + continue; + } + + QRectF windowRect = info.frameGeometry(); + + if (KWindowSystem::mapViewport()) { + windowRect = fixViewportPosition(windowRect.toRect()); + } + + windowRect = QRectF(windowRect.x() * m_widthScaleFactor, + windowRect.y() * m_heightScaleFactor, + windowRect.width() * m_widthScaleFactor, + windowRect.height() * m_heightScaleFactor).toRect(); + + bool active = (window == KWindowSystem::activeWindow()); + int windowIconSize = KIconLoader::global()->currentSize(KIconLoader::Small); + int windowRectSize = qMin(windowRect.width(), windowRect.height()); + windowIconSize = qMax(windowIconSize, windowRectSize / 2); + QPixmap icon = KWindowSystem::icon(info.win(), windowIconSize, windowIconSize, true); + m_pagerModel->appendWindowRect(i, window, windowRect, active, icon, info.visibleName()); + } + } +#endif +} + +void Pager::currentDesktopChanged(int desktop) +{ + if (desktop < 1) { + return; // bogus value, don't accept it + } + + setCurrentDesktop(desktop); + m_desktopDown = false; + startTimerFast(); +} + +void Pager::currentActivityChanged(const QString &activity) +{ + m_currentActivity = activity; + startTimerFast(); +} + +void Pager::numberOfDesktopsChanged(int num) +{ + if (num < 1) { + return; // refuse to update to zero desktops + } + +#if HAVE_X11 + m_removeDesktopAction->setEnabled(num > 1); + m_addDesktopAction->setEnabled(num < MAXDESKTOPS); +#endif + + m_desktopCount = num; + + m_pagerModel->clearDesktopRects(); + recalculateGridSizes(m_rows); + recalculateWindowRects(); +} + +void Pager::desktopNamesChanged() +{ + m_pagerModel->clearDesktopRects(); + m_validSizes = false; + startTimer(); +} + +void Pager::windowChanged(WId id, const unsigned long* dirty) +{ + Q_UNUSED(id) + + if (dirty[NETWinInfo::PROTOCOLS] & (NET::WMGeometry | NET::WMDesktop) || + dirty[NETWinInfo::PROTOCOLS2] & NET::WM2Activities) { + startTimer(); + } +} + +void Pager::desktopsSizeChanged() +{ + m_pagerModel->clearDesktopRects(); + m_validSizes = false; + startTimer(); +} + +void Pager::startTimer() +{ + if (!m_timer->isActive()) { + m_timer->start(UPDATE_DELAY); + } +} + +void Pager::startTimerFast() +{ + if (!m_timer->isActive()) { + m_timer->start(FAST_UPDATE_DELAY); + } +} + +void Pager::moveWindow(int window, double x, double y, int targetDesktop, int sourceDesktop) +{ +#if HAVE_X11 + if (!m_isX11) { + return; + } + WId windowId = (WId) window; + + QPointF dest = QPointF(x, y) - m_pagerModel->desktopRectAt(targetDesktop).topLeft(); + + dest = QPointF(dest.x()/m_widthScaleFactor, dest.y()/m_heightScaleFactor); + + // don't move windows to negative positions + dest = QPointF(qMax(dest.x(), qreal(0.0)), qMax(dest.y(), qreal(0.0))); + + // use _NET_MOVERESIZE_WINDOW rather than plain move, so that the WM knows this is a pager request + NETRootInfo info(QX11Info::connection(), 0); + int flags = (0x20 << 12) | (0x03 << 8) | 1; // from tool, x/y, northwest gravity + + if (!KWindowSystem::mapViewport()) { + KWindowInfo windowInfo = KWindowSystem::windowInfo(windowId, NET::WMDesktop | NET::WMState); + + if (!windowInfo.onAllDesktops()) { + KWindowSystem::setOnDesktop(windowId, targetDesktop+1); + } + + // only move the window if it is not full screen and if it is kept within the same desktop + // moving when dropping between desktop is too annoying due to the small drop area. + if (!(windowInfo.state() & NET::FullScreen) && + (targetDesktop == sourceDesktop || windowInfo.onAllDesktops())) { + QPoint d = dest.toPoint(); + info.moveResizeWindowRequest(windowId, flags, d.x(), d.y(), 0, 0); + } + } else { + // setOnDesktop() with viewports is also moving a window, and since it takes a moment + // for the WM to do the move, there's a race condition with figuring out how much to move, + // so do it only as one move + dest += KWindowSystem::desktopToViewport(targetDesktop+1, false); + QPoint d = KWindowSystem::constrainViewportRelativePosition(dest.toPoint()); + info.moveResizeWindowRequest(windowId, flags, d.x(), d.y(), 0, 0); + } + m_timer->start(); +#else + Q_UNUSED(window) + Q_UNUSED(x) + Q_UNUSED(y) + Q_UNUSED(targetDesktop) + Q_UNUSED(sourceDesktop) +#endif +} + +void Pager::changeDesktop(int newDesktop) +{ +#if HAVE_X11 + if (!m_isX11) { + return; + } + if (m_currentDesktop == newDesktop+1) { + // toogle the desktop or the dashboard + if (m_currentDesktopSelected == ShowDesktop) { + NETRootInfo info(QX11Info::connection(), 0); + m_desktopDown = !m_desktopDown; + info.setShowingDesktop(m_desktopDown); + } else if (m_currentDesktopSelected == ShowDashboard) { + QDBusInterface plasmaApp("org.kde.plasma-desktop", "/App"); + plasmaApp.call("toggleDashboard"); + } + } else { + KWindowSystem::setCurrentDesktop(newDesktop + 1); + setCurrentDesktop(newDesktop + 1); + } +#else + Q_UNUSED(newDesktop) +#endif +} + +// KWindowSystem does not translate position when mapping viewports +// to virtual desktops (it'd probably break more things than fix), +// so the offscreen coordinates need to be fixed +QRect Pager::fixViewportPosition( const QRect& r ) +{ + QRect desktopGeom = m_desktopWidget->geometry(); + int x = r.center().x() % desktopGeom.width(); + int y = r.center().y() % desktopGeom.height(); + if( x < 0 ) { + x = x + desktopGeom.width(); + } + if( y < 0 ) { + y = y + desktopGeom.height(); + } + return QRect( x - r.width() / 2, y - r.height() / 2, r.width(), r.height()); +} + + + +#include "moc_pager.cpp" diff --git a/applets/pager/plugin/pager.h b/applets/pager/plugin/pager.h new file mode 100644 index 0000000000..7de49dfb9c --- /dev/null +++ b/applets/pager/plugin/pager.h @@ -0,0 +1,168 @@ +/*************************************************************************** + * Copyright (C) 2007 by Daniel Laidig * + * Copyright (C) 2012 by Luís Gabriel Lima * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 PAGER_H +#define PAGER_H + +#include +#include + +#include + +#include "model.h" +#include + +class QDesktopWidget; + +class KColorScheme; +class KWindowInfo; +class KCModuleProxy; + +namespace Plasma +{ + class FrameSvg; +} + +class Pager : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject* model READ model CONSTANT) + Q_PROPERTY(int currentDesktop READ currentDesktop NOTIFY currentDesktopChanged) + Q_PROPERTY(bool showWindowIcons READ showWindowIcons WRITE setShowWindowIcons NOTIFY showWindowIconsChanged) + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) + Q_PROPERTY(QSizeF size READ size WRITE setSize NOTIFY sizeChanged) + Q_PROPERTY(QSize preferredSize READ preferredSize NOTIFY preferredSizeChanged) + Q_PROPERTY(Pager::CurrentDesktopSelected currentDesktopSelected READ currentDesktopSelected WRITE setCurrentDesktopSelected NOTIFY currentDesktopSelectedChanged) + Q_PROPERTY(Pager::DisplayedText displayedText READ displayedText WRITE setDisplayedText NOTIFY displayedTextChanged) + + public: + enum CurrentDesktopSelected { + DoNothing = 0, + ShowDesktop, + ShowDashboard + }; + Q_ENUMS(CurrentDesktopSelected) + + enum DisplayedText { + Number = 0, + Name, + None + }; + Q_ENUMS(DisplayedText) + + Pager(QObject *parent = 0); + ~Pager(); + + //void constraintsEvent(Plasma::Constraints); + virtual QList contextualActions(); + + QObject *model() const { return m_pagerModel; } + + int currentDesktop() const { return m_currentDesktop; } + void setCurrentDesktop(int desktop); + + bool showWindowIcons() const { return m_showWindowIcons; } + void setShowWindowIcons(bool show); + + Qt::Orientation orientation() const; + void setOrientation(Qt::Orientation orientation); + + QSizeF size() const; + void setSize(const QSizeF &size); + + QSize preferredSize() const; + + CurrentDesktopSelected currentDesktopSelected() const; + void setCurrentDesktopSelected(CurrentDesktopSelected cur); + + DisplayedText displayedText() const; + void setDisplayedText(DisplayedText disp); + + Q_INVOKABLE void moveWindow(int, double, double, int, int); + Q_INVOKABLE void changeDesktop(int desktopId); + + Q_SIGNALS: + void currentDesktopChanged(); + void showWindowIconsChanged(); + void orientationChanged(); + void sizeChanged(); + void preferredSizeChanged(); + void currentDesktopSelectedChanged(); + void displayedTextChanged(); + + public Q_SLOTS: + void recalculateGridSizes(int rows); + void updateSizes(); + void recalculateWindowRects(); + + protected Q_SLOTS: + void currentDesktopChanged(int desktop); + void currentActivityChanged(const QString &activity); + void desktopsSizeChanged(); + void numberOfDesktopsChanged(int num); + void desktopNamesChanged(); + void windowChanged(WId id, const unsigned long *dirty); + void startTimer(); + void startTimerFast(); +#if HAVE_X11 + void slotAddDesktop(); + void slotRemoveDesktop(); +#endif + + protected: + void createMenu(); + QRect fixViewportPosition( const QRect& r ); + + private: + + PagerModel *m_pagerModel; + + QTimer* m_timer; + + + DisplayedText m_displayedText; + CurrentDesktopSelected m_currentDesktopSelected; + int m_rows; + int m_columns; + int m_desktopCount; + int m_currentDesktop; + QString m_currentActivity; + qreal m_widthScaleFactor; + qreal m_heightScaleFactor; + QSizeF m_size; + QSize m_preferredSize; + Qt::Orientation m_orientation; + + //list of info about animations for each desktop + QList m_actions; + QAction *m_addDesktopAction; + QAction *m_removeDesktopAction; + + bool m_showWindowIcons : 1; + bool m_desktopDown : 1; + bool m_validSizes : 1; + + QDesktopWidget *m_desktopWidget; +#if HAVE_X11 + bool m_isX11; +#endif + }; + +#endif diff --git a/applets/pager/plugin/pagerplugin.cpp b/applets/pager/plugin/pagerplugin.cpp new file mode 100644 index 0000000000..4f55e84747 --- /dev/null +++ b/applets/pager/plugin/pagerplugin.cpp @@ -0,0 +1,29 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 "pagerplugin.h" +#include "pager.h" + +#include + +void KickoffPlugin::registerTypes (const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.pager")); + qmlRegisterType(uri, 2, 0, "Pager"); +} diff --git a/applets/pager/plugin/pagerplugin.h b/applets/pager/plugin/pagerplugin.h new file mode 100644 index 0000000000..09178e4557 --- /dev/null +++ b/applets/pager/plugin/pagerplugin.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 PAGERPLUGIN_H +#define PAGERPLUGIN_H + +#include +#include + + +class KickoffPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") +public: + virtual void registerTypes(const char *uri); +}; + +#endif // PAGERPLUGIN_H diff --git a/applets/pager/plugin/qmldir b/applets/pager/plugin/qmldir new file mode 100644 index 0000000000..a4e5c44b8c --- /dev/null +++ b/applets/pager/plugin/qmldir @@ -0,0 +1 @@ +plugin pagerplugin diff --git a/applets/showActivityManager/CMakeLists.txt b/applets/showActivityManager/CMakeLists.txt new file mode 100644 index 0000000000..71ae11bc79 --- /dev/null +++ b/applets/showActivityManager/CMakeLists.txt @@ -0,0 +1 @@ +plasma_install_package(package org.kde.plasma.showActivityManager) diff --git a/applets/showActivityManager/Messages.sh b/applets/showActivityManager/Messages.sh new file mode 100644 index 0000000000..36cad89025 --- /dev/null +++ b/applets/showActivityManager/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_org.kde.plasma.showActivityManager.pot +rm -f rc.cpp diff --git a/applets/showActivityManager/package/contents/ui/main.qml b/applets/showActivityManager/package/contents/ui/main.qml new file mode 100644 index 0000000000..defcdf2cb9 --- /dev/null +++ b/applets/showActivityManager/package/contents/ui/main.qml @@ -0,0 +1,61 @@ +/* + * Copyright 2012 Gregor Taetzner + * + * This program 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 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 Library 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. + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +MouseArea { + id: iconContainer + property string activeSource: "Status" + height: 16 + width: 16 + Layout.minimumWidth: 16 + Layout.minimumHeight: 16 + implicitWidth: units.iconSizes["panel"] + implicitHeight: implicitWidth + onClicked: { + var service = dataSource.serviceForSource(activeSource) + var operation = service.operationDescription("toggleActivityManager") + service.startOperationCall(operation) + } + + PlasmaCore.DataSource { + id: dataSource + engine: "org.kde.activities" + connectedSources: [activeSource] + } + + PlasmaCore.ToolTipArea { + id: tooltip + mainText: i18n("Show Activity Manager") + subText: i18n("Click to show the activity manager") + anchors.fill: parent + image: "preferences-activities" + } + + PlasmaCore.IconItem { + id: icon + source: "preferences-activities" + width: parent.width + height: parent.height + } +} + diff --git a/applets/showActivityManager/package/metadata.desktop b/applets/showActivityManager/package/metadata.desktop new file mode 100644 index 0000000000..28c59e60f2 --- /dev/null +++ b/applets/showActivityManager/package/metadata.desktop @@ -0,0 +1,127 @@ +[Desktop Entry] +Name=Activities +Name[ar]=الأنشطة +Name[bg]=Дейности +Name[bs]=motor aktivnosti +Name[ca]=Activitats +Name[ca@valencia]=Activitats +Name[cs]=Aktivity +Name[da]=Aktiviteter +Name[de]=Aktivitäten +Name[el]=Δραστηριότητες +Name[es]=Actividades +Name[et]=Tegevused +Name[eu]=Jarduerak +Name[fa]=فعالیتها +Name[fi]=Aktiviteetit +Name[fr]=Activités +Name[ga]=Gníomhaíochtaí +Name[gl]=Actividades +Name[he]=עילויות +Name[hr]=Aktivnosti +Name[hu]=Aktivitások +Name[ia]=Activitates +Name[is]=Virknistjóri +Name[it]=Attività +Name[ja]=アクティビティ +Name[kk]=Белсенділіктер +Name[km]=សកម្មភាព +Name[ko]=활동 +Name[lt]=Veiklos +Name[lv]=Aktivitātes +Name[mr]=कार्यपध्दती +Name[nb]=Aktiviteter +Name[nds]=Aktiviteten +Name[nl]=Activiteiten +Name[pa]=ਸਰਗਰਮੀਆਂ +Name[pl]=Działania +Name[pt]=Actividades +Name[pt_BR]=Atividades +Name[ro]=Activități +Name[ru]=Комнаты +Name[sk]=Aktivity +Name[sl]=Dejavnosti +Name[sr]=активности +Name[sr@ijekavian]=активности +Name[sr@ijekavianlatin]=aktivnosti +Name[sr@latin]=aktivnosti +Name[sv]=Aktiviteter +Name[tr]=Etkinlikler +Name[ug]=پائالىيەتلەر +Name[uk]=Простори дій +Name[vi]=Hoạt động +Name[wa]=Activités +Name[x-test]=xxActivitiesxx +Name[zh_CN]=活动 +Name[zh_TW]=活動 +Comment=Shows the activity manager +Comment[bg]=Управление на дейностите +Comment[bs]=Prikazuje menadžer aktivnosti +Comment[ca]=Mostra el gestor d'activitats +Comment[ca@valencia]=Mostra el gestor d'activitats +Comment[cs]=Zobrazí správce aktivit +Comment[da]=Vis aktivitetshåndtering +Comment[de]=Zeigt die Aktivitätenverwaltung an +Comment[el]=Εμφανίζει το διαχειριστή δραστηριοτήτων +Comment[es]=Muestra el gestor de actividades +Comment[et]=Tegevuste halduri näitamine +Comment[eu]=Jarduera-kudeatzailea erakusten du +Comment[fi]=Näyttää aktiviteettienhallinnan +Comment[fr]=Affiche le gestionnaire d'activités +Comment[ga]=Taispeáin an bainisteoir gníomhaíochta +Comment[gl]=Mostra o xestor da actividade +Comment[he]=מציג את מנהל פעילויות +Comment[hr]=Prikazuje upravitelja aktivnosti +Comment[hu]=Aktivitáskezelő megjelenítése +Comment[ia]=Monstra le gerente de activitate +Comment[is]=Birtir virknistjóra +Comment[it]=Mostra il gestore delle attività +Comment[kk]=Белсенділік менеджері көрсетеді +Comment[km]=បង្ហាញ​កម្មវិធី​គ្រប់គ្រង​សកម្មភាព​ +Comment[ko]=활동 관리자 보이기 +Comment[lt]=Rodo veiklų tvarkyklę +Comment[lv]=Rāda aktivitāšu pārvaldnieku +Comment[mr]=कार्यपध्दती व्यवस्थापक दर्शवितो +Comment[nb]=Viser aktivitetshåndtereren +Comment[nds]=Wiest den Aktivitetenpleger +Comment[nl]=Toont de activiteitenbeheerder +Comment[pa]=ਸਰਗਰਮੀ ਮੈਨੇਜਰ ਵੇਖਾਉਂਦਾ ਹੈ +Comment[pl]=Pokazuje menadżera działań +Comment[pt]=Mostra o gestor de actividades +Comment[pt_BR]=Mostra o gerenciador de atividades +Comment[ro]=Arată Gestionarul de activități +Comment[ru]=Показывает диспетчер комнат +Comment[sk]=Ukáže správcu aktivít +Comment[sl]=Prikaže upravljalnika dejavnosti +Comment[sr]=Приказује менаџер активности +Comment[sr@ijekavian]=Приказује менаџер активности +Comment[sr@ijekavianlatin]=Prikazuje menadžer aktivnosti +Comment[sr@latin]=Prikazuje menadžer aktivnosti +Comment[sv]=Visar Aktivitetshanteraren +Comment[tr]=Etkinlik yöneticisini gösterir +Comment[ug]=پائالىيەت باشقۇرغۇچنى كۆرسىتىدۇ +Comment[uk]=Показує вікно керування просторами дій +Comment[wa]=Mostrer l' manaedjeu des activités +Comment[x-test]=xxShows the activity managerxx +Comment[zh_CN]=显示活动管理器 +Comment[zh_TW]=顯示活動管理員 +Icon=preferences-activities +Type=Service + +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/main.qml + +X-Plasma-Requires-FileDialog=Unused +X-Plasma-Requires-LaunchApp=Unused + +X-KDE-PluginInfo-Author=Gregor Tätzner +X-KDE-PluginInfo-Email=plasma-devel@kde.org +X-KDE-PluginInfo-Website=http://plasma.kde.org/ +X-KDE-PluginInfo-Category=Windows and Tasks +X-KDE-PluginInfo-Name=org.kde.plasma.showActivityManager +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true + +X-KDE-ServiceTypes=Plasma/Applet diff --git a/applets/taskmanager/CMakeLists.txt b/applets/taskmanager/CMakeLists.txt new file mode 100644 index 0000000000..408d8a5bb7 --- /dev/null +++ b/applets/taskmanager/CMakeLists.txt @@ -0,0 +1,26 @@ +plasma_install_package(package org.kde.plasma.taskmanager) + +set(taskmanagerplugin_SRCS + plugin/backend.cpp + plugin/draghelper.cpp + plugin/taskmanagerplugin.cpp + plugin/textlabel.cpp +) + +install(FILES plugin/qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/taskmanager) + +add_library(taskmanagerplugin SHARED ${taskmanagerplugin_SRCS}) + +# FIXME TODO HACK: The last two are temp, see comment in Backend::activateItem(). +target_link_libraries(taskmanagerplugin + PW::LibTaskManager + Qt5::Core + Qt5::Qml + Qt5::Quick + Qt5::Widgets + KF5::KIOCore + KF5::WindowSystem + Qt5::X11Extras + ${X11_LIBRARIES}) + +install(TARGETS taskmanagerplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/taskmanager) diff --git a/applets/taskmanager/Messages.sh b/applets/taskmanager/Messages.sh new file mode 100644 index 0000000000..3958567d9f --- /dev/null +++ b/applets/taskmanager/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_tasks.pot +rm -f rc.cpp \ No newline at end of file diff --git a/applets/taskmanager/package/contents/code/layout.js b/applets/taskmanager/package/contents/code/layout.js new file mode 100644 index 0000000000..1e45a0dde4 --- /dev/null +++ b/applets/taskmanager/package/contents/code/layout.js @@ -0,0 +1,172 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +function horizontalMargins() { + return taskFrame.margins.left + taskFrame.margins.right; +} + +function verticalMargins() { + return taskFrame.margins.top + taskFrame.margins.bottom; +} + +function launcherLayoutTasks() { + return Math.round(backend.tasksModel.launcherCount / Math.floor(preferredMinWidth() / launcherWidth())); +} + +function launcherLayoutWidthDiff() { + return (launcherLayoutTasks() * taskWidth()) - (backend.tasksModel.launcherCount * launcherWidth()); +} + +function logicalTaskCount() { + var count = (backend.tasksModel.count - backend.tasksModel.launcherCount) + launcherLayoutTasks(); + + return Math.max(backend.tasksModel.count ? 1 : 0, count); +} + +function maxStripes() { + var length = tasks.vertical ? taskList.width : taskList.height; + var minimum = tasks.vertical ? preferredMinWidth() : preferredMinHeight(); + + return Math.min(plasmoid.configuration.maxStripes, Math.max(1, Math.floor(length / minimum))); +} + +function tasksPerStripe() { + if (plasmoid.configuration.forceStripes) { + return Math.ceil(logicalTaskCount() / maxStripes()); + } else { + var length = tasks.vertical ? taskList.height : taskList.width; + var minimum = tasks.vertical ? preferredMinHeight() : preferredMinWidth(); + + return Math.floor(length / minimum); + } +} + +function calculateStripes() { + var stripes = plasmoid.configuration.forceStripes ? plasmoid.configuration.maxStripes : Math.min(plasmoid.configuration.maxStripes, Math.ceil(logicalTaskCount() / tasksPerStripe())); + + return Math.min(stripes, maxStripes()); +} + +function full() { + return (maxStripes() == calculateStripes()); +} + +function optimumCapacity(width, height) { + var length = tasks.vertical ? height : width - (backend.tasksModel.launcherCount * launcherWidth()); + var maximum = tasks.vertical ? preferredMaxHeight() : preferredMaxWidth(); + + return (Math.ceil(length / maximum) * maxStripes()) + backend.tasksModel.launcherCount; +} + +function layoutWidth() { + if (plasmoid.configuration.forceStripes && !tasks.vertical) { + return Math.min(tasks.width, Math.max(preferredMaxWidth(), tasksPerStripe() * preferredMaxWidth())); + } else { + return tasks.width; + } +} + +function layoutHeight() { + if (plasmoid.configuration.forceStripes && tasks.vertical) { + return Math.min(tasks.height, Math.max(preferredMaxHeight(), tasksPerStripe() * preferredMaxHeight())); + } else { + return tasks.height; + } +} + +function preferredMinWidth() { + if (tasks.vertical) { + return horizontalMargins() + units.iconSizes.small; + } else { + return horizontalMargins() + units.iconSizes.small + 3 + (theme.mSize(theme.defaultFont).width * 12); + } +} + +function preferredMaxWidth() { + return Math.floor(preferredMinWidth() * 1.8); +} + +function preferredMinHeight() { + // TODO FIXME UPSTREAM: Port to proper font metrics for descenders once we have access to them. + return theme.mSize(theme.defaultFont).height + 4; +} + +function preferredMaxHeight() { + return verticalMargins() + Math.min(units.iconSizes.small * 3, theme.mSize(theme.defaultFont).height * 3); +} + +function taskWidth() { + if (tasks.vertical) { + return Math.floor(taskList.width / calculateStripes()); + } else { + if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) { + return Math.floor(taskList.width / Math.ceil(logicalTaskCount() / maxStripes())); + } else { + return Math.min(preferredMaxWidth(), Math.floor(taskList.width / Math.min(logicalTaskCount(), tasksPerStripe()))); + } + } +} + +function taskHeight() { + if (tasks.vertical) { + if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) { + return Math.floor(taskList.height / Math.ceil(logicalTaskCount() / maxStripes())); + } else { + return Math.min(preferredMaxHeight(), Math.floor(taskList.height / Math.min(logicalTaskCount(), tasksPerStripe()))); + } + } else { + return Math.floor(taskList.height / calculateStripes()); + } +} + +function launcherWidth() { + return horizontalMargins() + units.iconSizes.small; +} + +function layout(container) { + var item; + var stripes = calculateStripes(); + var taskCount = backend.tasksModel.count - backend.tasksModel.launcherCount; + var width = taskWidth(); + var adjustedWidth = width; + var height = taskHeight(); + + if (!tasks.vertical && stripes == 1 && taskCount) + { + width = Math.min(width + Math.floor(launcherLayoutWidthDiff() / taskCount), preferredMaxWidth()); + } + + for (var i = 0; i < container.count; ++i) { + item = container.itemAt(i); + item.visible = true; + + adjustedWidth = width; + + if (!tasks.vertical) { + if (item.isLauncher) { + adjustedWidth = launcherWidth(); + } else if (stripes > 1 && i == backend.tasksModel.launcherCount) { + adjustedWidth += launcherLayoutWidthDiff(); + } + } + + item.width = adjustedWidth; + item.height = height; + } +} diff --git a/applets/taskmanager/package/contents/code/tools.js b/applets/taskmanager/package/contents/code/tools.js new file mode 100644 index 0000000000..2ddd75a66e --- /dev/null +++ b/applets/taskmanager/package/contents/code/tools.js @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +function activateNextPrevTask(parentItem, next) { + var taskIdList; + + if (parentItem && parentItem.isGroupParent) { + taskIdList = backend.tasksModel.taskIdList(visualModel.modelIndex(parentItem.itemIndex)); + } else { + taskIdList = backend.tasksModel.taskIdList(); + } + + if (!taskIdList.length) { + return; + } + + var activeTaskId = backend.tasksModel.activeTaskId(); + var target = taskIdList[0]; + + for (var i = 0; i < taskIdList.length; ++i) { + if (taskIdList[i] == activeTaskId) + { + if (next && i < (taskIdList.length - 1)) { + target = taskIdList[i + 1]; + } else if (!next) + { + if (i) { + target = taskIdList[i - 1]; + } else { + target = taskIdList[taskIdList.length - 1]; + } + } + + break; + } + } + + activateItem(target, false); +} + +function insertionIndexAt(sourceIndex, x, y) { + var above = target.childAt(x, y); + + if (above) { + var index = above.itemIndex; + + if (index > sourceIndex) { + ++index; + } + + return index; + } else { + var distance = tasks.vertical ? x : y; + var step = tasks.vertical ? Layout.taskWidth() : Layout.taskHeight(); + var stripe = Math.ceil(distance / step); + + if (stripe == Layout.calculateStripes()) { + return -1; + } else { + return stripe * Layout.tasksPerStripe(); + } + } +} + +function publishIconGeometries(taskItems) { + for (var i = 0; i < taskItems.length - 1; ++i) { + var task = taskItems[i]; + + if (task.isGroupParent) { + var taskIdList = backend.tasksModel.taskIdList(visualModel.modelIndex(task.itemIndex)); + + for (var j = 0; j < taskIdList.length; ++j) { + tasks.itemGeometryChanged(task, taskIdList[j].itemId); + } + } else if (!task.isLauncher) { + tasks.itemGeometryChanged(task, task.itemId); + } + } +} + +function taskPrefix(prefix) { + + var effectivePrefix; + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + effectivePrefix = "west-" + prefix; + break; + case PlasmaCore.Types.TopEdge: + effectivePrefix = "north-" + prefix; + break; + case PlasmaCore.Types.RightEdge: + effectivePrefix = "east-" + prefix; + break; + default: + effectivePrefix = "south-" + prefix; + } + if (!frame.hasElementPrefix(effectivePrefix)) { + return prefix; + } + return effectivePrefix; + +} diff --git a/applets/taskmanager/package/contents/config/config.qml b/applets/taskmanager/package/contents/config/config.qml new file mode 100644 index 0000000000..0776fda9e1 --- /dev/null +++ b/applets/taskmanager/package/contents/config/config.qml @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +import org.kde.plasma.configuration 2.0 + +ConfigModel { + ConfigCategory { + name: "General" + icon: "preferences-system-windows" + source: "ConfigGeneral.qml" + } +} diff --git a/applets/taskmanager/package/contents/config/main.xml b/applets/taskmanager/package/contents/config/main.xml new file mode 100644 index 0000000000..1a8fe8a0a9 --- /dev/null +++ b/applets/taskmanager/package/contents/config/main.xml @@ -0,0 +1,48 @@ + + + + + + + true + + + false + + + true + + + false + + + 2 + + + true + + + 2 + + + 2 + + + false + + + true + + + false + + + + + + + + diff --git a/applets/taskmanager/package/contents/ui/ConfigGeneral.qml b/applets/taskmanager/package/contents/ui/ConfigGeneral.qml new file mode 100644 index 0000000000..c5ef053d83 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/ConfigGeneral.qml @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 as QtLayouts + +QtControls.GroupBox { + width: childrenRect.width + height: childrenRect.height + + flat: true + title: i18n("General") + + property alias cfg_forceStripes: forceStripes.checked + property alias cfg_showToolTips: showToolTips.checked + property alias cfg_highlightWindows: highlightWindows.checked + property alias cfg_maxStripes: maxStripes.value + property alias cfg_groupingStrategy: groupingStrategy.currentIndex + property alias cfg_onlyGroupWhenFull: onlyGroupWhenFull.checked + property alias cfg_sortingStrategy: sortingStrategy.currentIndex + property alias cfg_showOnlyCurrentScreen: showOnlyCurrentScreen.checked + property alias cfg_showOnlyCurrentDesktop: showOnlyCurrentDesktop.checked + property alias cfg_showOnlyCurrentActivity: showOnlyCurrentActivity.checked + property alias cfg_showOnlyMinimized: showOnlyMinimized.checked + + QtLayouts.ColumnLayout { + QtControls.GroupBox { + title: i18n("Appearance") + flat: true + + QtLayouts.ColumnLayout { + QtControls.CheckBox { + id: forceStripes + text: i18n("Force row settings") + } + + QtControls.CheckBox { + id: showToolTips + text: i18n("Show tooltips") + } + + QtControls.CheckBox { + id: highlightWindows + text: i18n("Highlight windows") + } + + QtLayouts.RowLayout { + QtControls.Label { + text: i18n("Maximum rows:") + } + + QtControls.SpinBox { + id: maxStripes + } + } + } + } + + QtControls.GroupBox { + title: i18n("Grouping and Sorting") + flat: true + + QtLayouts.ColumnLayout { + QtLayouts.RowLayout { + QtControls.Label { + text: i18n("Grouping:") + } + + QtControls.ComboBox { + id: groupingStrategy + model: [i18n("Do Not Group"), i18n("Manually"), i18n("By Program Name")] + } + } + + QtControls.CheckBox { + id: onlyGroupWhenFull + text: i18n("Only when the task manager is full") + } + + QtLayouts.RowLayout { + QtControls.Label { + text: i18n("Sorting:") + } + + QtControls.ComboBox { + id: sortingStrategy + model: [i18n("Do Not Sort"), i18n("Manually"), i18n("Alphabetically"), i18n("By Desktop"), i18n("By Activity")] + } + } + } + } + + QtControls.GroupBox { + title: i18n("Filters") + flat: true + + QtLayouts.ColumnLayout { + QtControls.CheckBox { + id: showOnlyCurrentScreen + text: i18n("Show only tasks from the current screen") + } + + QtControls.CheckBox { + id: showOnlyCurrentDesktop + text: i18n("Show only tasks from the current desktop") + } + + QtControls.CheckBox { + id: showOnlyCurrentActivity + text: i18n("Show only tasks from the current activity") + } + + QtControls.CheckBox { + id: showOnlyMinimized + text: i18n("Show only tasks that are minimized") + } + } + } + } +} diff --git a/applets/taskmanager/package/contents/ui/GroupDialog.qml b/applets/taskmanager/package/contents/ui/GroupDialog.qml new file mode 100644 index 0000000000..cf66b8c279 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/GroupDialog.qml @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.draganddrop 2.0 + +import "../code/layout.js" as LayoutManager + +PlasmaCore.Dialog { + visible: false + + type: PlasmaCore.Dialog.PopupMenu + flags: Qt.WindowStaysOnTopHint + hideOnWindowDeactivate: true + location: plasmoid.location + + mainItem: Item { + MouseHandler { + anchors.fill: parent + + id: mouseHandler + + target: taskList + } + + TaskList { + id: taskList + + anchors.fill: parent + + Repeater { + id: groupRepeater + + onCountChanged: updateSize() + } + } + } + + data: [ + VisualDataModel { + id: groupFilter + + delegate: Task { + visible: true + inPopup: true + } + } + ] + + onVisualParentChanged: { + if (!visualParent) { + visible = false; + } + } + + onVisibleChanged: { + if (visible && visualParent) { + groupFilter.model = backend.tasksModel; + groupFilter.rootIndex = groupFilter.modelIndex(visualParent.itemIndex); + groupRepeater.model = groupFilter; + } else { + visualParent = null; + groupRepeater.model = undefined; + groupFilter.model = undefined; + groupFilter.rootIndex = undefined; + } + } + + function updateSize() { + if (!visible || !visualParent) { + return; + } + + if (!groupRepeater.count) { + visible = false; + } else { + var task; + var maxWidth = 0; + + for (var i = 0; i < taskList.children.length - 1; ++i) { + task = taskList.children[i]; + + if (task.textWidth > maxWidth) { + maxWidth = task.textWidth; + } + + task.textWidthChanged.connect(updateSize); + } + + maxWidth += LayoutManager.horizontalMargins() + units.iconSizes.small + 6; + + // TODO: Properly derive limits from work area size (screen size sans struts). + mainItem.width = Math.min(maxWidth, (tasks.vertical ? 640 - tasks.width : Math.max(tasks.width, 640)) - 20); + mainItem.height = groupRepeater.count * (LayoutManager.verticalMargins() + units.iconSizes.small); + } + } +} diff --git a/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml b/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml new file mode 100644 index 0000000000..0c23098344 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/GroupExpanderOverlay.qml @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore + +PlasmaCore.SvgItem { + id: arrow + anchors { + bottom: { + if (plasmoid.location != PlasmaCore.Types.TopEdge && plasmoid.location != PlasmaCore.Types.LeftEdge && plasmoid.location != PlasmaCore.Types.RightEdge) { + return parent.bottom; + } else { + return undefined; + } + } + horizontalCenter: { + if (plasmoid.location != PlasmaCore.Types.LeftEdge && plasmoid.location != PlasmaCore.Types.RightEdge) { + return iconBox.horizontalCenter; + } else { + return undefined; + } + } + verticalCenter: { + if (plasmoid.location == PlasmaCore.Types.LeftEdge || plasmoid.location == PlasmaCore.Types.RightEdge) { + return iconBox.verticalCenter; + } else { + return undefined; + } + } + top: { + if (plasmoid.location == PlasmaCore.Types.TopEdge) { + return parent.top; + } else { + return undefined; + } + } + left: { + if (plasmoid.location == PlasmaCore.Types.LeftEdge) { + return parent.left; + } else { + return undefined; + } + } + right: { + if (plasmoid.location == PlasmaCore.Types.RightEdge) { + return parent.right; + } else { + return undefined; + } + } + } + + implicitWidth: Math.min(units.iconSizes.small, iconBox.width) + implicitHeight: implicitWidth + + svg: arrows + elementId: elementForLocation() + + function elementForLocation() { + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + return "right-arrow"; + case PlasmaCore.Types.TopEdge: + return "down-arrow"; + case PlasmaCore.Types.RightEdge: + return "left-arrow"; + case PlasmaCore.Types.BottomEdge: + default: + return "up-arrow"; + } + } + + Connections { + target: plasmoid.configuration + onLocationChanged: { + arrow.width = arrow.implicitWidth + arrow.height = arrow.implicitHeight + } + } +} diff --git a/applets/taskmanager/package/contents/ui/MouseHandler.qml b/applets/taskmanager/package/contents/ui/MouseHandler.qml new file mode 100644 index 0000000000..124e4c9ba4 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/MouseHandler.qml @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +import org.kde.draganddrop 2.0 +import org.kde.kquickcontrolsaddons 2.0 + +import "../code/layout.js" as LayoutManager +import "../code/tools.js" as TaskTools + +Item { + property Item target + + DropArea { + id: dropHandler + + anchors.fill: parent + + property Item hoveredItem + + onDragMove: { + if (target.animating) { + return; + } + + var above = target.childAt(event.x, event.y); + + // HACK: plasmoid.configuration.sortingStrategy is an integer representation + // of the TaskManager::GroupManager::TaskSortingStrategy enum. + if (tasks.dragSource && plasmoid.configuration.sortingStrategy == 1) { + if (tasks.dragSource != above && !tasks.dragSource.isLauncher + && !(above && "isLauncher" in above && above.isLauncher)) { + itemMove(tasks.dragSource.itemId, + TaskTools.insertionIndexAt(tasks.dragSource.itemIndex, + event.x, event.y)); + } + } else if (!tasks.dragSource && above && hoveredItem != above) { + hoveredItem = above; + activationTimer.restart(); + } else if (!above) { + hoveredItem = null; + activationTimer.stop(); + } + } + + onDragLeave: { + hoveredItem = null; + activationTimer.stop(); + } + + Timer { + id: activationTimer + + interval: 250 + repeat: false + + onTriggered: { + if (parent.hoveredItem.isGroupParent) { + groupDialog.target = parent.hoveredItem; + groupDialog.visible = true; + } else if (!parent.hoveredItem.isLauncher) { + tasks.activateItem(parent.hoveredItem.itemId, false); + } + } + } + } + + MouseEventListener { + id: wheelHandler + + anchors.fill: parent + + onWheelMoved: TaskTools.activateNextPrevTask(false, wheel.delta < 0) + } +} diff --git a/applets/taskmanager/package/contents/ui/Task.qml b/applets/taskmanager/package/contents/ui/Task.qml new file mode 100644 index 0000000000..56a1f05372 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/Task.qml @@ -0,0 +1,340 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.draganddrop 2.0 +import org.kde.kquickcontrolsaddons 2.0 + +import org.kde.plasma.private.taskmanager 0.1 as TaskManager + +import "../code/layout.js" as LayoutManager +import "../code/tools.js" as TaskTools + +MouseEventListener { + id: task + + width: groupDialog.mainItem.width + height: units.iconSizes.small + LayoutManager.verticalMargins() + + visible: false + + LayoutMirroring.enabled: (Qt.application.layoutDirection == Qt.RightToLeft) + LayoutMirroring.childrenInherit: (Qt.application.layoutDirection == Qt.RightToLeft) + + property int itemIndex: index + property int itemId: model.Id + property bool inPopup: false + property bool isGroupParent: model.hasModelChildren + property bool isLauncher: model.IsLauncher + property bool isStartup: model.IsStartup + property bool demandsAttention: model.DemandsAttention + property int textWidth: label.implicitWidth + property bool pressed: false + property int pressX: -1 + property int pressY: -1 + property Item busyIndicator + + acceptedButtons: Qt.LeftButton | Qt.RightButton + hoverEnabled: true + + onItemIndexChanged: { + if (!inPopup && !tasks.vertical && LayoutManager.calculateStripes() > 1) { + var newWidth = LayoutManager.taskWidth(); + + if (index == backend.tasksModel.launcherCount) { + newWidth += LayoutManager.launcherLayoutWidthDiff(); + } + + width = newWidth; + } + } + + onIsStartupChanged: { + if (!isStartup) { + tasks.itemGeometryChanged(itemId, x, y, width, height); + } + } + + onDemandsAttentionChanged: { + tasks.updateStatus(demandsAttention); + } + + onContainsMouseChanged: { + if (!containsMouse) { + pressed = false; + } + + tasks.itemHovered(model.Id, containsMouse); + } + + onPressed: { + if (mouse.buttons & Qt.LeftButton) { + pressed = true; + pressX = mouse.x; + pressY = mouse.y; + } else if (mouse.buttons & Qt.RightButton) { + if (plasmoid.configuration.showToolTips) { + toolTip.hideToolTip(); + } + + tasks.itemContextMenu(task, plasmoid.action("configure")); + } + } + + onReleased: { + if (pressed) { + if (!mouse.button == Qt.LeftButton) { + return; + } + + if (isGroupParent) { + if (groupDialog.visible) { + groupDialog.visible = false; + } else { + groupDialog.visualParent = task; + groupDialog.visible = true; + } + } else { + tasks.activateItem(model.Id, true); + } + } + + pressed = false; + pressX = -1; + pressY = -1; + } + + onPositionChanged: { + if (pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { + tasks.dragSource = task; + dragHelper.startDrag(task, model.MimeType, model.MimeData, + model.LauncherUrl, model.DecorationRole); + pressX = -1; + pressY = -1; + + return; + } + } + + onWheelMoved: TaskTools.activateNextPrevTask(task, wheel.delta < 0) + + PlasmaCore.FrameSvgItem { + id: frame + + anchors.fill: parent + + imagePath: "widgets/tasks" + prefix: TaskTools.taskPrefix("normal") + + PlasmaCore.ToolTipArea { + id: toolTip + + anchors.fill: parent + + property variant windows: model.WindowList + + active: !inPopup && plasmoid.configuration.showToolTips + interactive: true + location: plasmoid.location + + mainItem: toolTipDelegate + + //FIXME TODO: highlightWindows: plasmoid.configuration.highlightWindows + onContainsMouseChanged: { + if (containsMouse) { + toolTip.windows = model.WindowList; + toolTip.mainText = model.DisplayRole; + toolTip.icon = model.DecorationRole; + toolTip.subText = model.IsLauncher ? model.GenericName + : toolTip.generateSubText(model); + } + } + + function generateSubText(task) { + var subTextEntries = new Array(); + + if (!plasmoid.configuration.showOnlyCurrentDesktop) { + subTextEntries.push(i18n("On %1", task.DesktopName)); + } + + if (task.OnAllActivities) { + subTextEntries.push(i18nc("Which virtual desktop a window is currently on", + "Available on all activities")); + } else if (plasmoid.configuration.showOnlyCurrentActivity) { + if (task.OtherActivityNames.length > 0) { + subTextEntries.push(i18nc("Activities a window is currently on (apart from the current one)", + "Also available on %1", + task.OtherActivityNames.join(", "))); + } + } else if (task.ActivityNames.length > 0) { + subTextEntries.push(i18nc("Which activities a window is currently on", + "Available on %1", + task.ActivityNames.join(", "))); + } + + return subTextEntries.join("
    "); + } + } + } + + Item { + id: iconBox + + anchors { + left: parent.left + leftMargin: taskFrame.margins.left + verticalCenter: parent.verticalCenter + } + + width: inPopup ? units.iconSizes.small : Math.min(height, parent.width - LayoutManager.horizontalMargins()) + height: Math.min(units.iconSizes.huge, + parent.height - (parent.height - LayoutManager.verticalMargins() < units.iconSizes.small ? + Math.min(9, LayoutManager.verticalMargins()) : LayoutManager.verticalMargins())) + + PlasmaCore.IconItem { + id: icon + + anchors.fill: parent + + visible: !model.IsStartup + + active: task.containsMouse + enabled: !(model.Minimized && !plasmoid.configuration.showOnlyMinimized) + + source: model.DecorationRole + + onVisibleChanged: { + if (visible && busyIndicator) { + busyIndicator.destroy(); + } + } + } + + states: [ + // Using a state transition avoids a binding loop between label.visible and + // the text label margin, which derives from the icon width. + State { + name: "standalone" + when: !label.visible + + AnchorChanges { + target: iconBox + anchors.left: undefined + anchors.horizontalCenter: parent.horizontalCenter + } + + PropertyChanges { + target: iconBox + anchors.leftMargin: 0 + } + } + ] + } + + TaskManager.TextLabel { + id: label + + anchors { + left: parent.left + right: parent.right + leftMargin: taskFrame.margins.left + icon.width + 4 + rightMargin: taskFrame.margins.right + verticalCenter: parent.verticalCenter + } + + height: Math.max(theme.mSize(theme.defaultFont).height, parent.height - taskFrame.margins.top - taskFrame.margins.bottom) + + visible: !model.IsLauncher && (parent.width - anchors.leftMargin - anchors.rightMargin) >= (theme.mSize(theme.defaultFont).width * 3) + + enabled: !model.Minimized + + text: model.DisplayRole + color: theme.textColor + elide: !inPopup + } + + states: [ + State { + name: "launcher" + when: model.IsLauncher + + PropertyChanges { + target: frame + prefix: "" + } + }, + State { + name: "hovered" + when: containsMouse + + PropertyChanges { + target: frame + prefix: TaskTools.taskPrefix("hover"); + } + }, + State { + name: "attention" + when: model.DemandsAttention + + PropertyChanges { + target: frame + prefix: TaskTools.taskPrefix("attention"); + } + }, + State { + name: "minimized" + when: model.Minimized && !(groupDialog.visible && groupDialog.target == task) + + PropertyChanges { + target: frame + prefix: TaskTools.taskPrefix("minimized"); + } + }, + State { + name: "active" + when: model.Active || groupDialog.visible && groupDialog.target == task + + PropertyChanges { + target: frame + prefix: TaskTools.taskPrefix("focus"); + } + } + ] + + Component.onCompleted: { + if (model.IsStartup) { + busyIndicator = Qt.createQmlObject('import org.kde.plasma.components 2.0 as PlasmaComponents; ' + + 'PlasmaComponents.BusyIndicator { anchors.fill: parent; running: true }', iconBox); + } + + if (model.hasModelChildren) { + var component = Qt.createComponent("GroupExpanderOverlay.qml"); + component.createObject(task); + } + } +/* + Component.onDestruction: { + if (groupDialog.visible && groupDialog.groupItemId == model.Id) { + groupDialog.visible = false; + } + } +*/ +} diff --git a/applets/taskmanager/package/contents/ui/TaskList.qml b/applets/taskmanager/package/contents/ui/TaskList.qml new file mode 100644 index 0000000000..5572966709 --- /dev/null +++ b/applets/taskmanager/package/contents/ui/TaskList.qml @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 + +Flow { + property bool animating: false + + layoutDirection: Qt.application.layoutDirection + + property int rows: Math.floor(height / children[0].height) + property int columns: Math.floor(width / children[0].width) + + move: Transition { + SequentialAnimation { + PropertyAction { target: taskList; property: "animating"; value: true } + + NumberAnimation { + properties: "x, y" + easing.type: Easing.OutQuad + } + + PropertyAction { target: taskList; property: "animating"; value: false } + } + } +} diff --git a/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml b/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml new file mode 100644 index 0000000000..1f5cf34acd --- /dev/null +++ b/applets/taskmanager/package/contents/ui/ToolTipDelegate.qml @@ -0,0 +1,111 @@ +/* +* Copyright 2013 by Sebastian Kügler +* Copyright 2014 by Martin Gräßlin +* +* This program 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, 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 Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. +*/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + +Column { + id: tooltipContentItem + + property Item toolTip + + property int preferredTextWidth: theme.mSize(theme.defaultFont).width * 40 + property int _s: units.largeSpacing / 2 + + Layout.minimumWidth: childrenRect.width + _s + Layout.minimumHeight: childrenRect.height + units.largeSpacing + Layout.maximumWidth: childrenRect.width + _s + Layout.maximumHeight: childrenRect.height + units.largeSpacing + width: childrenRect.width + _s + height: childrenRect.height + units.largeSpacing + spacing: units.largeSpacing + + Row { + anchors.horizontalCenter: parent.horizontalCenter + width: childrenRect.width + height: childrenRect.height + spacing: units.largeSpacing + Repeater { + model: toolTip.windows + PlasmaCore.WindowThumbnail { + // hardcoded values from old implementation + width: 200 + height: 150 + winId: modelData + } + } + } + + Row { + width: childrenRect.width + _s + height: childrenRect.height + units.largeSpacing + spacing: units.largeSpacing + + Item { + id: imageContainer + visible: toolTip != null && toolTip.icon != null + width: tooltipIcon.width + height: tooltipIcon.height + x: _s + y: _s + + PlasmaCore.IconItem { + id: tooltipIcon + x: _s + width: toolTip != undefined && toolTip.icon != null ? units.iconSizes.desktop : 0 + height: width + source: toolTip != undefined && toolTip.icon != null ? toolTip.icon : "" + } + } + + Column { + id: mainColumn + x: _s + y: _s + + //This instance is purely for metrics + PlasmaExtras.Heading { + id: tooltipMaintextPlaceholder + visible: false + level: 3 + text: toolTip ? toolTip.mainText : "" + } + PlasmaExtras.Heading { + id: tooltipMaintext + level: 3 + width: Math.min(tooltipMaintextPlaceholder.width, preferredTextWidth) + //width: 400 + elide: Text.ElideRight + text: toolTip ? toolTip.mainText : "" + } + PlasmaComponents.Label { + id: tooltipSubtext + width: tooltipContentItem.preferredTextWidth + wrapMode: Text.WordWrap + text: toolTip ? toolTip.subText : "" + opacity: 0.5 + } + } + } +} diff --git a/applets/taskmanager/package/contents/ui/main.qml b/applets/taskmanager/package/contents/ui/main.qml new file mode 100644 index 0000000000..229c3dfc2b --- /dev/null +++ b/applets/taskmanager/package/contents/ui/main.qml @@ -0,0 +1,236 @@ +/*************************************************************************** + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.plasmoid 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore + +import org.kde.plasma.private.taskmanager 0.1 as TaskManager + +import "../code/layout.js" as LayoutManager +import "../code/tools.js" as TaskTools + +Item { + id: tasks + + anchors.fill: parent + + property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical) + + Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation + + Layout.fillWidth: true + Layout.fillHeight:true + Layout.minimumWidth: tasks.vertical ? 0 : LayoutManager.preferredMinWidth() + Layout.minimumHeight: !tasks.vertical ? 0 : LayoutManager.preferredMinHeight() + +//BEGIN TODO: this is not precise enough: launchers are smaller than full tasks + Layout.preferredWidth: tasks.vertical ? units.gridUnit * 10 : Math.min(taskList.columns, taskList.children.length) * units.gridUnit * 10; + Layout.preferredHeight: tasks.vertical ? Math.min(taskList.rows, taskList.children.length) * units.gridUnit * 2 : units.gridUnit * 2; +//END TODO + + property Item dragSource: null + + signal activateItem(int id, bool toggle) + signal itemContextMenu(Item item, QtObject configAction) + signal itemHovered(int id, bool hovered) + signal itemMove(int id, int newIndex) + signal itemGeometryChanged(Item item, int id) + + onWidthChanged: { + taskList.width = LayoutManager.layoutWidth(); + + if (plasmoid.configuration.forceStripes) { + taskList.height = LayoutManager.layoutHeight(); + } + } + + onHeightChanged: { + if (plasmoid.configuration.forceStripes) { + taskList.width = LayoutManager.layoutWidth(); + } + + taskList.height = LayoutManager.layoutHeight(); + } + + TaskManager.Backend { + id: backend + + taskManagerItem: tasks + highlightWindows: plasmoid.configuration.highlightWindows + + groupingStrategy: plasmoid.configuration.groupingStrategy + sortingStrategy: plasmoid.configuration.sortingStrategy + + onLaunchersChanged: plasmoid.configuration.launchers = launchers + + Component.onCompleted: { + launchers = plasmoid.configuration.launchers; + } + } + + Connections { + target: plasmoid.configuration + onLaunchersChanged: backend.launchers = plasmoid.configuration.launchers + } + + Binding { + target: backend.groupManager + property: "screen" + value: plasmoid.screen + } + + Binding { + target: backend.groupManager + property: "onlyGroupWhenFull" + value: plasmoid.configuration.onlyGroupWhenFull + } + + Binding { + target: backend.groupManager + property: "fullLimit" + value: LayoutManager.optimumCapacity(width, height) + 1 + } + + Binding { + target: backend.groupManager + property: "showOnlyCurrentScreen" + value: plasmoid.configuration.showOnlyCurrentScreen + } + + Binding { + target: backend.groupManager + property: "showOnlyCurrentDesktop" + value: plasmoid.configuration.showOnlyCurrentDesktop + } + + Binding { + target: backend.groupManager + property: "showOnlyCurrentActivity" + value: plasmoid.configuration.showOnlyCurrentActivity + } + + Binding { + target: backend.groupManager + property: "showOnlyMinimized" + value: plasmoid.configuration.showOnlyMinimized + } + + TaskManager.DragHelper { id: dragHelper } + + PlasmaCore.FrameSvgItem { + id: taskFrame + + visible: false; + + imagePath: "widgets/tasks"; + prefix: "normal" + } + + PlasmaCore.Svg { + id: arrows + + imagePath: "widgets/arrows" + size: "16x16" + } + + MouseHandler { + id: mouseHandler + + anchors.fill: parent + + target: taskList + } + + VisualDataModel { + id: visualModel + + model: backend.tasksModel + delegate: Task {} + } + + ToolTipDelegate { + id: toolTipDelegate + } + + TaskList { + id: taskList + + anchors { + left: parent.left + top: parent.top + } + + onWidthChanged: LayoutManager.layout(taskRepeater) + onHeightChanged: LayoutManager.layout(taskRepeater) + + flow: tasks.vertical ? Flow.TopToBottom : Flow.LeftToRight + + onAnimatingChanged: { + if (!animating) { + TaskTools.publishIconGeometries(children); + } + } + + Repeater { + id: taskRepeater + + model: visualModel + + onCountChanged: { + taskList.width = LayoutManager.layoutWidth(); + taskList.height = LayoutManager.layoutHeight(); + LayoutManager.layout(taskRepeater); + } + + function modelWasReset() { + LayoutManager.layout(taskRepeater); + } + + Component.onCompleted: { + backend.tasksModel.modelReset.connect(modelWasReset); + } + } + } + + GroupDialog { id: groupDialog } + + function updateStatus(demandsAttention) { + if (demandsAttention) { + plasmoid.status = PlasmaCore.Types.NeedsAttentionStatus; + } else if (!backend.anyTaskNeedsAttention) { + plasmoid.status = PlasmaCore.Types.PassiveStatus; + } + } + + function resetDragSource() { + dragSource = null; + } + + Component.onCompleted: { + tasks.activateItem.connect(backend.activateItem); + tasks.itemContextMenu.connect(backend.itemContextMenu); + tasks.itemHovered.connect(backend.itemHovered); + tasks.itemMove.connect(backend.itemMove); + tasks.itemGeometryChanged.connect(backend.itemGeometryChanged); + dragHelper.dropped.connect(resetDragSource); + } +} diff --git a/applets/taskmanager/package/metadata.desktop b/applets/taskmanager/package/metadata.desktop new file mode 100644 index 0000000000..35fe84ab89 --- /dev/null +++ b/applets/taskmanager/package/metadata.desktop @@ -0,0 +1,172 @@ +[Desktop Entry] +Name=Task Manager +Name[af]=Taakbestuurder +Name[ar]=مدير المهام +Name[ast]=Xestor de xeres +Name[be]=Кіраванне заданнямі +Name[be@latin]=Kiraŭnik zadańniaŭ +Name[bg]=Управление на задачи +Name[bn]=টাস্ক ম্যানেজার +Name[bs]=menadžer zadataka +Name[ca]=Gestor de tasques +Name[ca@valencia]=Gestor de tasques +Name[cs]=Správce úloh +Name[csb]=Menedżer dzejaniów +Name[da]=Opgavelinje +Name[de]=Fensterleiste +Name[el]=Διαχειριστής εργασιών +Name[en_GB]=Task Manager +Name[eo]=Taskadministrilo +Name[es]=Gestor de tareas +Name[et]=Tegumihaldur +Name[eu]=Ataza-kudeatzailea +Name[fi]=Tehtävienhallinta +Name[fr]=Gestionnaire de tâches +Name[fy]=Taakbehearder +Name[ga]=Bainisteoir na dTascanna +Name[gl]=Xestor de tarefas +Name[gu]=ટાસ્ક વ્યવસ્થાપક +Name[he]=מנהל משימות +Name[hi]=कार्य प्रबंधक +Name[hne]=काम प्रबंधक +Name[hr]=Upravljanje zadacima +Name[hsb]=Rjadowar nadawkow +Name[hu]=Feladatkezelő +Name[ia]=Gerente de carga +Name[id]=Manajer Tugas +Name[is]=Verkefnastjóri +Name[it]=Gestore dei processi +Name[ja]=タスクマネージャ +Name[kk]=Тапсырмалар менеджері +Name[km]=កម្មវិធី​គ្រប់គ្រង​ភារកិច្ច +Name[kn]=ಕಾರ್ಯ ವ್ಯವಸ್ಥಾಪಕ (ಟಾಸ್ಕ್ ಮ್ಯಾನೇಜರ್) +Name[ko]=작업 관리자 +Name[lt]=Užduočių tvarkyklė +Name[lv]=Uzdevumu pārvaldnieks +Name[mk]=Менаџер на апликации +Name[ml]=ടാസ്ക് മാനേജര്‍ +Name[mr]=कार्य व्यवस्थापक +Name[nb]=Oppgavebehandler +Name[nds]=Opgavenpleger +Name[ne]=कार्य प्रबन्धक +Name[nl]=Takenbeheer +Name[nn]=Oppgåvehandsamar +Name[or]=କାର୍ଯ୍ୟ ପରିଚାଳକ +Name[pa]=ਟਾਸਕ ਮੈਨੇਜਰ +Name[pl]=Zarządzanie zadaniami +Name[pt]=Gestor de Tarefas +Name[pt_BR]=Gerenciador de tarefas +Name[ro]=Gestionar de sarcini +Name[ru]=Панель задач +Name[se]=Bargogieđahalli +Name[si]=කාර්‍යය කළමණාකරු +Name[sk]=Správca úloh +Name[sl]=Upravljalnik opravil +Name[sr]=менаџер задатака +Name[sr@ijekavian]=менаџер задатака +Name[sr@ijekavianlatin]=menadžer zadataka +Name[sr@latin]=menadžer zadataka +Name[sv]=Aktivitetshanterare +Name[ta]=பணி மேலாளர் +Name[te]=కర్తవ్య నిర్వాహకి +Name[tg]=Мудири вазифаҳо +Name[th]=จัดการงาน +Name[tr]=Görev Yöneticisi +Name[ug]=ۋەزىپە باشقۇرغۇچ +Name[uk]=Менеджер задач +Name[uz]=Vazifa boshqaruvchisi +Name[uz@cyrillic]=Вазифа бошқарувчиси +Name[wa]=Manaedjeu des bouyes +Name[x-test]=xxTask Managerxx +Name[zh_CN]=任务管理器 +Name[zh_TW]=工作管理員 +Comment=Switch between running applications +Comment[ar]=بدّل بين التطبيقات التي تعمل +Comment[ast]=Camudar ente aplicaciones n'execución +Comment[be@latin]=Pieraklučeńnie dziejnych aplikacyjaŭ +Comment[bg]=Превключване между стартирани програми +Comment[bs]=Prebacujte između programa u radu +Comment[ca]=Commuta entre aplicacions en execució +Comment[ca@valencia]=Commuta entre aplicacions en execució +Comment[cs]=Přepínač mezi běžícími aplikacemi +Comment[da]=Skift mellem kørende programmer +Comment[de]=Ermöglicht den wechselnden Zugriff auf laufende Programme. +Comment[el]=Εναλλαγή μεταξύ εκτελούμενων εφαρμογών +Comment[en_GB]=Switch between running applications +Comment[eo]=Komuti inter funkciantaj aplikaĵoj +Comment[es]=Cambiar entre aplicaciones en ejecución +Comment[et]=Lülitumine töötavate rakenduste vahel +Comment[eu]=Aldatu abian dauden aplikazio batetik bestera +Comment[fi]=Vaihda avoinna olevien ohjelmien välillä +Comment[fr]=Passe d'une application à l'autre +Comment[fy]=Wikselje tusken rinnende programma's +Comment[ga]=Athraigh idir feidhmchláir atá ag rith +Comment[gl]=Troca entre programas en execución +Comment[gu]=ચાલતાં કાર્યક્રમો વચ્ચે ફેરબદલી કરો +Comment[he]=מעבר בין יישומים פעילים +Comment[hi]=चल रहे अनुप्रयोगों के बीच स्विच करें +Comment[hne]=चलत अनुपरयोग मं स्विच करव +Comment[hr]=Promjena među pokrenutim aplikacijama +Comment[hsb]=Šaltuje mjez běžacymi aplikacijemi +Comment[hu]=A futó alkalmazások között lehet vele váltani +Comment[ia]=Commuta inter applicationes que on exeque +Comment[id]=Berpindah di antara aplikasi yang berjalan +Comment[is]=Skipta á milli forrita sem eru í gangi +Comment[it]=Passa ad altre applicazioni in esecuzione +Comment[ja]=実行中のアプリケーションを切り替えます +Comment[kk]=Жегілген қолданбаларды ақтару +Comment[km]=ប្ដូរ​រវាង​កម្មវិធី​ដែល​កំពុង​រត់ +Comment[kn]=ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅನ್ವಯಗಳ ನಡುವೆ ಅಂತರಿಸು +Comment[ko]=실행 중인 프로그램을 전환합니다 +Comment[lt]=Perjungimas tarp veikiančių programų +Comment[lv]=Pārslēdzas starp palaistajām programmām +Comment[mk]=Движете се низ активните апликации +Comment[ml]=പ്രവര്‍ത്തിക്കുന്ന പ്രവര്‍ത്തങ്ങള്‍ തമ്മില്‍ മാറുക +Comment[mr]=कार्यरत अनुप्रयोग अंतर्गत बदल करा +Comment[nb]=Bytt mellom kjørende programmer +Comment[nds]=Twischen lopen Programmen wesseln +Comment[nl]=Schakel tussen draaiende programma's +Comment[nn]=Byt mellom program som køyrer +Comment[or]=ଚାଲୁଥିବା ପ୍ରୟୋଗଗୁଡ଼ିକ ମଧ୍ଯରେ ଅଦଳ ବଦଳ କରନ୍ତୁ +Comment[pa]=ਚੱਲਦੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਬਦਲੋ +Comment[pl]=Przełączanie między działającymi programami +Comment[pt]=Mudar de aplicações em execução +Comment[pt_BR]=Alterna entre os aplicativos em execução +Comment[ro]=Comută printre aplicațiile ce rulează +Comment[ru]=Переключение между запущенными приложениями +Comment[si]=ක්‍රියාත්මක වන යෙදුම් අතරේ මාරුවන්න +Comment[sk]=Prepínanie medzi bežiacimi aplikáciami +Comment[sl]=Preklapljajte med zagnanimi programi +Comment[sr]=Пребацујте између програма у раду +Comment[sr@ijekavian]=Пребацујте између програма у раду +Comment[sr@ijekavianlatin]=Prebacujte između programa u radu +Comment[sr@latin]=Prebacujte između programa u radu +Comment[sv]=Byt mellan program som kör +Comment[ta]=Switch between running applications +Comment[te]=నడుస్తున్న అనువర్తనముల మద్యన మారుము +Comment[tg]=Переключение между рабочими столами +Comment[th]=สลับการทำงานระหว่างโปรแกรมต่าง ๆ +Comment[tr]=Çalışan uygulamalar arasında gezin +Comment[ug]=ئىجرا بولۇۋاتقان پروگراممىلارنى ئالماشتۇر +Comment[uk]=Перемкніть запущені програми +Comment[wa]=Passer d' on programe ovrant a èn ôte +Comment[x-test]=xxSwitch between running applicationsxx +Comment[zh_CN]=在已运行的程序间切换 +Comment[zh_TW]=在執行中的應用程式間切換 +Type=Service +Icon=preferences-system-windows +X-KDE-ServiceTypes=Plasma/Applet + +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/main.qml + + +X-KDE-PluginInfo-Author=Eike Hein +X-KDE-PluginInfo-Email=hein@kde.org +X-KDE-PluginInfo-Name=org.kde.plasma.taskmanager +X-KDE-PluginInfo-Version=3.0 +X-KDE-PluginInfo-Website=http://userbase.kde.org/Plasma/Tasks +X-KDE-PluginInfo-Category=Windows and Tasks +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL v2+ +X-KDE-PluginInfo-EnabledByDefault=true diff --git a/applets/taskmanager/plugin/backend.cpp b/applets/taskmanager/plugin/backend.cpp new file mode 100644 index 0000000000..7d8d47c6c4 --- /dev/null +++ b/applets/taskmanager/plugin/backend.cpp @@ -0,0 +1,272 @@ +/*************************************************************************** + * Copyright (C) 2007 by Robert Knight * + * Copyright (C) 2008 by Alexis Ménard * + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "backend.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +//FIXME TODO HACK See comment in Backend::activateItem(). +#include +#include + +#include +#include + +Backend::Backend(QObject* parent) : QObject(parent), + m_groupManager(new TaskManager::GroupManager(this)), + m_tasksModel(new TaskManager::TasksModel(m_groupManager, this)), + m_lastWindowId(0), + m_highlightWindows(false) +{ + connect(m_groupManager, SIGNAL(launcherListChanged()), this, SLOT(updateLaunchersCache())); +} + +Backend::~Backend() +{ +} + +TaskManager::GroupManager* Backend::groupManager() const +{ + return m_groupManager; +} + +TaskManager::TasksModel* Backend::tasksModel() const +{ + return m_tasksModel; +} + +QQuickItem* Backend::taskManagerItem() const +{ + return m_taskManagerItem; +} + +void Backend::setTaskManagerItem(QQuickItem* item) +{ + if (item != m_taskManagerItem) { + m_taskManagerItem = item; + emit taskManagerItemChanged(item); + } +} + +bool Backend::anyTaskNeedsAttention() const +{ + return groupManager()->rootGroup()->demandsAttention(); +} + +bool Backend::highlightWindows() const +{ + return m_highlightWindows; +} + +void Backend::setHighlightWindows(bool highlight) +{ + if (highlight != m_highlightWindows) { + m_highlightWindows = highlight; + emit highlightWindowsChanged(highlight); + } +} + +int Backend::groupingStrategy() const +{ + return m_groupManager->groupingStrategy(); +} + +void Backend::setGroupingStrategy(int groupingStrategy) +{ + // FIXME TODO: This is fucking terrible. + m_groupManager->setGroupingStrategy(static_cast(groupingStrategy)); +} + +int Backend::sortingStrategy() const +{ + return m_groupManager->sortingStrategy(); +} + +void Backend::setSortingStrategy(int sortingStrategy) +{ + // FIXME TODO: This is fucking terrible. + m_groupManager->setSortingStrategy(static_cast(sortingStrategy)); +} + +void Backend::updateLaunchersCache() +{ + const QList launcherList = m_groupManager->launcherList(); + + QStringList launchers; + + foreach(const QUrl& launcher, launcherList) { + launchers.append(launcher.toString()); + } + + QString joined(launchers.join(',')); + + if (joined != m_launchers) { + m_launchers = joined; + emit launchersChanged(); + } +} + +QString Backend::launchers() const +{ + return m_launchers; +} + +void Backend::setLaunchers(const QString& launchers) +{ + if (launchers == m_launchers) { + return; + } + + m_launchers = launchers; + + QList launcherList; + + foreach(const QString& launcher, launchers.split(',')) { + launcherList.append(launcher); + } + + disconnect(m_groupManager, SIGNAL(launcherListChanged()), this, SLOT(updateLaunchersCache())); + m_groupManager->setLauncherList(launcherList); + connect(m_groupManager, SIGNAL(launcherListChanged()), this, SLOT(updateLaunchersCache())); + + emit launchersChanged(); +} + +void Backend::activateItem(int id, bool toggle) +{ + TaskManager::AbstractGroupableItem* item = m_groupManager->rootGroup()->getMemberById(id); + + if (!item) { + return; + } + + if (item->itemType() == TaskManager::TaskItemType && !item->isStartupItem()) { + TaskManager::TaskItem* taskItem = static_cast(item); + + if (toggle) { + taskItem->task()->activateRaiseOrIconify(); + } else { + taskItem->task()->activate(); + } + + //FIXME TODO HACK This papers over XSendEvent() calls lacking an explicit flush in + //KWindowSystem; not addressed there due to pending xcb port. + XFlush(QX11Info::display()); + } else if (item->itemType() == TaskManager::LauncherItemType) { + static_cast(item)->launch(); + } +} + + +void Backend::itemContextMenu(QQuickItem *item, QObject *configAction) +{ + TaskManager::AbstractGroupableItem* agItem = m_groupManager->rootGroup()->getMemberById(item->property("itemId").toInt()); + + if (!KAuthorized::authorizeKAction("kwin_rmb") || !item || !item->window() || !agItem) { + return; + } + + QList actionList; + + QAction *action = static_cast(configAction); + + if (action && action->isEnabled()) { + actionList << action; + } + + TaskManager::BasicMenu* menu = 0; + + if (agItem->itemType() == TaskManager::TaskItemType && !agItem->isStartupItem()) { + TaskManager::TaskItem* taskItem = static_cast(agItem); + menu = new TaskManager::BasicMenu(0, taskItem, m_groupManager, actionList); + } else if (agItem->itemType() == TaskManager::GroupItemType) { + TaskManager::TaskGroup* taskGroup = static_cast(agItem); + const int maxWidth = 0.8 * item->window()->screen()->size().width(); + menu = new TaskManager::BasicMenu(0, taskGroup, m_groupManager, actionList, QList (), maxWidth); + } else if (agItem->itemType() == TaskManager::LauncherItemType) { + menu = new TaskManager::BasicMenu(0, static_cast(agItem), + m_groupManager, actionList); + } + + if (!menu) { + return; + } + + menu->adjustSize(); + + if (!taskManagerItem()->property("vertical").toBool()) { + menu->setMinimumWidth(item->width()); + } + + menu->exec(QCursor::pos()); + menu->deleteLater(); +} + +void Backend::itemHovered(int id, bool hovered) +{ + TaskManager::AbstractGroupableItem* item = m_groupManager->rootGroup()->getMemberById(id); + + if (!item) { + return; + } + + if (hovered && m_highlightWindows && m_taskManagerItem->window()) { + m_lastWindowId = m_taskManagerItem->window()->winId(); + KWindowEffects::highlightWindows(m_lastWindowId, QList::fromSet(item->winIds())); + } else if (m_highlightWindows && m_lastWindowId) { + KWindowEffects::highlightWindows(m_lastWindowId, QList()); + } +} + +void Backend::itemMove(int id, int newIndex) +{ + m_groupManager->manualSortingRequest(m_groupManager->rootGroup()->getMemberById(id), newIndex); +} + +void Backend::itemGeometryChanged(QQuickItem *item, int id) +{ + TaskManager:: AbstractGroupableItem *agItem = m_groupManager->rootGroup()->getMemberById(id); + + if (!item || !item->window() || !agItem || agItem->itemType() != TaskManager::TaskItemType) + { + return; + } + + TaskManager::TaskItem *taskItem = static_cast(agItem); + + if (!taskItem->task()) { + return; + } + + QRect iconRect(item->x(), item->y(), item->width(), item->height()); + iconRect.moveTopLeft(item->parentItem()->mapToScene(iconRect.topLeft()).toPoint()); + iconRect.moveTopLeft(item->window()->mapToGlobal(iconRect.topLeft())); + + taskItem->task()->publishIconGeometry(iconRect); +} diff --git a/applets/taskmanager/plugin/backend.h b/applets/taskmanager/plugin/backend.h new file mode 100644 index 0000000000..b1a4f5f812 --- /dev/null +++ b/applets/taskmanager/plugin/backend.h @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 BACKEND_H +#define BACKEND_H + +#include + +#include +#include + +class QQuickItem; + +class Backend : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QObject* groupManager READ groupManager CONSTANT) + Q_PROPERTY(QObject* tasksModel READ tasksModel CONSTANT) + Q_PROPERTY(QQuickItem* taskManagerItem READ taskManagerItem WRITE setTaskManagerItem NOTIFY taskManagerItemChanged) + Q_PROPERTY(bool anyTaskNeedsAttention READ anyTaskNeedsAttention) + Q_PROPERTY(bool highlightWindows READ highlightWindows WRITE setHighlightWindows NOTIFY highlightWindowsChanged) + Q_PROPERTY(int groupingStrategy READ groupingStrategy WRITE setGroupingStrategy) + Q_PROPERTY(int sortingStrategy READ sortingStrategy WRITE setSortingStrategy) + Q_PROPERTY(QString launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged) + + public: + Backend(QObject *parent = 0); + ~Backend(); + + TaskManager::GroupManager *groupManager() const; + TaskManager::TasksModel *tasksModel() const; + + QQuickItem* taskManagerItem() const; + void setTaskManagerItem(QQuickItem *item); + + bool anyTaskNeedsAttention() const; + + bool highlightWindows() const; + void setHighlightWindows(bool highlight); + + int groupingStrategy() const; + void setGroupingStrategy(int groupingStrategy); + + int sortingStrategy() const; + void setSortingStrategy(int sortingStrategy); + + QString launchers() const; + void setLaunchers(const QString& launchers); + + public Q_SLOTS: + void activateItem(int id, bool toggle); + void itemContextMenu(QQuickItem *item, QObject *configAction); + void itemHovered(int id, bool hovered); + void itemMove(int id, int newIndex); + void itemGeometryChanged(QQuickItem *item, int id); + + private Q_SLOTS: + void updateLaunchersCache(); + + Q_SIGNALS: + void taskManagerItemChanged(QQuickItem*); + void highlightWindowsChanged(bool); + void launchersChanged(); + + private: + TaskManager::GroupManager *m_groupManager; + TaskManager::TasksModel *m_tasksModel; + QQuickItem* m_taskManagerItem; + WId m_lastWindowId; + bool m_highlightWindows; + QString m_launchers; +}; + +#endif diff --git a/applets/taskmanager/plugin/blur.cpp b/applets/taskmanager/plugin/blur.cpp new file mode 100644 index 0000000000..7135e9cacb --- /dev/null +++ b/applets/taskmanager/plugin/blur.cpp @@ -0,0 +1,154 @@ +#ifndef BLUR_CPP +#define BLUR_CPP + +/* + * Copyright 2007 Jani Huhtanen + * + * This program 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 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 Library 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 + +// Exponential blur, Jani Huhtanen, 2006 +// +template +static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha); + +template +static inline void blurrow(QImage &im, int line, int alpha); + +template +static inline void blurcol(QImage &im, int col, int alpha); + +/* +* expblur(QImage &img, int radius) +* +* In-place blur of image 'img' with kernel +* of approximate radius 'radius'. +* +* Blurs with two sided exponential impulse +* response. +* +* aprec = precision of alpha parameter +* in fixed-point format 0.aprec +* +* zprec = precision of state parameters +* zR,zG,zB and zA in fp format 8.zprec +*/ +template +void expblur(QImage &img, int radius) +{ + if (radius < 1) { + return; + } + + img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + /* Calculate the alpha such that 90% of + the kernel is within the radius. + (Kernel extends to infinity) + */ + int alpha = (int)((1 << aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f)))); + + int height = img.height(); + int width = img.width(); + for (int row=0; row(img, row, alpha); + } + + for (int col=0; col(img, col, alpha); + } + return; +} + +template +static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha) +{ + int R, G, B, A; + R = *bptr; + G = *(bptr + 1); + B = *(bptr + 2); + A = *(bptr + 3); + + zR += (alpha * ((R << zprec) - zR)) >> aprec; + zG += (alpha * ((G << zprec) - zG)) >> aprec; + zB += (alpha * ((B << zprec) - zB)) >> aprec; + zA += (alpha * ((A << zprec) - zA)) >> aprec; + + *bptr = zR >> zprec; + *(bptr+1) = zG >> zprec; + *(bptr+2) = zB >> zprec; + *(bptr+3) = zA >> zprec; +} + +template +static inline void blurrow(QImage &im, int line, int alpha) +{ + int zR, zG, zB, zA; + + QRgb *ptr = (QRgb *)im.scanLine(line); + int width = im.width(); + + zR = *((unsigned char *)ptr ) << zprec; + zG = *((unsigned char *)ptr + 1) << zprec; + zB = *((unsigned char *)ptr + 2) << zprec; + zA = *((unsigned char *)ptr + 3) << zprec; + + for (int index=1; index((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); + } + for (int index=width-2; index>=0; index--) { + blurinner((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); + } +} + +template +static inline void blurcol(QImage &im, int col, int alpha) +{ + int zR, zG, zB, zA; + + QRgb *ptr = (QRgb *)im.bits(); + ptr += col; + int height = im.height(); + int width = im.width(); + + zR = *((unsigned char *)ptr ) << zprec; + zG = *((unsigned char *)ptr + 1) << zprec; + zB = *((unsigned char *)ptr + 2) << zprec; + zA = *((unsigned char *)ptr + 3) << zprec; + + for (int index=width; index<(height-1)*width; index+=width) { + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); + } + + for (int index=(height-2)*width; index>=0; index-=width) { + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); + } +} + +template +inline const T &qClamp(const T &x, const T &low, const T &high) +{ + if (x < low) { + return low; + } else if (x > high) { + return high; + } else { + return x; + } +} + +#endif diff --git a/applets/taskmanager/plugin/draghelper.cpp b/applets/taskmanager/plugin/draghelper.cpp new file mode 100644 index 0000000000..64f8ca237c --- /dev/null +++ b/applets/taskmanager/plugin/draghelper.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "draghelper.h" + +#include +#include +#include +#include +#include +#include + +DragHelper::DragHelper(QObject* parent) : QObject(parent) +{ +} + +DragHelper::~DragHelper() +{ +} + +bool DragHelper::isDrag(int oldX, int oldY, int newX, int newY) const +{ + return ((QPoint(oldX, oldY) - QPoint(newX, newY)).manhattanLength() >= QApplication::startDragDistance()); +} + +void DragHelper::startDrag(QQuickItem *item, const QString &mimeType, + const QVariant &mimeData, const QUrl &url, const QIcon &icon) const +{ + QList urlList; + urlList.append(url); + + QMimeData *dragData = new QMimeData(); + dragData->setData(mimeType, mimeData.toByteArray()); + dragData->setUrls(urlList); + + QDrag *drag = new QDrag(item); + drag->setMimeData(dragData); + drag->setPixmap(icon.pixmap(QSize(48, 48))); + drag->setHotSpot(QPoint(drag->pixmap().width() / 2, drag->pixmap().height() / 2)); + + drag->exec(); + + emit dropped(); +} + diff --git a/applets/taskmanager/plugin/draghelper.h b/applets/taskmanager/plugin/draghelper.h new file mode 100644 index 0000000000..48e291afd2 --- /dev/null +++ b/applets/taskmanager/plugin/draghelper.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 DRAGHELPER_H +#define DRAGHELPER_H + +#include + +class QIcon; +class QQuickItem; +class QUrl; + +class DragHelper : public QObject +{ + Q_OBJECT + + public: + DragHelper(QObject *parent = 0); + ~DragHelper(); + + Q_INVOKABLE bool isDrag(int oldX, int oldY, int newX, int newY) const; + Q_INVOKABLE void startDrag(QQuickItem* item, const QString &mimeType, + const QVariant &mimeData, const QUrl &url, const QIcon &icon) const; + + Q_SIGNALS: + void dropped() const; +}; + +#endif diff --git a/applets/taskmanager/plugin/qmldir b/applets/taskmanager/plugin/qmldir new file mode 100644 index 0000000000..6bc8b190d9 --- /dev/null +++ b/applets/taskmanager/plugin/qmldir @@ -0,0 +1,2 @@ +module org.kde.plasma.private.taskmanager +plugin taskmanagerplugin diff --git a/applets/taskmanager/plugin/taskmanagerplugin.cpp b/applets/taskmanager/plugin/taskmanagerplugin.cpp new file mode 100644 index 0000000000..8921f83a0b --- /dev/null +++ b/applets/taskmanager/plugin/taskmanagerplugin.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 . * + ***************************************************************************/ + +/* + Copyright (C) 2011 Martin Gräßlin + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 "taskmanagerplugin.h" +#include "backend.h" +#include "draghelper.h" +#include "textlabel.h" + +#include + +void TaskManagerPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.taskmanager")); + qmlRegisterType(uri, 0, 1, "Backend"); + qmlRegisterType(uri, 0, 1, "DragHelper"); + qmlRegisterType(uri, 0, 1, "TextLabel"); +} + +#include "taskmanagerplugin.moc" diff --git a/applets/taskmanager/plugin/taskmanagerplugin.h b/applets/taskmanager/plugin/taskmanagerplugin.h new file mode 100644 index 0000000000..7b7fb0926d --- /dev/null +++ b/applets/taskmanager/plugin/taskmanagerplugin.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright (C) 2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 TASKMANAGERPLUGIN_H +#define TASKMANAGERPLUGIN_H + +#include +#include + +class TaskManagerPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + + public: + virtual void registerTypes(const char *uri); +}; + +#endif // TASKMANAGERPLUGIN_H diff --git a/applets/taskmanager/plugin/textlabel.cpp b/applets/taskmanager/plugin/textlabel.cpp new file mode 100644 index 0000000000..f916384425 --- /dev/null +++ b/applets/taskmanager/plugin/textlabel.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** + * Copyright (C) 2007 Jani Huhtanen * + * Copyright (C) 2007 by Robert Knight * + * Copyright (C) 2008 by Alexis Ménard * + * Copyright (C) 2008 by Marco Martin * + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "textlabel.h" +#include "blur.cpp" + +#include +#include +#include + +TextLabel::TextLabel(QQuickItem* parent) : QQuickPaintedItem(parent), + m_enabled(true), + m_elide(false) +{ +} + +TextLabel::~TextLabel() +{ +} + +bool TextLabel::enabled() const +{ + return m_enabled; +} + +void TextLabel::setEnabled(bool enabled) +{ + if (enabled != m_enabled) { + m_enabled = enabled; + update(); + } +} + +QString TextLabel::text() const +{ + return m_text; +} + +void TextLabel::setText(const QString& text) +{ + if (text != m_text) + { + m_text = text; + m_cachedShadow = QPixmap(); + updateImplicitSize(); + update(); + emit textChanged(text); + } +} + +QColor TextLabel::color() const +{ + return m_color; +} + +void TextLabel::setColor(const QColor& color) +{ + if (color != m_color) + { + m_color = color; + m_cachedShadow = QPixmap(); + update(); + } +} + + +bool TextLabel::elide() const +{ + return m_elide; +} + +void TextLabel::setElide(bool elide) +{ + m_elide = elide; + + updateImplicitSize(); +} + +void TextLabel::updateImplicitSize() +{ + if (m_elide) { + setImplicitWidth(0); + setImplicitHeight(0); + } else { + QFontMetrics fm(QFontDatabase::systemFont(QFontDatabase::GeneralFont)); + + setImplicitWidth(fm.width(m_text)); + setImplicitHeight(fm.height()); + } +} + +void TextLabel::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) +{ + if (newGeometry.size() != oldGeometry.size()) { + m_cachedShadow = QPixmap(); + } +} + +QColor TextLabel::textColor() const +{ + QColor color(m_color); + + if (!m_enabled) { + color.setAlphaF(0.5); + } + + return color; +} + +QTextOption TextLabel::textOption() const +{ + Qt::LayoutDirection direction = QApplication::layoutDirection(); + Qt::Alignment alignment = QStyle::visualAlignment(direction, Qt::AlignLeft | Qt::AlignVCenter); + + QTextOption option; + option.setTextDirection(direction); + option.setAlignment(alignment); + + return option; +} + +void TextLabel::layoutText(QTextLayout &layout, const QString &text, const QSize &constraints) +{ + QFontMetrics metrics(layout.font()); + int leading = metrics.leading(); + int height = 0; + int maxWidth = constraints.width(); + int widthUsed = 0; + int lineSpacing = metrics.lineSpacing(); + QTextLine line; + + layout.setText(text); + + layout.beginLayout(); + while ((line = layout.createLine()).isValid()) { + height += leading; + + // Make the last line that will fit infinitely long. + // drawTextLayout() will handle this by fading the line out + // if it won't fit in the constraints. + if (height + 2 * lineSpacing > constraints.height()) { + line.setPosition(QPoint(0, height)); + break; + } + + line.setLineWidth(maxWidth); + line.setPosition(QPoint(0, height)); + + height += int(line.height()); + widthUsed = int(qMax(qreal(widthUsed), line.naturalTextWidth())); + } + layout.endLayout(); +} + +void TextLabel::drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect) +{ + if (rect.width() < 1 || rect.height() < 1) { + return; + } + + QPixmap pixmap(rect.size()); + pixmap.fill(Qt::transparent); + + QPainter p(&pixmap); + p.setPen(painter->pen()); + + // Create the alpha gradient for the fade out effect + QLinearGradient alphaGradient(0, 0, 1, 0); + alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode); + if (layout.textOption().textDirection() == Qt::LeftToRight) { + alphaGradient.setColorAt(0, QColor(0, 0, 0, 255)); + alphaGradient.setColorAt(1, QColor(0, 0, 0, 0)); + } else { + alphaGradient.setColorAt(0, QColor(0, 0, 0, 0)); + alphaGradient.setColorAt(1, QColor(0, 0, 0, 255)); + } + + QFontMetrics fm(layout.font()); + int textHeight = layout.lineCount() * fm.lineSpacing(); + + QPointF position(0, (rect.height() - textHeight) / 2); + QList fadeRects; + int fadeWidth = 30; + + // Draw each line in the layout + for (int i = 0; i < layout.lineCount(); i++) { + QTextLine line = layout.lineAt(i); + line.draw(&p, position); + + // Add a fade out rect to the list if the line is too long + if (line.naturalTextWidth() > rect.width()) + { + int x = int(qMin(line.naturalTextWidth(), (qreal)pixmap.width())) - fadeWidth; + int y = int(line.position().y() + position.y()); + QRect r = QStyle::visualRect(layout.textOption().textDirection(), pixmap.rect(), + QRect(x, y, fadeWidth, int(line.height()))); + fadeRects.append(r); + } + } + + // Reduce the alpha in each fade out rect using the alpha gradient + if (!fadeRects.isEmpty()) { + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + foreach (const QRect &rect, fadeRects) { + p.fillRect(rect, alphaGradient); + } + } + + p.end(); + + + QColor shadowColor; + if (qGray(textColor().rgb()) > 192) { + shadowColor = Qt::black; + } else { + shadowColor = Qt::white; + } + + if (m_cachedShadow.isNull()) { + QImage shadow = pixmap.toImage(); + expblur<16, 7>(shadow, 1); + QPainter p(&shadow); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(shadow.rect(), shadowColor); + p.end(); + m_cachedShadow = QPixmap(shadow.size()); + m_cachedShadow.fill(Qt::transparent); + QPainter buffPainter(&m_cachedShadow); + buffPainter.drawImage(QPoint(0,0), shadow); + } + + if (shadowColor == Qt::white) { + painter->drawPixmap(rect.topLeft(), m_cachedShadow); + } else { + painter->drawPixmap(rect.topLeft() + QPoint(1, 2), m_cachedShadow); + } + painter->drawPixmap(rect.topLeft(), pixmap); +} + +void TextLabel::paint(QPainter* painter) +{ + painter->setPen(QPen(textColor(), 1.0)); + + if (QFontDatabase::systemFont(QFontDatabase::GeneralFont) != m_layout.font()) { + m_cachedShadow = QPixmap(); + } + + m_layout.setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont)); + m_layout.setTextOption(textOption()); + + layoutText(m_layout, text(), boundingRect().toRect().size()); + drawTextLayout(painter, m_layout, boundingRect().toRect()); +} diff --git a/applets/taskmanager/plugin/textlabel.h b/applets/taskmanager/plugin/textlabel.h new file mode 100644 index 0000000000..f5f6de2b51 --- /dev/null +++ b/applets/taskmanager/plugin/textlabel.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2007 by Robert Knight * + * Copyright (C) 2008 by Alexis Ménard * + * Copyright (C) 2008 by Marco Martin * + * Copyright (C) 2012-2013 by Eike Hein * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 TEXTLABEL_H +#define TEXTLABEL_H + +#include +#include +#include +#include +#include + +class TextLabel : public QQuickPaintedItem +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(bool elide READ elide WRITE setElide) + + public: + TextLabel(QQuickItem *parent = 0); + ~TextLabel(); + + bool enabled() const; + void setEnabled(bool enabled); + + QString text() const; + void setText(const QString& text); + + QColor color() const; + void setColor(const QColor& color); + + bool elide() const; + void setElide(bool elide); + + void paint(QPainter *painter); + + Q_SIGNALS: + void textChanged(const QString& text); + + protected: + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + + private: + void updateImplicitSize(); + QColor textColor() const; + QTextOption textOption() const;; + void layoutText(QTextLayout &layout, const QString &text, const QSize &constraints); + void drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect); + + bool m_enabled; + QString m_text; + QColor m_color; + bool m_elide; + QTextLayout m_layout; + QPixmap m_cachedShadow; +}; + +#endif diff --git a/applets/trash/Messages.sh b/applets/trash/Messages.sh new file mode 100644 index 0000000000..b1303ad54a --- /dev/null +++ b/applets/trash/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_trash.pot +rm -f rc.cpp \ No newline at end of file diff --git a/applets/trash/contents/ui/main.qml b/applets/trash/contents/ui/main.qml new file mode 100644 index 0000000000..d6cb9bcd90 --- /dev/null +++ b/applets/trash/contents/ui/main.qml @@ -0,0 +1,96 @@ +/* + * Copyright 2013 Heena Mahour + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 . + */ +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as Components +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.dirmodel 2.0 + +MouseArea { + id:root + + Layout.minimumWidth: formFactor == PlasmaCore.Types.Horizontal ? height: 1 + Layout.minimumHeight: formFactor == PlasmaCore.Types.Vertical ? width : 1 + property int formFactor: plasmoid.formFactor + property bool constrained: formFactor==PlasmaCore.Types.Vertical||formFactor==PlasmaCore.Types.Horizontal + hoverEnabled: true + onClicked: Qt.openUrlExternally("trash:/"); + + DirModel { + id: dirModel + url: "trash:/" + } + + function action_open() { + Qt.openUrlExternally("trash:/"); + } + + function action_empty() { + queryDialog.open(); + } + + Component.onCompleted: { + plasmoid.backgroundHints = 0; + plasmoid.setAction("open", "Open","document-open"); + plasmoid.setAction("empty","Empty","trash-empty"); + plasmoid.popupIcon = "user-trash"; + } + + PlasmaCore.IconItem { + id:icon + source: (dirModel.count > 0) ? "user-trash-full": "user-trash" + anchors{ + left: parent.left + right: parent.right + top: parent.top + bottom: constrained ? parent.bottom: text.top + } + active: root.containsMouse + } + Components.Label { + id: text + text: (dirModel.count==0) ? i18n("Trash\nEmpty"): i18np("Trash\nOne item", "Trash\n %1 items", dirModel.count); + anchors { + left: parent.left + bottom: parent.bottom + right: parent.right + } + horizontalAlignment: Text.AlignHCenter + opacity: constrained ? 0: 1 + } + PlasmaCore.ToolTipArea { + anchors.fill: parent + mainText: i18n("Trash") + subText: (dirModel.count==0) ? i18n("Trash \n Empty"): i18np("Trash\nOne item", "Trash\n %1 items", dirModel.count ); + image: (dirModel.count > 0) ? "user-trash-full": "user-trash" + } + + + Components.QueryDialog { + id: queryDialog + titleIcon: "user-trash" + titleText: i18n("Empty Trash") + message: i18n("Do you really want to empty the trash ? All the items will be deleted.") + acceptButtonText: i18n("Empty Trash") + rejectButtonText: i18n("Cancel") + onAccepted: plasmoid.runCommand("ktrash", ["--empty"]); + onRejected: queryDialog.close(); + visualParent: root + } +} diff --git a/applets/trash/metadata.desktop b/applets/trash/metadata.desktop new file mode 100644 index 0000000000..ef366301e5 --- /dev/null +++ b/applets/trash/metadata.desktop @@ -0,0 +1,90 @@ +[Desktop Entry] +Name=Trashcan +Name[af]=Gemors +Name[ar]=سلة المهملات +Name[ast]=Papelera +Name[be@latin]=Śmietnica +Name[bg]=Кошче +Name[bn]=আবর্জনা +Name[bs]=korpa za smeće +Name[ca]=Paperera +Name[ca@valencia]=Paperera +Name[csb]=Kòsz +Name[da]=Affald +Name[de]=Papierkorb +Name[el]=Κάδος απορριμμάτων +Name[en_GB]=Wastebin +Name[eo]=Rubujo +Name[es]=Papelera +Name[et]=Prügikast +Name[eu]=Zakarontzia +Name[fi]=Roskakori +Name[fr]=Corbeille +Name[fy]=Jiskefet +Name[ga]=Bruscar +Name[gl]=Lixo +Name[gu]=કચરાપેટી +Name[he]=פח אשפה +Name[hi]=रद्दी की टोकरी +Name[hne]=घुरुवा +Name[hr]=Otpad +Name[hsb]=Papjernik +Name[hu]=Kuka +Name[ia]=Corbe +Name[id]=Tempat Sampah +Name[is]=Ruslafata +Name[it]=Cestino +Name[ja]=ごみ箱 +Name[kk]=Өшірілгендер +Name[km]=ធុង​សំរាម +Name[kn]=ಕಸಬುಟ್ಟಿ +Name[ko]=휴지통 +Name[ku]=Qutiya Sergo +Name[lt]=Šiukšliadėžė +Name[lv]=Miskaste +Name[mk]=Корпа +Name[ml]=ചവറ്റുകുട്ട +Name[mr]=कचरापेटी +Name[nds]=Affalltünn +Name[nl]=Prullenbak +Name[or]=Trashcan +Name[pa]=ਰੱਦੀ-ਟੋਕਰੀ +Name[pl]=Kosz +Name[ro]=Coș de gunoi +Name[ru]=Корзина +Name[si]=ඉවතලන බඳුන +Name[sv]=Papperskorg +Name[ta]=அகற்றிடம் +Name[te]=చెత్తబుట్ట +Name[tg]=Ахлотдон +Name[th]=ถังขยะ +Name[tr]=Çöp Kutusu +Name[ug]=ئەخلەتخانا +Name[uk]=Смітник +Name[uz]=Chiqindilar qutisi +Name[uz@cyrillic]=Чиқиндилар қутиси +Name[wa]=Batch ås mannestés +Name[zh_CN]=回收站 +Name[zh_TW]=資源回收筒 +Type=Service +Icon=user-trash +X-KDE-ServiceTypes=Plasma/Applet +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/main.qml + +X-Plasma-RequiredExtensions=LaunchApp,localio +X-Plasma-OptionalExtensions=LaunchApp +X-Plasma-ConfigPlugins=kcmtrash +X-KDE-Library=plasma_applet_trash +X-KDE-PluginInfo-Author=Heena +X-KDE-PluginInfo-Email=heena393@gmail.com +X-KDE-PluginInfo-Name=org.kde.plasma.trash +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=http://plasma.kde.org/ +X-KDE-PluginInfo-Category=File System +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=Gpl +X-KDE-PluginInfo-EnabledByDefault=true +X-Plasma-Requires-FileDialog=Unused +X-Plasma-Requires-LaunchApp=Required +X-Plasma-Requires-KRun=true diff --git a/applets/window-list/Messages.sh b/applets/window-list/Messages.sh new file mode 100644 index 0000000000..ef7d038057 --- /dev/null +++ b/applets/window-list/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_windowlist.pot +rm -f rc.cpp \ No newline at end of file diff --git a/applets/window-list/contents/ui/Menu.qml b/applets/window-list/contents/ui/Menu.qml new file mode 100644 index 0000000000..acbc3d0402 --- /dev/null +++ b/applets/window-list/contents/ui/Menu.qml @@ -0,0 +1,79 @@ +/* + * Copyright 2013 Heena Mahour + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 . + */ +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + +PlasmaExtras.ScrollArea { + id: menu + + property alias model: menuListView.model + property alias section: menuListView.section + property int iconSize: units.iconSizes.small + property bool showDesktop: true + signal itemSelected(int id) + signal executeJob(string jobName, int id) + signal setOnDesktop(int id, int desktop) + + ListView { + id: menuListView + anchors.top: menu.top + anchors.left: menu.left + anchors.bottom: menu.bottom + focus: true + section.property: desktop + section.criteria: ViewSection.FullString + spacing:0 + + section.delegate: PlasmaComponents.Highlight { + hover: menu.focus + width: menu.width + height: sectionDelegateLabel.height + marginHints.top + marginHints.bottom + + PlasmaComponents.Label { + id: sectionDelegateLabel + text: section > 0 ? i18n("Desktop") + section : i18n("On all desktops") + anchors.centerIn: parent + } + } + + highlight: PlasmaComponents.Highlight { + hover: false + width: menuListView.width + } + + delegate: TaskDelegate { + id: menuItemDelegate + width: menuListView.width + nameLabel: DisplayRole + desktop: Desktop + icon: DecorationRole + active: Active + iconSize: menu.iconSize + showDesktop: menu.showDesktop + onClicked: menu.itemSelected(Id); + onExecuteJob: menu.executeJob(jobName, Id); + onSetOnDesktop: menu.setOnDesktop(Id, desktop); + onActiveChanged: { + if (active) { + menuListView.currentIndex = index + } + } + } + } +} diff --git a/applets/window-list/contents/ui/TaskDelegate.qml b/applets/window-list/contents/ui/TaskDelegate.qml new file mode 100644 index 0000000000..986433e023 --- /dev/null +++ b/applets/window-list/contents/ui/TaskDelegate.qml @@ -0,0 +1,91 @@ +/* + * Copyright 2013 Heena Mahour + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 . + */ +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +Item { + id: menuItem + width: parent.width + height: Math.max(iconItem.height, label.height) + highlightItem.marginHints.top + highlightItem.marginHints.bottom + + signal clicked() + signal entered() + signal executeJob(string jobName) + signal setOnDesktop(int desktop) + property alias nameLabel: label.text + property int desktop + property alias icon: iconItem.source + property alias label: label.text + property bool active: false + property int iconSize: units.iconSizes.small + property bool showDesktop: true + property variant desktopItems: [] + + PlasmaCore.IconItem { + id: iconItem + + width: menuItem.iconSize + height: width + + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: highlightItem.marginHints.left + } + } + + PlasmaComponents.Label { + id: label + + height: implicitHeight + anchors { + left: iconItem.right + leftMargin: highlightItem.marginHints.left + right: parent.right + verticalCenter: parent.verticalCenter + } + + font.italic: (minimized == true) ? true : false + + elide: Text.ElideRight + } + + MouseArea { + id:root_item + anchors.fill: parent + hoverEnabled: true + + onClicked: { + menuItem.clicked(); + } + + onEntered:{ + highlightItem.trackingItem = menuItem + highlightItem.width = menuItem.width + highlightItem.height = menuItem.height + menuItem.entered(); + highlight = true + } + + onExited: { + highlight = false + } + } +} + diff --git a/applets/window-list/contents/ui/main.qml b/applets/window-list/contents/ui/main.qml new file mode 100644 index 0000000000..d2278cfea5 --- /dev/null +++ b/applets/window-list/contents/ui/main.qml @@ -0,0 +1,176 @@ +/* + * Copyright 2013 Heena Mahour + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 . + */ +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + +PlasmaExtras.ConditionalLoader { + Layout.minimumWidth: Math.max(200, item ? item.implicitWidth : 0) + Layout.minimumHeight: Math.max(400, item ? item.implicitHeight : 0) + when: plasmoid.expanded + + source: Component { + MouseArea { + id: main + anchors.fill: parent + implicitWidth: windowListMenu.implicitWidth + implicitHeight: windowListMenu.implicitHeight + property alias data: tasksSource.data; + property variant desktopList: [] + property int iconSize: units.iconSizes.smallMedium + property bool showDesktop: true + property bool highlight: false + + PlasmaComponents.Highlight { + id: highlightItem + + property Item trackingItem + onTrackingItemChanged: { + if (trackingItem) { + y = trackingItem.mapToItem(main, 0, 0).y + } + } + + hover: true + width: windowListMenu.width + x: 0 + y: 0 + height: trackingItem.height + visible: true + opacity: highlight ? 1 : 0 + + Behavior on opacity { + NumberAnimation { + duration: units.longDuration + easing: Easing.InOutQuad + } + } + Behavior on y { + NumberAnimation { + duration: units.longDuration + easing: Easing.InOutQuad + } + } + } + Connections { + target: windowListMenu.flickableItem + onContentYChanged: { + highlightItem.trackingItem = null + } + } + + + function performOperation(op) { + var service =tasksSource.serviceForSource(""); + var operation = service.operationDescription(op); + service.startOperationCall(operation); + } + + function executeJob(operationName, id) { + var service = tasksSource.serviceForSource("tasks"); + var operation = service.operationDescription(operationName); + operation.Id = id; + service.startOperationCall(operation); + } + + function setOnDesktop(id, desktop) { + var service = tasksSource.serviceForSource("tasks"); + var operation = service.operationDescription("toDesktop"); + operation.Id = id; + operation.desktop = desktop; + service.startOperationCall(operation); + } + + Component.onCompleted: { + var toolTipData = new Object; + toolTipData["image"] = "preferences-system-window"; + toolTipData["mainText"] = i18n("Window List"); + toolTipData["subText"] = i18n("Show list of opened windows"); + plasmoid.popupIconToolTip = toolTipData; + plasmoid.popupIcon = QIcon("preferences-system-windows"); + } + + PlasmaCore.DataSource { + id: tasksSource + engine: "tasks" + onSourceAdded: { + connectSource(source); + } + connectedSources: "tasks" + Component.onCompleted: { + print("connected"); + connectSource("virtualDesktops"); + main.desktopList = tasksSource.data["virtualDesktops"]["names"]; + print(models.tasks) + } + } + + PlasmaCore.SortFilterModel { + id: tasksModelSortedByDesktop + sortRole: "desktop" + sourceModel: tasksSource.models.tasks + } + + Column { + id: col + + PlasmaComponents.Highlight { + hover: menu.focus + width: windowListMenu.width + height: actions.height + marginHints.top + marginHints.bottom + PlasmaComponents.Label { + id: actions + text: i18n("Actions") + anchors.centerIn: parent + } + } + + TaskDelegate { + nameLabel: i18n("Unclutter Windows") + onClicked: performOperation("unclutter") + } + + TaskDelegate { + nameLabel : i18n("Cascade Windows") + onClicked: performOperation("cascade") + } + } + + Menu { + id: windowListMenu + anchors { + top: col.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + + model: tasksModelSortedByDesktop + section.property: "desktop" + section.criteria: ViewSection.FullString + iconSize: main.iconSize + showDesktop: main.showDesktop + onItemSelected: main.executeJob("activate", id); + onExecuteJob: main.executeJob(jobName, id); + onSetOnDesktop: main.setOnDesktop(id, desktop); + } + } + } +} diff --git a/applets/window-list/metadata.desktop b/applets/window-list/metadata.desktop new file mode 100644 index 0000000000..9400e8a646 --- /dev/null +++ b/applets/window-list/metadata.desktop @@ -0,0 +1,119 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Window list +Name[bs]=Lista prozora +Name[ca]=Llista de finestres +Name[ca@valencia]=Llista de finestres +Name[cs]=Seznam oken +Name[da]=Vinduesliste +Name[de]=Fensterliste +Name[el]=Λίστα παραθύρων +Name[es]=Lista de ventanas +Name[eu]=Leiho-zerrenda +Name[fi]=Ikkunaluettelo +Name[fr]=Liste des fenêtres +Name[gl]=Lista de xanelas +Name[hu]=Ablaklista +Name[ia]=Lista de fenestra +Name[kk]=Терезе тізімі +Name[ko]=창 목록 +Name[nb]=Vindusliste +Name[nds]=Finsterlist +Name[nl]=Vensterlijst +Name[pa]=ਵਿੰਡੋ ਲਿਸਟ +Name[pl]=Lista okien +Name[pt]=Lista de janelas +Name[pt_BR]=Lista de janelas +Name[ro]=Lista ferestrelor +Name[sk]=Zoznam okien +Name[sl]=Seznam oken +Name[sr]=списак прозора +Name[sr@ijekavian]=списак прозора +Name[sr@ijekavianlatin]=spisak prozora +Name[sr@latin]=spisak prozora +Name[sv]=Fönsterlista +Name[tr]=Pencere listesi +Name[uk]=Список вікон +Name[x-test]=xxWindow listxx +Name[zh_CN]=窗口列表 +Name[zh_TW]=視窗列表 +Comment=Plasmoid to show list of opened windows. +Comment[ar]=بلازمويد لعرض لائحة بالنوافذ المفتوحة +Comment[ast]=Plasmoide qu'amuesa una llista de les ventanes abiertes. +Comment[bg]=Джаджа, показваща списък с отворените прозорци +Comment[bs]=Plazmoid za prikaz spiska otvorenih prozora. +Comment[ca]=Plasmoide que mostra una llista de les finestres obertes. +Comment[ca@valencia]=Plasmoide que mostra una llista de les finestres obertes. +Comment[cs]=Zobrazit seznam otevřených oken. +Comment[csb]=Plazmòid wëskrzënianiô lëstë òtemkłich òknów +Comment[da]=Plasmoid til at vise en liste over åbne vinduer. +Comment[de]=Miniprogramm zur Auflistung geöffneter Fenster. +Comment[el]=Πλασμοειδές για εμφάνιση λίστας των ανοιχτών παραθύρων. +Comment[en_GB]=Plasmoid to show list of opened windows. +Comment[es]=Plasmoide que muestra una lista de las ventanas abiertas. +Comment[et]=Avatud akende nimekirja näitav plasmoid. +Comment[eu]=Irekitako leihoen zerrenda erakusteko plasmoidea. +Comment[fi]=Plasmoidi avoimien ikkunoiden luettelon näyttämiseen. +Comment[fr]=Composant graphique affichant la liste des fenêtres ouvertes. +Comment[fy]=PLasmoid om in opsomming fan iepen finsters sjen te litten. +Comment[ga]=Plasmoid a thaispeánann liosta d'fhuinneoga oscailte. +Comment[gl]=Un plasmoide que mostra unha lista coas xanelas abertas. +Comment[he]=‏Plasmoid להצגת רשימת חלונות פתוחים. +Comment[hr]=Plasmoid koji prikazuje listu otvorenih prozora +Comment[hu]=Plazmoid a megnyitott ablakok listájának megjelenítésére. +Comment[ia]=Plasmoid per monstrar lista de fenestras aperite. +Comment[id]=Plasmoid untuk menampilkan senarai jendela terbuka. +Comment[is]=Plasmíð sem birtir lista yfir alla opna glugga +Comment[it]=Plasmoide per mostrare un elenco di finestre aperte. +Comment[ja]=開いているウィンドウの一覧を表示するプラズモイド +Comment[kk]=Ашылған терезелер тізімін көрсететін плазмоид. +Comment[km]=Plasmoid ត្រូវ​បង្ហាញ​បញ្ជី​បង្អួច​​ដែល​បា​ន​បើក ។ +Comment[ko]=열린 창 목록을 보여주는 Plasmoid. +Comment[lt]=Atvertų langų sąrašą rodantis plazmoidas. +Comment[lv]=Plazmoīds, kas rāda atvērto logu sarakstu. +Comment[mk]=Плазмоид за прикажување листа од отворените прозорци +Comment[ml]=തുറന്ന ജാലകങ്ങളുടെ പട്ടിക കാണിയ്ക്കാനുള്ള പ്ലാസ്മോയിഡ് +Comment[mr]=उघडलेल्या चौकटींची यादी दर्शविणारे प्लाज्मोइड +Comment[nb]=Plasmoide som viser en liste over åpne vinduer. +Comment[nds]=Plasma-Lüttprogramm, dat de List mit opmaakt Finstern wiest +Comment[nl]=Plasmoid voor het tonen van een lijst van geopende vensters. +Comment[nn]=Plasmoide for å visa oversikt over opne vindauge. +Comment[pa]=ਖੁੱਲ੍ਹੀਆਂ ਵਿੰਡੋਜ਼ ਦੀ ਲਿਸਟ ਵੇਖਾਉਣ ਲਈ ਪਲਾਜ਼ਾਮੋਡ। +Comment[pl]=Plazmoid pokazujący listę otwartych okien. +Comment[pt]=Um plasmóide para ver a lista de janelas abertas. +Comment[pt_BR]=Plasmoide para exibir a lista de janelas abertas. +Comment[ro]=Plasmoid ce arată lista ferestrelor deschise. +Comment[ru]=Виджет, показывающий список окон +Comment[si]=විවෘත කල කවුළු ලැයිස්තුවක් පෙන්වීම සඳහා ප්ලැස්මොයිඩය. +Comment[sk]=Zobrazenie zoznamu otvorených okien. +Comment[sl]=Gradnik, ki prikazuje seznam odprtih oken. +Comment[sr]=Плазмоид за приказ списка отворених прозора. +Comment[sr@ijekavian]=Плазмоид за приказ списка отворених прозора. +Comment[sr@ijekavianlatin]=Plazmoid za prikaz spiska otvorenih prozora. +Comment[sr@latin]=Plazmoid za prikaz spiska otvorenih prozora. +Comment[sv]=Plasmoid för att visa lista med öppna fönster. +Comment[tg]=Барномаи Plasmoid барои намоиши рӯйхат бо тирезаҳои кушодашуда. +Comment[th]=พลาสมอยด์สำหรับแสดงรายการของหน้าต่างต่าง ๆ ที่เปิดอยู่ +Comment[tr]=Açık pencerelerin listesini gösteren plasmoid. +Comment[ug]=ئېچىلغان كۆزنەكلەرنىڭ Plasmoid تىزىمىنى كۆرسىتىدۇ. +Comment[uk]=Плазмоїд для показу списку відкритих вікон. +Comment[wa]=Plasmowide po mostrer l' djivêye des fniesses di drovowes. +Comment[x-test]=xxPlasmoid to show list of opened windows.xx +Comment[zh_CN]=显示已打开窗口的 Plasmoid 部件。 +Comment[zh_TW]=顯示已開啟視窗清單的元件 +Icon=preferences-system-windows +Type=Service +X-KDE-ParentApp= + +X-KDE-PluginInfo-Author=Heena +X-KDE-PluginInfo-Email=heena393@gmail.com +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=org.kde.plasma.windowlist +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=plasma.kde.org +X-KDE-ServiceTypes=Plasma/Applet,Plasma/PopupApplet +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml +X-Plasma-RemoteLocation= +X-KDE-PluginInfo-Category=Windows and Tasks diff --git a/config-X11.h.cmake b/config-X11.h.cmake new file mode 100644 index 0000000000..ee5183a632 --- /dev/null +++ b/config-X11.h.cmake @@ -0,0 +1,44 @@ +/* Define if you have the XRandR extension */ +#cmakedefine HAVE_XRANDR 1 + +/* Define if you have the XDamage extension */ +#cmakedefine HAVE_XDAMAGE 1 + +/* Define if you have the XKB extension */ +#cmakedefine HAVE_XKB 1 + +/* Define if you have the Xinerama extension */ +#cmakedefine HAVE_XINERAMA 1 + +/* Define if you have the XSHM (MIT SHM) extension */ +#cmakedefine HAVE_XSHM 1 + +/* Define if you have the XComposite extension */ +#cmakedefine HAVE_XCOMPOSITE 1 + +/* Define to 1 if you have Xcursor */ +#cmakedefine HAVE_XCURSOR 1 + +/* Define if you have the xf86misc extension */ +#cmakedefine HAVE_XF86MISC 1 + +/* Define if you have the XFixes extension */ +#cmakedefine HAVE_XFIXES 1 + +/* Define if you have the XTest extension */ +#cmakedefine HAVE_XTEST 1 + +/* Define if your system has XRender support */ +#cmakedefine HAVE_XRENDER 1 + +/* Define if you have OpenGL */ +#cmakedefine HAVE_OPENGL 1 + +/* Define if you have the XSync extension */ +#cmakedefine HAVE_XSYNC 1 + +/* Define if you have XRandR 1.3 */ +#cmakedefine HAS_RANDR_1_3 1 + +/* Define if you have X11 at all */ +#define HAVE_X11 ${X11_FOUND} \ No newline at end of file diff --git a/config-unix.h.cmake b/config-unix.h.cmake new file mode 100644 index 0000000000..ddb49b680d --- /dev/null +++ b/config-unix.h.cmake @@ -0,0 +1,35 @@ +/* Defines if you have PAM (Pluggable Authentication Modules) */ +#cmakedefine HAVE_PAM 1 + +/* Define if your PAM headers are in pam/ instead of security/ */ +#cmakedefine HAVE_PAM_PAM_APPL_H 1 + +/* Define if your PAM expects a conversation function with const pam_message (Solaris) */ +#cmakedefine PAM_MESSAGE_CONST 1 + +/* The PAM service to be used by kdm */ +#cmakedefine KDM_PAM_SERVICE ${KDM_PAM_SERVICE} + +/* The PAM service to be used by kscreensaver */ +#cmakedefine KSCREENSAVER_PAM_SERVICE ${KSCREENSAVER_PAM_SERVICE} + +/* Defines if your system has the getspnam function */ +#cmakedefine HAVE_GETSPNAM 1 + +/* Defines if your system has the crypt function */ +#cmakedefine HAVE_CRYPT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CRYPT_H 1 + +/* Define to 1 if you have the `pw_encrypt' function. */ +#cmakedefine HAVE_PW_ENCRYPT 1 + +/* Define to 1 if you have the `getpassphrase' function. */ +#cmakedefine HAVE_GETPASSPHRASE 1 + +/* Define to 1 if you have the `vsyslog' function. */ +#cmakedefine HAVE_VSYSLOG 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 diff --git a/config-workspace.h.cmake b/config-workspace.h.cmake new file mode 100644 index 0000000000..66c1d6359a --- /dev/null +++ b/config-workspace.h.cmake @@ -0,0 +1,159 @@ +/* config-workspace.h. Generated by cmake from config-workspace.h.cmake */ + +#cmakedefine HAVE_QIMAGEBLITZ + +/* Define if you have DPMS support */ +#cmakedefine HAVE_DPMS 1 + +/* Define if you have the DPMSCapable prototype in */ +#cmakedefine HAVE_DPMSCAPABLE_PROTO 1 + +/* Define if you have the DPMSInfo prototype in */ +#cmakedefine HAVE_DPMSINFO_PROTO 1 + +/* Defines if your system has the libfontconfig library */ +#cmakedefine HAVE_FONTCONFIG 1 + +/* Defines if your system has the freetype library */ +#cmakedefine HAVE_FREETYPE 1 + +/* Define if you have gethostname */ +#cmakedefine HAVE_GETHOSTNAME 1 + +/* Define if you have the gethostname prototype */ +#cmakedefine HAVE_GETHOSTNAME_PROTO 1 + +/* Define to 1 if you have the `getpeereid' function. */ +#cmakedefine HAVE_GETPEEREID 1 + +/* Defines if you have Solaris' libkstat */ +/* #undef HAVE_KSTAT */ + +/* Define if you have long long as datatype */ +#cmakedefine HAVE_LONG_LONG 1 + +/* Define to 1 if you have the `nice' function. */ +#cmakedefine HAVE_NICE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SASL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SASL_SASL_H 1 + +/* Define to 1 if you have the `setpriority' function. */ +#cmakedefine HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `sigaction' function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the `sigset' function. */ +#cmakedefine HAVE_SIGSET 1 + +/* Define to 1 if you have statvfs */ +#cmakedefine HAVE_STATVFS 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define if you have the struct ucred */ +#cmakedefine HAVE_STRUCT_UCRED 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_LOADAVG_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have statfs(). */ +#cmakedefine HAVE_STATFS 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_H 1 + +/* Define if you have unsetenv */ +#cmakedefine HAVE_UNSETENV 1 + +/* Define if you have the unsetenv prototype */ +#cmakedefine HAVE_UNSETENV_PROTO 1 + +/* Define if you have usleep */ +#cmakedefine HAVE_USLEEP 1 + +/* Define if you have the usleep prototype */ +#cmakedefine HAVE_USLEEP_PROTO 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#cmakedefine HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the Wayland libraries. */ +#cmakedefine WAYLAND_FOUND 1 + +/* KDE's default home directory */ +#cmakedefine KDE_DEFAULT_HOME "${KDE_DEFAULT_HOME}" + +/* KDE's binaries directory */ +#define KDE_BINDIR "${BIN_INSTALL_DIR}" + +/* KDE's configuration directory */ +#define KDE_CONFDIR "${CONFIG_INSTALL_DIR}" + +/* KDE's static data directory */ +#define KDE_DATADIR "${DATA_INSTALL_DIR}" + +/* Define where your java executable is */ +#undef PATH_JAVA + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* X binaries directory */ +#cmakedefine XBINDIR "${XBINDIR}" + +/* X libraries directory */ +#cmakedefine XLIBDIR "${XLIBDIR}" + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +/* type to use in place of socklen_t if not defined */ +#define kde_socklen_t socklen_t + +#define WORKSPACE_VERSION_STRING "${KDE4WORKSPACE_VERSION}" \ No newline at end of file diff --git a/containments/CMakeLists.txt b/containments/CMakeLists.txt new file mode 100644 index 0000000000..3d364eef09 --- /dev/null +++ b/containments/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(desktop) +plasma_install_package(panel org.kde.panel plasma/plasmoids containment) diff --git a/containments/desktop/CMakeLists.txt b/containments/desktop/CMakeLists.txt new file mode 100644 index 0000000000..d66cd41460 --- /dev/null +++ b/containments/desktop/CMakeLists.txt @@ -0,0 +1,2 @@ +plasma_install_package(package org.kde.desktopcontainment plasma/plasmoids containment) +add_subdirectory(tests) diff --git a/containments/desktop/Messages.sh b/containments/desktop/Messages.sh new file mode 100644 index 0000000000..c8a9b6091b --- /dev/null +++ b/containments/desktop/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.qml` -L Java -o $podir/plasma_containment_org.kde.plasma.desktopcontainment.pot +rm -f rc.cpp diff --git a/containments/desktop/TODO b/containments/desktop/TODO new file mode 100644 index 0000000000..23fb4a670d --- /dev/null +++ b/containments/desktop/TODO @@ -0,0 +1,73 @@ + + == Declarative Desktop for Plasma == + + +TODO: +* hide handle after short timeout +* fix user interaction with rotation +* + + +BUGS: +* drag input is blocked for folderview, debug, applet is dragged instead of rubberband or items +* folderview doesn't have "run associated application" action +* blackboard doesn't have "run associated application" action + +DONE: +o ToolBox QML files move into their own package +o ToolBox is put on top of the scene in DeclarativeAppletScript::qmlCreationFinished() +o rename ToolBox.qml to ToolBoxItem.qml +o ToolBox-visible name to the runtime is ToolBox +o mouse drag expands over handle + o move mouseventlistener into subitem to be able to manage its margins / position + o everything else under the mouse *has to be* parented to this one, still +o minimum size for applethandle +o switch handle appearance when minimumSize is reached during resize +o implement rotation + o rotate item + o save rotation per item + o restore rotation per item +o rename main to root +o rename itemgroup to AppletItem +o meaningful name for plasmoidgroup or merge into AppletItem? +o open associated app + +OTHER: + +/** Action Mapping for ToolBox + +list-add Add Panel +list-add Add Widgets +preferences-activities Activities Activities +configure-shortcuts Shortcut Settings Shortcut Settings +configure $containment_name Settings $containment_name Settings +object-locked Lock Widgets +object-unlocked Unlock Widgets +system-lock-screen Lock Screen Lock Screen +system-shutdown Leave Leave + +**/ + +[17:04:19] sebas: i think should be in DeclarativeAppletScript::qmlCreationFinished, same thing as now checks if is a popupapplet and does compactrepresentation +[17:04:58] notmart: hah, I've that file open as well +[17:05:05] in init() +[17:05:50] So I'll split out the toolbox into its own QML Package +[17:06:38] but I'll still have to expose what is now InternalToolBox to the Containment +[17:06:52] right now, to have something that works quickly, you may just load a single file +[17:07:07] --> Savago (~adenilson@200.160.100.16) has joined #plasma +[17:07:21] it needs two elements anyway, so I suppose a package is fine +[17:07:28] (button to open it, the toolbox itself) +[17:07:41] aseigo: what do you think about that? ^^ (how to do toolbox) +[17:07:45] I've basically the QML code for those already written +[17:07:54] that's how i would do it, don't know if i'm overengineering +[17:08:05] <-> krake_ is now known as krake +[17:08:28] I don't really see a problem with putting the toolbox directly into the containment, but I might be missing some plugin architecture behind it +[17:08:42] and it should be possible to share the toolbox between containments +[17:08:49] terietor: m_namedFiles gets all the files with key names in the model... +[17:09:26] notmart: looks reasonable i think +[17:09:46] sebas: it gets used by several different containments +[17:09:50] folderview and desktop, e.g. +[17:10:00] notmart, aseigo: is the InternalToolBox api-wise OK with you to expose to both containment and ToolBox? +[17:10:46] terietor: and then in PackageModel::data it assumes that the # of files listed == the # of keys (m_namedFiles) +[17:10:57] sebas: looks sensible + diff --git a/containments/desktop/package/contents/code/LayoutManager.js b/containments/desktop/package/contents/code/LayoutManager.js new file mode 100644 index 0000000000..108987ffe9 --- /dev/null +++ b/containments/desktop/package/contents/code/LayoutManager.js @@ -0,0 +1,294 @@ +/* + * Copyright 2011 Marco Martin + * + * This program 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, 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 Library 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. + */ + +.pragma library + +var positions = new Array(); + +var cellSize = new Object(); +cellSize.width = 24; +cellSize.height = 24; + +var defaultAppletSize = new Object(); +defaultAppletSize.width = cellSize.width * 6; +defaultAppletSize.height = cellSize.height * 6; + + +var resultsFlow +var plasmoid; +var itemsConfig + +//bookkeeping for the item groups +var itemGroups = new Object() + +function restore() +{ + var appletsMap = new Object(); + var applet; + for (var i = 0; i < plasmoid.applets.length; ++i) { + applet = plasmoid.applets[i]; + appletsMap["Applet-"+applet.id] = applet; + } + + itemsConfig = new Object(); + var configString = String(plasmoid.configuration.ItemsGeometries) + //print("Config read from configfile: " + configString); + //array, a cell for encoded item geometry + var itemsStrings = configString.split(";") + for (var i=0; i= Math.max(item.minimumWidth, cellSize.width) && + forwardAvail.height >= Math.max(item.minimumHeight, cellSize.height)) { + x = forwardX + y = forwardY + avail = forwardAvail + break + } + forwardX += cellSize.width + //new line + if (forwardX+item.width > resultsFlow.width) { + forwardX = 0 + forwardY += cellSize.height + //forward positions exausted + //scrolling now + /*if (forwardY > resultsFlow.height) { + break; + }*/ + } + + //backwards positions exausted + if (backY < 0) { + continue + } + + //look backwards + var backAvail = availableSpace(backX, backY, + Math.max(item.minimumWidth, item.width), + Math.max(item.minimumHeight, item.height)) + //print("checking backwards "+backX/cellSize.width+" "+backY/cellSize.height+" "+backAvail.width/cellSize.width+" "+backAvail.height/cellSize.height) + + if (backAvail.width >= Math.max(item.minimumWidth, cellSize.width) && + backAvail.height >= Math.max(item.minimumHeight, cellSize.height)) { + x = backX + y = backY + avail = backAvail + break + } + backX -= cellSize.width + if (backX < 0) { + backX = resultsFlow.width - item.width + backY -= cellSize.height + } + } + + var width = Math.max(cellSize.width*Math.max(1, Math.ceil(item.minimumWidth/cellSize.width)), + Math.round(Math.min(avail.width, item.width)/cellSize.width)*cellSize.width) + var height = Math.max(cellSize.height*Math.max(1, Math.ceil(item.minimumHeight/cellSize.height)), + Math.round(Math.min(avail.height, item.height)/cellSize.height)*cellSize.height) + + setSpaceAvailable(x, y, width, height, false) + //resultsFlow.height = Math.max(resultsFlow.height, y+cellSize.height) + + item.x = x + item.y = y + item.width = width + item.height = height + + saveItem(item); +} + +function removeApplet(applet) { + // Keeps config in sync, deletion of items in the scene + // are handled in AppletAppearance and main.qml + delete itemsConfig["Applet-"+applet.id]; + delete itemGroups["Applet-"+applet.id]; +} + +function saveItem(item) { + var rect = new Object() + rect.x = item.x + rect.y = item.y + rect.width = item.width + rect.height = item.height + rect.rotation = item.rotation + //print("-- Saving rotation : " + rect.rotation); + //save only things that actually have a category (exclude the placeholder) + if (item.category) { + //print("-- Saving rotation : " + rect.rotation); + itemsConfig[item.category] = rect + } + +} diff --git a/containments/desktop/package/contents/config/main.xml b/containments/desktop/package/contents/config/main.xml new file mode 100644 index 0000000000..d889999299 --- /dev/null +++ b/containments/desktop/package/contents/config/main.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + topleft + + + + + + + + + + + + + true + + + + diff --git a/containments/desktop/package/contents/images/resize-handle.svgz b/containments/desktop/package/contents/images/resize-handle.svgz new file mode 100755 index 0000000000000000000000000000000000000000..888b14e16907156bc8e5ead16fb1ee57a6c000c4 GIT binary patch literal 1375 zcmV-l1)%yLiwFP!000000L@oRbK5o$zWZ08%q5wMBmll?QJH3vcyel|dGy$UNJwH$ z5gL%PB>(y@NP?m)y0)99Hf_%U`@rsgyI8EJZ};m0-EdjuqD%~8VFU3p6TV$jj?{ooTp3>yV=j{PhZ&U{zu( zQ@#LAZk4>Y-+y`EGfiw|bv8H#4y{tQ;U{)AvBit6d9`6FuWU_k^an*l8bY2W#)ml+ z#h>kdpBQ+vZZsuId5dCg;0%LMbDRs0+UhnU`!{aC6Sm>!lRi z5{#96hfakcrnvDnF*cG{T;8<4YRBW=X>7Rxl9YO((@1E5;!LC};=};`{Fa+5sQrRl zkg8i_HeK_YWvpg8UcDz6m{2M4@9#g(rfC}gA>_3ZQlFx;x!6LKAeE&t8A_%;Y`8w4JpvqRGCO)1vUHs*75j6Y7sV%avVrW`)b4zNRqvjyy#_;k zQR!IJIs^xy&^VJB103!Vo`C39QTx}J`}u_ zG*eMP|9FL)@3J8Y$RC6f#@JZOT9nea{e1Qhhm1;YhT z;Y?QS*rDnUZn|Q;k{r7DtC0e|7s`Ny9dp@{zLt3nt$GVxlX*E+vdX=hSVU@pE#YW#v+DV1!q#SSEH5_$h0bmq0eV z$&2_Q9_8yvj9`2m=z2)nAgh(wDc@DCZ|}@jw?aVPDYbkWxFk4bHrb~&88uQR z#{QrvgUh0}G^AY>o!5{07iPoimC{gCB8n!&K@35)!@Nr1$D|WH*s9&_=^!fmB07@x zXCwt4xii8ltiwKo$`2a4olN_bA15Uz@*Fn|>E!~(#(s2Ao58!@Y~{A#aVg4MC~|oC zrMPak{M2>}7?Wv3u19+#gbiI$L8mdgNBtphyAkWj-VR{73uh1AKO#Jmh-12*nDB9o z@FY5gXk5%|p!^O9|82rGgpS|c^yh-`VT@b_MRX%? h;=hPy1gPAL+%q>LcjCS2p1Pam>~9^~=czOl008Qds&oJV literal 0 HcmV?d00001 diff --git a/containments/desktop/package/contents/ui/ActionButton.qml b/containments/desktop/package/contents/ui/ActionButton.qml new file mode 100644 index 0000000000..ff0322fa31 --- /dev/null +++ b/containments/desktop/package/contents/ui/ActionButton.qml @@ -0,0 +1,144 @@ +/* + * Copyright 2011 Marco Martin + * Copyright 2013 Sebastian Kügler + * + * This program 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, 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Item { + id: button + + //API + property QtObject svg + property alias elementId: icon.elementId + property QtObject action + property bool backgroundVisible: false + property int iconSize: 32 + property int pressedOffset: 1 + property bool checked: false + property bool toggle: false + property string text + signal clicked + + width: buttonRow.width + height: buttonRow.height + + opacity: action==undefined||action.enabled?1:0.6 + + Behavior on opacity { + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + + onCheckedChanged: { + if (checked) { + buttonItem.elementId = "pressed" + shadowItem.opacity = 0 + } else { + buttonItem.elementId = "normal" + shadowItem.opacity = 1 + } + } + + PlasmaCore.Svg { + id: buttonSvg + imagePath: "widgets/actionbutton" + } + + PlasmaCore.SvgItem { + id: shadowItem + svg: buttonSvg + elementId: "shadow" + width: iconSize+13//button.backgroundVisible?iconSize+8:iconSize + height: width + visible: button.backgroundVisible + } + + Row { + id: buttonRow + + Item { + width: buttonItem.visible?buttonItem.width:iconSize + height: buttonItem.visible?buttonItem.height:iconSize + + PlasmaCore.SvgItem { + id: buttonItem + svg: buttonSvg + elementId: "normal" + width: shadowItem.width + height: shadowItem.height + visible: backgroundVisible + } + + PlasmaCore.SvgItem { + id: icon + width: iconSize + height: iconSize + svg: button.svg + anchors.centerIn: parent + } + } + + Text { + id: actionText + text: button.text + style: Text.Outline + color: theme.textColor + styleColor: Qt.rgba(1,1,1,0.4) + anchors.verticalCenter: parent.verticalCenter + } + } + + MouseArea { + anchors.fill: parent + anchors.leftMargin: -10 + anchors.topMargin: -10 + anchors.rightMargin: -10 + anchors.bottomMargin: -10 + preventStealing: true + onPressed: { + buttonItem.elementId = "pressed" + shadowItem.opacity = 0; + button.x = button.x + button.pressedOffset; + button.y = button.y + button.pressedOffset; + } + onReleased: { + if (button.checked || !button.toggle) { + buttonItem.elementId = "normal" + shadowItem.opacity = 1 + button.checked = false + } else { + button.checked = true + } + button.x = button.x - button.pressedOffset; + button.y = button.y - button.pressedOffset; + } + onClicked: { + if (action) { + action.trigger() + } else { + button.clicked() + } + } + } + Rectangle { color: "white"; opacity: 0.4; visible: debug; anchors.fill: parent; } +} diff --git a/containments/desktop/package/contents/ui/AppletAppearance.qml b/containments/desktop/package/contents/ui/AppletAppearance.qml new file mode 100644 index 0000000000..3fd88b376b --- /dev/null +++ b/containments/desktop/package/contents/ui/AppletAppearance.qml @@ -0,0 +1,376 @@ +/* + * Copyright 2011-2013 Sebastian Kügler + * Copyright 2011 Marco Martin + * Copyright 2014 David Edmundson + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +Item { + id: appletItem + + anchors.rightMargin: -handleWidth*controlsOpacity + + property int handleWidth: iconSize + 8 // 4 pixels margins inside handle + property int minimumHandleHeight: 6 * (root.iconSize + 6) + margins.top + margins.bottom + property int handleHeight: (height < minimumHandleHeight) ? minimumHandleHeight : height + property string category + + property bool showAppletHandle: false + property real controlsOpacity: (plasmoid.immutable || !showAppletHandle) ? 0 : 1 + property bool handleShown: true + property string backgroundHints: "NoBackground" + property bool hasBackground: false + property bool handleMerged: (height > minimumHandleHeight) + property bool animationsEnabled: false + + property int minimumWidth: Math.max(LayoutManager.cellSize.width, + appletContainer.minimumWidth + + appletItem.contents.anchors.leftMargin + + appletItem.contents.anchors.rightMargin) + + property int minimumHeight: Math.max(LayoutManager.cellSize.height, + appletContainer.minimumHeight + + appletItem.contents.anchors.topMargin + + appletItem.contents.anchors.bottomMargin) + + property alias applet: appletContainer.applet + + property Item contents: appletContainer + property alias margins: plasmoidBackground.margins + property alias imagePath: plasmoidBackground.imagePath + + visible: false + + //FIXME: this delay is because backgroundHints gets updated only after a while in qml applets + Timer { + id: appletTimer + interval: 50 + repeat: false + running: false + onTriggered: { + updateBackgroundHints(); + applet.parent = appletContainer; + applet.anchors.fill = appletContainer; + } + } + + function updateBackgroundHints() { + hasBackground = (applet.backgroundHints != "NoBackground"); + if (applet.backgroundHints == 1) { + appletItem.imagePath = "widgets/background"; + backgroundHints = "StandardBackground"; + } else if (applet.backgroundHints == 2) { + appletItem.imagePath = "widgets/translucentbackground" + backgroundHints = "TranslucentBackground"; + } else if (applet.backgroundHints == 0) { + appletItem.imagePath = "" + backgroundHints = "NoBackground"; + } else { + backgroundHints = "DefaultBackground"; + appletItem.imagePath = "widgets/background"; + } + //print("Backgroundhints changed: " + appletItem.imagePath); + } + + Rectangle { color: Qt.rgba(0,0,0,0); border.width: 3; border.color: "white"; opacity: 0.5; visible: debug; anchors.fill: parent; } + + KQuickControlsAddons.MouseEventListener { + id: mouseListener + + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + height: handleHeight + width: parent.width+handleWidth; + z: 10 + + hoverEnabled: true + + onPressAndHold: { + if (root.pressAndHoldHandle && !plasmoid.immutable) { + //hoverTracker.interval = 400; + hoverTracker.restart(); + } + } + + onContainsMouseChanged: { + + animationsEnabled = true; + //print("Mouse is " + containsMouse); + if (!plasmoid.immutable && containsMouse) { + if (!root.pressAndHoldHandle) { + hoverTracker.interval = root.handleDelay; + hoverTracker.restart(); + } + } else { + hoverTracker.stop(); + showAppletHandle = false; + } + } + + Timer { + id: hoverTracker + repeat: false + interval: handleDelay + onTriggered: showAppletHandle = true; + } + Rectangle { color: Qt.rgba(0,0,0,0); border.width: 3; border.color: "red"; opacity: 0.5; visible: debug; anchors.fill: parent; } + + + + Item { + anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } + width: parent.width+handleWidth; + + z: mouseListener.z + 4 + + PlasmaCore.FrameSvgItem { + id: plasmoidBackground + visible: backgroundHints != "NoBackground" + imagePath: "widgets/background" + anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } + width: (showAppletHandle && handleMerged) ? parent.width : parent.width-handleWidth; + smooth: true + + Behavior on width { + enabled: animationsEnabled + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + Connections { + target: plasmoid + onImmutableChanged: { + print(" TB dragMouseArea.visible: " + plasmoid.immutable) + dragMouseArea.visible = !plasmoid.immutable; + showAppletHandle = false; + } + onAppletRemoved: { + print("Applet removed Applet-" + applet.id) + if (applet.id == appletItem.applet.id) { + print("Destroying Applet-" + applet.id) + LayoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) + //applet.action("remove").trigger(); + //appletItem.destroy() + appletItem.destroy(); + } + } + } + Connections { + target: applet + onBusyChanged: { + if (applet.busy) { + busyLoader.source = "BusyOverlay.qml" + } else if (busyLoader.item && typeof(busyLoader.item) != "undefined") { + busyLoader.item.disappear(); + } + } + onBackgroundHintsChanged: { + print("plasmoid.backgroundHintsChanged"); + updateBackgroundHints(); + } + } + + MouseArea { + id: dragMouseArea + + anchors.fill: parent + z: appletContainer.z - 2 + + property int lastX + property int lastY + property int zoffset: 1000 + + onPressed: { + appletItem.z = appletItem.z + zoffset; + animationsEnabled = false + mouse.accepted = true + var x = Math.round(appletItem.x/LayoutManager.cellSize.width)*LayoutManager.cellSize.width + var y = Math.round(appletItem.y/LayoutManager.cellSize.height)*LayoutManager.cellSize.height + LayoutManager.setSpaceAvailable(x, y, appletItem.width, appletItem.height, true) + + var globalMousePos = mapToItem(root, mouse.x, mouse.y) + lastX = globalMousePos.x + lastY = globalMousePos.y + + + placeHolder.syncWithItem(appletItem) + placeHolderPaint.opacity = root.haloOpacity; + } + onPositionChanged: { + placeHolder.syncWithItem(appletItem) + + var globalPos = mapToItem(root, x, y) + + var globalMousePos = mapToItem(root, mouse.x, mouse.y) + appletItem.x += (globalMousePos.x - lastX) + appletItem.y += (globalMousePos.y - lastY) + + lastX = globalMousePos.x + lastY = globalMousePos.y + } + onReleased: { + appletItem.z = appletItem.z - zoffset; + repositionTimer.running = false + placeHolderPaint.opacity = 0 + animationsEnabled = true + LayoutManager.positionItem(appletItem) + LayoutManager.save() + } + } + + Item { + id: appletContainer + anchors { + fill: parent + leftMargin: plasmoidBackground.margins.left + rightMargin: plasmoidBackground.margins.right + handleWidth + topMargin: plasmoidBackground.margins.top + bottomMargin: plasmoidBackground.margins.bottom + } + z: mouseListener.z+1 + + property QtObject applet + + property int minimumWidth: applet && applet.Layout ? applet.Layout.minimumWidth : 0 + property int minimumHeight: applet && applet.Layout ? applet.Layout.minimumHeight : 0 + + function appletDestroyed() { + print("Applet DESTROYED."); + LayoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) + applet.action("remove").trigger(); + appletItem.destroy() + } + + onAppletChanged: { + if (applet) { + appletTimer.running = true; + } + } + Connections { + target: appletHandle.item + onRemoveApplet: { + killAnim.running = true; + } + } + Behavior on opacity { + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + SequentialAnimation { + id: killAnim + PlasmaExtras.DisappearAnimation { + targetItem: appletItem + } + ScriptAction { + script: appletContainer.appletDestroyed() + } + } + Loader { + id: busyLoader + anchors.centerIn: parent + z: appletContainer.z + 1 + } + Rectangle { color: "green"; opacity: 0.3; visible: debug; anchors.fill: parent; } + Component.onCompleted: PlasmaExtras.AppearAnimation { + targetItem: appletItem + } + } + + Loader { + id: appletHandle + z: appletContainer.z + 1 + anchors { + top: parent.top + bottom: parent.bottom + right: plasmoidBackground.right + rightMargin: appletItem.margins.right + } + Connections { + target: appletItem + onShowAppletHandleChanged: { + if (appletItem.showAppletHandle && appletHandle.source == "") { + //print("Loading applethandle "); + appletHandle.source = "AppletHandle.qml"; + } + } + } + + } + + Rectangle { color: "orange"; opacity: 0.1; visible: debug; anchors.fill: parent; } + } + } + + Behavior on controlsOpacity { + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on x { + enabled: animationsEnabled + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on y { + enabled: animationsEnabled + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on width { + enabled: animationsEnabled + NumberAnimation { + id: widthAnimation + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on height { + enabled: animationsEnabled + NumberAnimation { + id: heightAnimation + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + + Component.onCompleted: { + layoutTimer.running = true + layoutTimer.restart() + visible = false + // restore rotation + } +} diff --git a/containments/desktop/package/contents/ui/AppletHandle.qml b/containments/desktop/package/contents/ui/AppletHandle.qml new file mode 100644 index 0000000000..eabe15ea41 --- /dev/null +++ b/containments/desktop/package/contents/ui/AppletHandle.qml @@ -0,0 +1,260 @@ +/* + * Copyright 2011-2013 Sebastian Kügler + * Copyright 2011 Marco Martin + * Copyright 2014 David Edmundson + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.core 2.0 as PlasmaCore + +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +Item { + id: appletHandle + + opacity: appletItem.controlsOpacity + visible: opacity > 0 + width: appletItem.handleWidth + //z: dragMouseArea.z + 1 + + property int buttonMargin: 6 + property int minimumHeight: 6 * (root.iconSize + buttonMargin) + property Item buttonsParent: appletItem.handleMerged ? appletHandle : noBackgroundHandle + + signal removeApplet + + transform: Translate { + x: handleMerged ? 0 : controlsOpacity * appletHandle.width + } + + PlasmaCore.FrameSvgItem { + id: noBackgroundHandle + visible: controlsOpacity > 0 + z: plasmoidBackground.z - 10 + + height: (backgroundHints != "NoBackground") ? appletItem.handleHeight : appletItem.handleHeight + noBackgroundHandle.margins.top + noBackgroundHandle.margins.bottom + + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + + smooth: true + imagePath: (backgroundHints == "NoBackground" || !handleMerged) ? "widgets/background" : "" + } + + ColumnLayout { + id: buttonColumn + width: handleWidth + parent: buttonsParent + anchors { + top: parent.top + topMargin: (!appletItem.hasBackground || !handleMerged) ? noBackgroundHandle.margins.top : appletItem.margins.top + bottom: parent.bottom + bottomMargin: (!appletItem.hasBackground && !handleMerged) ? noBackgroundHandle.margins.bottom : appletItem.margins.bottom + right: parent.right + rightMargin: appletItem.handleMerged ? -buttonMargin : noBackgroundHandle.margins.right - buttonMargin + } + spacing: buttonMargin*2 + ActionButton { + svg: configIconsSvg + elementId: "size-diagonal-tr2bl" + iconSize: root.iconSize + visible: (action && typeof(action) != "undefined") ? action.enabled : false + action: (applet) ? applet.action("configure") : null + Component.onCompleted: { + if (action && typeof(action) != "undefined") { + action.enabled = true + } + } + + MouseArea { + id: resizeHandle + anchors { + fill: parent + margins: -buttonMargin + } + + property int startX + property int startY + + onPressed: { + mouse.accepted = true + animationsEnabled = false; + startX = mouse.x; + startY = mouse.y; + LayoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) + } + onPositionChanged: { + appletItem.width = Math.max(appletItem.minimumWidth, appletItem.width + mouse.x-startX) + appletItem.y = appletItem.y + (mouse.y-startY); + appletItem.height = Math.max(appletItem.minimumHeight, appletItem.height + startY-mouse.y) + } + onReleased: { + animationsEnabled = true + LayoutManager.positionItem(appletItem) + LayoutManager.save() + LayoutManager.setSpaceAvailable(appletItem.x, appletItem.y, widthAnimation.to, heightAnimation.to, false) + } + Rectangle { color: "blue"; opacity: 0.4; visible: debug; anchors.fill: parent; } + } + } + ActionButton { + id: rotateButton + svg: configIconsSvg + elementId: "rotate" + iconSize: root.iconSize + action: (applet) ? applet.action("rotate") : null + Component.onCompleted: { + if (action && typeof(action) != "undefined") { + action.enabled = true + } + } + MouseArea { + + anchors { + fill: parent + margins: -buttonMargin + } + + property int startRotation + property real startCenterRelativeAngle; + + function pointAngle(pos) { + var r = Math.sqrt(pos.x * pos.x + pos.y * pos.y); + var cosine = pos.x / r; + + if (pos.y >= 0) { + return Math.acos(cosine) * (180/Math.PI); + } else { + return -Math.acos(cosine) * (180/Math.PI); + } + } + + function centerRelativePos(x, y) { + var mousePos = appletItem.parent.mapFromItem(rotateButton, x, y); + var centerPos = appletItem.parent.mapFromItem(appletItem, appletItem.width/2, appletItem.height/2); + + mousePos.x -= centerPos.x; + mousePos.y -= centerPos.y; + return mousePos; + } + + onPressed: { + mouse.accepted = true + animationsEnabled = false; + startRotation = appletItem.rotation; + LayoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) + + startCenterRelativeAngle = pointAngle(centerRelativePos(mouse.x, mouse.y)); + } + onPositionChanged: { + + var rot = startRotation%360; + var snap = 4; + var newRotation = pointAngle(centerRelativePos(mouse.x, mouse.y)) - startCenterRelativeAngle + startRotation; + + if (newRotation < 0) { + newRotation = newRotation + 360; + } + + snapIt(0); + snapIt(90); + snapIt(180); + snapIt(270); + + function snapIt(snapTo) { + if (newRotation > (snapTo - snap) && newRotation < (snapTo + snap)) { + newRotation = snapTo; + } + } + print("Start: " + startRotation + " new: " + newRotation); + appletItem.rotation = newRotation; + } + onReleased: { + // save rotation +// print("saving..."); + LayoutManager.saveItem(appletItem); + } + Rectangle { color: "red"; opacity: 0.6; visible: debug; anchors.fill: parent; } + } + } + ActionButton { + svg: configIconsSvg + elementId: "configure" + iconSize: root.iconSize + visible: (action && typeof(action) != "undefined") ? action.enabled : false + action: (applet) ? applet.action("configure") : null + Component.onCompleted: { + if (action && typeof(action) != "undefined") { + action.enabled = true + } + } + } + ActionButton { + svg: configIconsSvg + elementId: "size-diagonal-tr2bl" // FIXME should be maximize + //elementId: "maximize" + iconSize: root.iconSize + visible: (action && typeof(action) != "undefined") ? action.enabled : false + action: (applet) ? applet.action("run associated application") : null + Component.onCompleted: { + if (action && typeof(action) != "undefined") { + action.enabled = true + } + } + } + + //spacer + Item { + Layout.fillHeight: true + height: 0 + } + + ActionButton { + svg: configIconsSvg + elementId: "close" + iconSize: root.iconSize + visible: { + var a = applet.action("remove"); + return (a && typeof(a) != "undefined") ? a.enabled : false; + } + // we don't set action, since we want to catch the button click, + // animate, and then trigger the "remove" action + // Triggering the action is handled in the appletItem, we just + // emit a signal here to avoid the applet-gets-removed-before-we- + // can-animate it race condition. + onClicked: { + appletHandle.removeApplet(); + } + Component.onCompleted: { + var a = applet.action("remove"); + if (a && typeof(a) != "undefined") { + a.enabled = true + } + } + } + } +} diff --git a/containments/desktop/package/contents/ui/BusyOverlay.qml b/containments/desktop/package/contents/ui/BusyOverlay.qml new file mode 100644 index 0000000000..33d72c0f98 --- /dev/null +++ b/containments/desktop/package/contents/ui/BusyOverlay.qml @@ -0,0 +1,64 @@ +/* + * Copyright 2011-2013 Sebastian Kügler + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + +PlasmaComponents.BusyIndicator { + id: busyIndicator + + anchors.centerIn: parent + z: appletContainer.z + 1 + visible: applet.busy + + running: visible + + function disappear() { + appearAnim.running = false; + disappearAnim.running = true; + } + + onRunningChanged: { + if (running) { + disappearAnim.running = false; + appearAnim.running = true; + } + } + + PlasmaExtras.AppearAnimation { + id: appearAnim + targetItem: busyIndicator + running: false + } + + SequentialAnimation { + id: disappearAnim + running: false + PlasmaExtras.DisappearAnimation { + targetItem: busyIndicator + } + ScriptAction { + script: { + // unload ourselves + busyLoader.source = ""; + } + } + } +} diff --git a/containments/desktop/package/contents/ui/ContainmentConfig.qml b/containments/desktop/package/contents/ui/ContainmentConfig.qml new file mode 100644 index 0000000000..ea6c7bd504 --- /dev/null +++ b/containments/desktop/package/contents/ui/ContainmentConfig.qml @@ -0,0 +1,127 @@ +/* + * Copyright 2011-2013 Sebastian Kügler + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +Item { + id: containmentConfig + + width: 400 + height: 320 + + property bool open: false + + PlasmaComponents.ToolButton { + id: cfgbutton + + width: root.iconSize + height: width + + iconSource: "configure" + onClicked: open = !open; + } + + PlasmaCore.FrameSvgItem { + id: configFrame + anchors.fill: parent + imagePath: "widgets/background" + opacity: open ? 1 : 0 + Behavior on opacity { PropertyAnimation {} } + + Row { + anchors.fill: parent + anchors.margins: parent.margins.top + + spacing: configFrame.margins.top/2 + + Column { + width: parent.width / 2 - (configFrame.margins.top) + spacing: configFrame.margins.top/2 + PlasmaComponents.Label { + width: parent.width + horizontalAlignment: Text.AlignRight + text: "Visual debugging:" + } + PlasmaComponents.Label { + width: parent.width + horizontalAlignment: Text.AlignRight + text: "Icon size:" + } + PlasmaComponents.Label { + width: parent.width + horizontalAlignment: Text.AlignRight + text: "Applethandle delay:" + } + PlasmaComponents.Label { + width: parent.width + horizontalAlignment: Text.AlignRight + text: "Halo move duration:" + } + PlasmaComponents.Label { + width: parent.width + horizontalAlignment: Text.AlignRight + text: "Halo opacity:" + } + } + + Column { + spacing: configFrame.margins.top/2 + PlasmaComponents.CheckBox { + checked: root.debug + onCheckedChanged: { + print("Debug is now " + checked); + root.debug = checked; + } + } + PlasmaComponents.TextField { + text: root.iconSize + onTextChanged: { + print("Set icon size to " + text); + root.iconSize = text; + } + } + PlasmaComponents.TextField { + text: root.handleDelay + onTextChanged: { + print("Set handle delay to " + text); + root.handleDelay = text; + } + } + PlasmaComponents.TextField { + text: placeHolderPaint.moveDuration + onTextChanged: { + print("Set move duration to " + text); + placeHolderPaint.moveDuration = text; + } + } + PlasmaComponents.TextField { + text: root.haloOpacity + onTextChanged: { + print("Set halo opacity to " + text); + root.haloOpacity = text; + } + } + } + } + } +} diff --git a/containments/desktop/package/contents/ui/main.qml b/containments/desktop/package/contents/ui/main.qml new file mode 100644 index 0000000000..9b72842028 --- /dev/null +++ b/containments/desktop/package/contents/ui/main.qml @@ -0,0 +1,315 @@ +// -*- coding: iso-8859-1 -*- +/* + * Copyright 2011-2013 Sebastian Kügler + * Copyright 2011 Marco Martin + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.draganddrop 2.0 as DragDrop + +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +DragDrop.DropArea { + id: root + + property Item toolBox + + property bool debug: false + property int handleDelay: 800 + property real haloOpacity: 0.5 + property bool pressAndHoldHandle: false + + property int iconSize: 16 + property int iconWidth: iconSize + property int iconHeight: iconWidth + + onIconHeightChanged: updateGridSize() + + function updateGridSize() + { + print("Updategridsize"); + LayoutManager.cellSize.width = root.iconWidth + toolBoxSvg.elementSize("left").width + toolBoxSvg.elementSize("right").width + LayoutManager.cellSize.height = root.iconHeight + toolBoxSvg.elementSize("top").height + toolBoxSvg.elementSize("bottom").height; + LayoutManager.defaultAppletSize.width = LayoutManager.cellSize.width * 6; + LayoutManager.defaultAppletSize.height = LayoutManager.cellSize.height * 6; + layoutTimer.restart() + } + + function addApplet(applet, x, y) { + var component = Qt.createComponent("AppletAppearance.qml"); + var e = component.errorString(); + if (e != "") { + print("Error loading AppletAppearance.qml: " + component.errorString()); + } + + var container = component.createObject(resultsFlow) + + applet.parent = container + applet.visible = true; + + container.category = "Applet-"+applet.id; + var config = LayoutManager.itemsConfig[container.category]; + + //Not a valid size? reset + if (config === undefined || config.width === undefined || config.height === undefined || + config.width <= 0 || config.height <=0) { + container.width = LayoutManager.defaultAppletSize.width; + container.height = LayoutManager.defaultAppletSize.height; + } else { + container.width = config.width; + container.height = config.height; + } + container.applet = applet; + //coordinated passed by param? + if ( x >= 0 && y >= 0) { + container.x = x; + container.y = y; + //coordinates stored? + } else if (config !== undefined && config.x !== undefined && config.y !== undefined && + config.x >= 0 && config.y >= 0) { + container.x = config.x; + container.y = config.y; + } + + //rotation sotired and significative? + if (config !== undefined && config.rotation !== undefined && + (config.rotation > 5 || config.rotation < -5)) { + container.rotation = config.rotation; + } + + LayoutManager.itemGroups[container.category] = container; + print("Applet " + container.category + applet.title + " added at" + container.x + " " + container.y); + + if (container.x >= 0 && container.y >= 0) { + LayoutManager.positionItem(container); + } + } + + onDragEnter: { + placeHolder.width = LayoutManager.defaultAppletSize.width; + placeHolder.height = LayoutManager.defaultAppletSize.height; + placeHolder.x = event.x - placeHolder.width / 2; + placeHolder.y = event.y - placeHolder.width / 2; + LayoutManager.positionItem(placeHolder); + LayoutManager.setSpaceAvailable(placeHolder.x, placeHolder.y, placeHolder.width, placeHolder.height, true); + placeHolderPaint.opacity = root.haloOpacity; + } + + onDragMove: { + placeHolder.width = LayoutManager.defaultAppletSize.width; + placeHolder.height = LayoutManager.defaultAppletSize.height; + placeHolder.x = event.x - placeHolder.width / 2; + placeHolder.y = event.y - placeHolder.width / 2; + LayoutManager.positionItem(placeHolder); + LayoutManager.setSpaceAvailable(placeHolder.x, placeHolder.y, placeHolder.width, placeHolder.height, true); + placeHolderPaint.opacity = root.haloOpacity; + } + + onDragLeave: { + placeHolderPaint.opacity = 0; + } + + onDrop: { + placeHolderPaint.opacity = 0; + plasmoid.processMimeData(event.mimeData, event.x - placeHolder.width / 2, event.y - placeHolder.height / 2); + } + + + Connections { + target: plasmoid + + onAppletAdded: { + addApplet(applet, x, y); + //clean any eventual invalid chunks in the config + LayoutManager.save(); + } + + onAppletRemoved: { + //clean any eventual invalid chunks in the config + print("Applet REMOVED!!!!!!!!!"); + LayoutManager.removeApplet(applet); + LayoutManager.save(); + } + } + + PlasmaCore.Svg { + id: toolBoxSvg + imagePath: "widgets/toolbox" + property int rightBorder: elementSize("right").width + property int topBorder: elementSize("top").height + property int bottomBorder: elementSize("bottom").height + property int leftBorder: elementSize("left").width + } + PlasmaCore.Svg { + id: configIconsSvg + imagePath: "widgets/configuration-icons" + } + + Item { + id: resultsFlow + anchors.fill: parent + + anchors { + top: parent.top + topMargin: 5 + horizontalCenter: parent.horizontalCenter + } + + //This is just for event compression when a lot of boxes are created one after the other + Timer { + id: layoutTimer + repeat: false + running: false + interval: 100 + onTriggered: { + LayoutManager.resetPositions() + for (var i=0; i 0 + NumberAnimation { + duration: placeHolderPaint.moveDuration + easing.type: Easing.InOutQuad + } + } + Behavior on y { + enabled: placeHolderPaint.opacity > 0 + NumberAnimation { + duration: placeHolderPaint.moveDuration + easing.type: Easing.InOutQuad + } + } + Behavior on width { + enabled: placeHolderPaint.opacity > 0 + NumberAnimation { + duration: placeHolderPaint.moveDuration + easing.type: Easing.InOutQuad + } + } + } + } + + Component.onCompleted: { + placeHolderPaint.opacity = 0; + placeHolderPaint.visible = true; + print("Containment completed."); + LayoutManager.resultsFlow = resultsFlow + LayoutManager.plasmoid = plasmoid + updateGridSize() + //plasmoid.containmentType = "DesktopContainment" + + LayoutManager.restore() + + for (var i = 0; i < plasmoid.applets.length; ++i) { + var applet = plasmoid.applets[i] + addApplet(applet, -1, -1); + } + //clean any eventual invalid chunks in the config + LayoutManager.save(); + } +} diff --git a/containments/desktop/package/metadata.desktop b/containments/desktop/package/metadata.desktop new file mode 100644 index 0000000000..2ab7289592 --- /dev/null +++ b/containments/desktop/package/metadata.desktop @@ -0,0 +1,152 @@ +[Desktop Entry] +Name=Desktop +Name[af]=Werkskerm +Name[ar]=سطح المكتب +Name[ast]=Escritoriu +Name[be]=Працоўны стол +Name[be@latin]=Rabočy stoł +Name[bg]=Работен плот +Name[bn]=ডেস্কটপ +Name[bn_IN]=ডেস্কটপ +Name[br]=Gorretaol +Name[ca]=Escriptori +Name[ca@valencia]=Escriptori +Name[cs]=Pracovní plocha +Name[csb]=Pùlt +Name[cy]=Penbwrdd +Name[da]=Skrivebord +Name[de]=Arbeitsfläche +Name[el]=Επιφάνεια εργασίας +Name[en_GB]=Desktop +Name[eo]=Labortablo +Name[es]=Escritorio +Name[et]=Töölaud +Name[eu]=Mahaigaina +Name[fa]=رومیزی +Name[fi]=Työpöytä +Name[fr]=Bureau +Name[fy]=Buroblêd +Name[ga]=Deasc +Name[gl]=Escritorio +Name[gu]=ડેસ્કટોપ +Name[he]=שולחן עבודה +Name[hi]=डेस्कटॉप +Name[hne]=डेस्कटाप +Name[hsb]=Dźěłowy powjerch +Name[hu]=Munkaasztal +Name[ia]=Scriptorio +Name[id]=Desktop +Name[it]=Desktop +Name[ka]=სამუშაო დაფა +Name[kk]=Жұмыс үстелі +Name[kn]=ಗಣಕತೆರೆ +Name[ko]=데스크톱 +Name[ku]=Sermasê +Name[lt]=Darbastalis +Name[mai]=डेस्कटाप +Name[mk]=Работна површина +Name[ml]=പണിയിടം +Name[mr]=डेस्कटॉप +Name[ms]=Ruang Kerja +Name[nb]=Skrivebord +Name[nds]=Schriefdisch +Name[ne]=डेस्कटप +Name[nl]=Bureaublad +Name[nn]=Skrivebord +Name[oc]=Burèu +Name[or]=ଡ଼େସ୍କଟପ +Name[pa]=ਡੈਸਕਟਾਪ +Name[pl]=Pulpit +Name[pt]=Ambiente de Trabalho +Name[pt_BR]=Área de trabalho +Name[ro]=Birou +Name[se]=Čállinbeavdi +Name[si]=වැඩතලය +Name[sk]=Plocha +Name[sl]=Namizje +Name[sr]=Површ +Name[sr@ijekavian]=Површ +Name[sr@ijekavianlatin]=Površ +Name[sr@latin]=Površ +Name[sv]=Skrivbord +Name[ta]=பணிமேசை +Name[te]=రంగస్ఠలం +Name[tg]=Мизи корӣ +Name[th]=พื้นที่ทำงาน +Name[tr]=Masaüstü +Name[uk]=Стільниця +Name[uz]=Ish stoli +Name[uz@cyrillic]=Иш столи +Name[vi]=Màn hình nền +Name[wa]=Sicribanne +Name[xh]=Desktop +Name[x-test]=xxDesktopxx +Name[zh_CN]=桌面 +Name[zh_TW]=桌面 +Comment=A clean and simple layout +Comment[bs]=Čist i jednostavan Izgled +Comment[ca]=Una disposició neta i senzilla +Comment[ca@valencia]=Una disposició neta i senzilla +Comment[cs]=Čisté a jednoduché rozvržení +Comment[da]=Et rent og simpelt layout +Comment[de]=Ein klares und einfaches Layout +Comment[el]=Μια σαφής και απλή διάταξη +Comment[es]=Un esquema sencillo y claro +Comment[et]=Puhas ja lihtne paigutus +Comment[eu]=Diseinu garbi eta xumea +Comment[fi]=Selkeä ja yksinkertainen asettelu +Comment[fr]=Une disposition simple et épurée +Comment[gl]=Unha disposición sinxela e limpa +Comment[hu]=Egy tiszta és egyszerű elrendezés +Comment[ia]=Un disposition simple e munde +Comment[it]=Una disposizione semplice e pulita +Comment[kk]=Анық және қарапайым қалыпы +Comment[km]=ប្លង់​សាមញ្ញ ហើយ​​ស្អាត +Comment[ko]=깨끗하고 정돈된 레이아웃 +Comment[lt]=Švarus ir paprastas Išdėstymas +Comment[mr]=स्वच्छ व साधी रचना +Comment[nb]=En ren og enkel utforming +Comment[nds]=En schier un eenfach Utsehn +Comment[nl]=Een schone en simpele opmaak +Comment[pa]=ਸਾਫ਼ ਅਤੇ ਸਧਾਰਨ ਲੇਆਉਟ +Comment[pl]=Schludny i prosty układ +Comment[pt]=Uma disposição limpa e simples +Comment[pt_BR]=Um leiaute limpo e simples +Comment[ro]=Aranjament curat și simplu +Comment[ru]=Ясный и простой шаблон +Comment[sk]=Čisté a jednoduché rozloženie +Comment[sl]=Čist in preprost razpored +Comment[sr]=Чист и једноставан распоред +Comment[sr@ijekavian]=Чист и једноставан распоред +Comment[sr@ijekavianlatin]=Čist i jednostavan raspored +Comment[sr@latin]=Čist i jednostavan raspored +Comment[sv]=En ren och enkel layout +Comment[tr]=Temiz ve basit bir yerleşim +Comment[uk]=Просте компонування +Comment[x-test]=xxA clean and simple layoutxx +Comment[zh_CN]=简洁的布局 +Comment[zh_TW]=乾淨、簡單的佈局 +Encoding=UTF-8 + +Type=Service +Icon=user-desktop +X-KDE-ParentApp= +X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment + +X-KDE-PluginInfo-Author=Sebastian Kügler +X-KDE-PluginInfo-Email=sebas@kde.org +X-KDE-PluginInfo-Name=org.kde.desktopcontainment +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=http://plasma.kde.org/ +X-KDE-PluginInfo-Category=Containments +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-PluginInfo-Version=0.1 + +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml +X-Plasma-RemoteLocation= +X-Plasma-RequiredExtensions=LaunchApp,http,localio,networkio +X-Plasma-ContainmentCategories=desktop diff --git a/containments/desktop/tests/CMakeLists.txt b/containments/desktop/tests/CMakeLists.txt new file mode 100644 index 0000000000..a5eb468d11 --- /dev/null +++ b/containments/desktop/tests/CMakeLists.txt @@ -0,0 +1,6 @@ + + +# Background test plasmoid +install(DIRECTORY org.kde.tests.background/ DESTINATION ${DATA_INSTALL_DIR}/plasma/plasmoids/org.kde.tests.background) +install(FILES org.kde.tests.background/metadata.desktop DESTINATION ${SERVICES_INSTALL_DIR} RENAME plasma-applet-org.kde.tests.background.desktop) + diff --git a/containments/desktop/tests/framehandle-resizing-draft.qml b/containments/desktop/tests/framehandle-resizing-draft.qml new file mode 100644 index 0000000000..c521503c5f --- /dev/null +++ b/containments/desktop/tests/framehandle-resizing-draft.qml @@ -0,0 +1,100 @@ +/* + * Copyright 2013 Sebastian Kügler + * + * This program 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 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore +import org.kde.kquickcontrolsaddons 0.1 as KQuickControlsAddons + +Rectangle { + + property bool showAppletHandle: mouseListener.containsMouse + + width: 600 + height: 600 + color: "black" + anchors.fill: parent + + property int w: 30 + + Rectangle { + id: applet + color: "blue" + x: 100 + y: 60 + width: 400 + height: 400 + + KQuickControlsAddons.MouseEventListener { + /* The MouseEventListener + * + * this is the parent of the applet and handle, + * it's wider than it's alloted position, however, + * and unclipped. It carries the whole area that + * is hoverable. + */ + id: mouseListener + anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } + width: parent.width+w; + hoverEnabled: true + + onContainsMouseChanged: print("Mouse is " + containsMouse); + + PlasmaCore.FrameSvgItem { + id: backgroundFrame + /* The applet+handle frame + * + * This is the growing frame containing the applet + * and handle. + * + */ + imagePath: "widgets/background" + z: parent.z+1 + anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } + width: showAppletHandle ? parent.width: parent.width-w; + Behavior on width { PropertyAnimation {}} + + // DragArea goes here + + // Handle itself goes here + } + Rectangle { + /* The Applet + * + * Sits on top of the frame, but doesn't resize with it, + * only with the whole allotted area. + * + * As it's a child of the MouseEventListener, the applet + * still receives all input. + */ + id: yellow + color: "green" + z: parent.z+1 + x: 0 + backgroundFrame.margins.left + y: 0 + backgroundFrame.margins.top + width: applet.width - (backgroundFrame.margins.left + backgroundFrame.margins.right) + height: applet.width - (backgroundFrame.margins.top + backgroundFrame.margins.bottom) + MouseArea { + anchors.fill: parent + onClicked: print("Applet clicked."); + } + } + } + } + onShowAppletHandleChanged: print("Active? " + showAppletHandle); +} diff --git a/containments/desktop/tests/org.kde.tests.background/contents/code/testbackground.qml b/containments/desktop/tests/org.kde.tests.background/contents/code/testbackground.qml new file mode 100644 index 0000000000..e4813d5636 --- /dev/null +++ b/containments/desktop/tests/org.kde.tests.background/contents/code/testbackground.qml @@ -0,0 +1,141 @@ +/* + * Copyright 2013 Sebastian Kügler + * + * This program 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 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 Library 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. + */ + +import QtQuick 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents +import org.kde.plasma.extras 0.1 as PlasmaExtras +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: root + width: 200 + height: 300 + clip: true + + Rectangle { + color: "white" + opacity: 0.0 + anchors.fill: parent + } + PlasmaExtras.Title { + id: title + anchors { top: parent.top; left: parent.left; right: parent.right; } + text: i18n("Test Applet") + } + PlasmaExtras.Paragraph { + id: para + anchors { top: title.bottom; left: parent.left; right: parent.right; } + text: { + var o = "x: " + root.x; + o += "
    y: " + root.y; + o += "
    w: " + root.width; + o += "
    h: " + root.height; + //o += "

    s: " + plasmoid.availableScreenRect(screen[0]); + return o; + } + } + + PlasmaComponents.ButtonColumn { + visible: root.width + root.height > 500 + anchors { verticalCenter: parent.verticalCenter; horizontalCenter: parent.horizontalCenter; } + spacing: 12 + //anchors.fill: parent + PlasmaComponents.Button { + text: hint + iconSource: "view-refresh" + property string hint: "NoBackground" + checkable: true + checked: plasmoid.backgroundHints == hint + onClicked: saveHints(hint); + } + PlasmaComponents.Button { + text: hint + iconSource: "view-refresh" + property string hint: "TranslucentBackground" + checkable: true + checked: plasmoid.backgroundHints == hint + onClicked: saveHints(hint); + } + PlasmaComponents.Button { + text: hint + iconSource: "view-refresh" + property string hint: "NormalBackground" + checkable: true + checked: plasmoid.backgroundHints == hint + onClicked: saveHints(hint); + } + PlasmaComponents.Button { + text: hint + iconSource: "view-refresh" + property string hint: "DefaultBackground" + checkable: true + checked: plasmoid.backgroundHints == hint + onClicked: saveHints(hint); + } + } + + function saveHints(hint) { + print("writing to config: " + hint); + plasmoid.writeConfig("bgHints", hint); + } + + function configChanged() + { +// //serviceUrl = plasmoid.readConfig("serviceUrl"); +// var u = plasmoid.readConfig("userName"); +// var s = plasmoid.readConfig("serviceUrl"); +// print(" @@@@@@@@@@@@@@@@@@ configChanged()" + u + " s: " + s); +// +// if (u != "") { +// userName = u; +// } +// if (s != "") { +// serviceUrl = s; +// imageSourc + var bgh = "DefaultBackground"; + var _bgh = plasmoid.readConfig("bgHints"); + print("-- " + _bgh); + if (_bgh != "") { + bgh = _bgh; + } else { + //bgh = ; + print("Default"); + } +// if (typeof(bgh) == "undefined" || bgh == undefined || bgh == "") { +// } + print(" ----------? Read Background Hints from Config: " + bgh + " " + (typeof(_bgh))); + + //plasmoid.backgroundHints = "DefaultBackground"; + plasmoid.backgroundHints = "NormalBackground"; + } + + Timer { + repeat: false + //running: true + interval: 100 + //onTriggered: configChanged() + } + + Component.onCompleted: { + //plasmoid.backgroundHints = "NoBackground" + //plasmoid.addEventListener('ConfigChanged', configChanged); + //plasmoid.configurationRequired = true + configChanged() + } +} \ No newline at end of file diff --git a/containments/desktop/tests/org.kde.tests.background/contents/plasmatepreviewerlog.txt b/containments/desktop/tests/org.kde.tests.background/contents/plasmatepreviewerlog.txt new file mode 100644 index 0000000000..fd868ad6fe --- /dev/null +++ b/containments/desktop/tests/org.kde.tests.background/contents/plasmatepreviewerlog.txt @@ -0,0 +1,498 @@ +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00166 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00178 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00194 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c001ac +Warning: QWidget::setLayout: Attempting to set QLayout "" on Publisher "", when the QLayout already has a parent +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c001c3 +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c001ce +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c001e4 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c001f5 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00266 +Warning: QFont::setPixelSize: Pixel size <= 0 (0) +Warning: static bool QDeclarativeMetaType::isModule(const QByteArray&, int, int) Qt 4.7 import detected; please note that Qt 4.7 is directly reusable as QtQuick 1.x with no code changes. Continuing, but startup time will be slower. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0028e +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0029b +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c002a6 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0030c +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00328 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00317 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00333 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0034f +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0033e +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0035a +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Debug: Enchant dict for "en_US" 0x2a7dfb0 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c00365 +Debug: Enchant dict for "en_US" 0x3568e30 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5c0037c +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00175 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/.kde4/share/apps/plasmate/testbackground/contents/code/testbackground.qml:52: ReferenceError: Can't find variable: screen +Warning: file:///home/sebas/.kde4/share/apps/plasmate/testbackground/contents/code/testbackground.qml:52: ReferenceError: Can't find variable: screen +Warning: file:///home/sebas/.kde4/share/apps/plasmate/testbackground/contents/code/testbackground.qml:52: ReferenceError: Can't find variable: screen +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QWidget::setLayout: Attempting to set QLayout "" on Publisher "", when the QLayout already has a parent +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001af +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001ba +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001dc +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001e7 +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001f2 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e001fd +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00208 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00213 +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e0021e +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00229 +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00234 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e0023f +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e0024a +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00255 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e00260 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: QPainter::begin: Paint device returned engine == 0, type: 2 +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Warning: file:///home/sebas/kdesvn/install/lib/kde4/imports/org/kde/plasma/components/Button.qml:194:5: QML Row: Possible anchor loop detected on fill. +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" +Warning: X Error: BadWindow (invalid Window parameter) 3 + Major opcode: 20 (X_GetProperty) + Resource id: 0x5e0026b +Debug: tempPackagePath "/home/sebas/.kde4/share/apps/plasmate/testbackground.plasmoid" +Debug: m_projectPath "/home/sebas/.kde4/share/apps/plasmate/testbackground/" diff --git a/containments/desktop/tests/org.kde.tests.background/metadata.desktop b/containments/desktop/tests/org.kde.tests.background/metadata.desktop new file mode 100644 index 0000000000..fb58dc7f00 --- /dev/null +++ b/containments/desktop/tests/org.kde.tests.background/metadata.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +Comment=Testing background settings in Plasma Quick Containments +Comment[bs]=Testiranje pozadinskih postavki u Plasma Quick Containmentsu +Comment[ca]=Prova de la configuració del fons dels «Plasma Quick Containments» +Comment[ca@valencia]=Prova de la configuració del fons dels «Plasma Quick Containments» +Comment[da]=Test af baggrundsindstillinger i Plasma Quick-beholdere +Comment[de]=Test von Hintergrundeinstellungen in „Plasma Quick Containments“ +Comment[el]=Έλεγχος των ρυθμίσεων φόντου στους υποδοχείς του Plasma Quick +Comment[es]=Prueba de las preferencias del fondo de los contenedores de Plasma Quick +Comment[eu]=Atzeko planoko ezarpenen proba Plasma Quick edukiontzietan +Comment[fi]=Plasma Quick -sovelmasäiliöiden tausta-asetusten testi +Comment[fr]=Test des paramètres d'arrière plan dans un conteneur rapide Plasma +Comment[gl]=Probas da configuración do fondo nos Plasma Quick Containments +Comment[hu]=Háttérbeállítás tesztelése a Plasma gyors elhatárolásban +Comment[ia]=Essayante preferentias de fundo in Plasma Quick Containments +Comment[kk]=Plasma шұғыл контейнерде аясының параметрлерін тексеру +Comment[ko]=Plasma Quick 컨테이너의 배경 설정 시험 +Comment[nb]=Tester bakgrunnsinnstillinger i Plasma Quick Containments +Comment[nds]=Achtergrund-Instellen binnen gau Plasma-Gelaatsen utproberen +Comment[nl]=Achtergrondinstellingen testen in Plasma Quick Containments +Comment[pl]=Testowanie ustawień tła w Plasma Quick Containments +Comment[pt]=Configuração de testes do fundo dos contentores do Plasma Quick +Comment[pt_BR]=Configuração de testes do plano de fundo dos contêineres do Plasma Quick +Comment[sk]=Testujem nastavenia pozadia v Plasma Quick Containments +Comment[sl]=Preizkušanje nastavitev ozadij v vsebnikih Plasma Quick +Comment[sr]=Испробавање поставки позадине у плазма‑квик садржаоцима +Comment[sr@ijekavian]=Испробавање поставки позадине у плазма‑квик садржаоцима +Comment[sr@ijekavianlatin]=Isprobavanje postavki pozadine u Plasma Quick sadržaocima +Comment[sr@latin]=Isprobavanje postavki pozadine u Plasma Quick sadržaocima +Comment[sv]=Prova bakgrundsinställningar i Plasma Quick-omgivningar +Comment[tr]=Plasma Hızlı Barındırmasında arkaplan ayarlarını sınama +Comment[uk]=Перевірка параметрів тла у контейнерах мобільної Плазми +Comment[x-test]=xxTesting background settings in Plasma Quick Containmentsxx +Comment[zh_CN]=在 Plasma Quick 容器中测试背景设置 +Comment[zh_TW]=在 Plasma Quick Containments 中測試背景設定 +Encoding=UTF-8 +Icon=text-frame-link +Keywords= +Name=Background Test +Name[bs]=Pozadinski test +Name[ca]=Prova del fons +Name[ca@valencia]=Prova del fons +Name[da]=Baggrundstest +Name[de]=Hintergrundtest +Name[el]=Έλεγχος φόντου +Name[es]=Prueba del fondo +Name[eu]=Atzeko planoko proba +Name[fi]=Taustatesti +Name[fr]=Test de l'arrière plan +Name[gl]=Proba do fondo +Name[hu]=Háttér teszt +Name[ia]=Essayo de fundo +Name[kk]=Аясын тексеру +Name[ko]=배경 시험 +Name[nb]=Bakgrunnstest +Name[nds]=Achtergrund-Test +Name[nl]=Achtergrondtest +Name[pa]=ਬੈਕਗਰਾਊਂਡ ਟੈਸਟ +Name[pl]=Test tła +Name[pt]=Teste de Fundo +Name[pt_BR]=Teste do plano de fundo +Name[sk]=Test pozadia +Name[sl]=Preizkus ozadja +Name[sr]=Проба позадине +Name[sr@ijekavian]=Проба позадине +Name[sr@ijekavianlatin]=Proba pozadine +Name[sr@latin]=Proba pozadine +Name[sv]=Bakgrundsprov +Name[tr]=Arkaplan Sınaması +Name[uk]=Перевірка тла +Name[x-test]=xxBackground Testxx +Name[zh_CN]=背景测试 +Name[zh_TW]=背景測試 +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Sebastian Kügler +X-KDE-PluginInfo-Category=Utilities +X-KDE-PluginInfo-Email=sebas@kde.org +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=org.kde.tests.background +X-KDE-PluginInfo-Version=1 +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=Plasma/Applet +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=code/testbackground.qml +X-Plasma-RemoteLocation= diff --git a/containments/panel/Messages.sh b/containments/panel/Messages.sh new file mode 100644 index 0000000000..b1326bce1a --- /dev/null +++ b/containments/panel/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp +$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_panel.pot +rm -f rc.cpp diff --git a/containments/panel/contents/code/LayoutManager.js b/containments/panel/contents/code/LayoutManager.js new file mode 100644 index 0000000000..914ac265c0 --- /dev/null +++ b/containments/panel/contents/code/LayoutManager.js @@ -0,0 +1,158 @@ +/* + * Copyright 2013 Marco Martin + * + * This program 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, 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 Library 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. + */ + +.pragma library + + +var layout; +var root; +var plasmoid; + + +function restore() { + var configString = String(plasmoid.configuration.AppletOrder) + + //array, a cell for encoded item order + var itemsArray = configString.split(";"); + + //map applet id->order in panel + var idsOrder = new Object(); + //map order in panel -> applet pointer + var appletsOrder = new Object(); + + for (var i = 0; i < itemsArray.length; i++) { + //property name: applet id + //property value: order + idsOrder[itemsArray[i]] = i; + } + + for (var i = 0; i < plasmoid.applets.length; ++i) { + if (idsOrder[plasmoid.applets[i].id] !== undefined) { + appletsOrder[idsOrder[plasmoid.applets[i].id]] = plasmoid.applets[i]; + //ones that weren't saved in AppletOrder go to the end + } else { + appletsOrder["unordered"+i] = plasmoid.applets[i]; + } + } + + //finally, restore the applets in the correct order + for (var i in appletsOrder) { + root.addApplet(appletsOrder[i], -1, -1) + } + //rewrite, so if in the orders there were now invalid ids or if some were missing creates a correct list instead + save(); +} + +function save() { + var ids = new Array(); + for (var i = 0; i < layout.children.length; ++i) { + var child = layout.children[i]; + + if (child.applet) { + ids.push(child.applet.id); + } + } + plasmoid.configuration.AppletOrder = ids.join(';'); +} + +function insertBefore(item1, item2) { + if (item1 === item2) { + return; + } + var removed = new Array(); + + var child; + + var i; + for (i = layout.children.length - 1; i >= 0; --i) { + child = layout.children[i]; + removed.push(child); + child.parent = root; + + if (child === item1) { + break; + } + } + + item2.parent = layout; + + for (var j = removed.length - 1; j >= 0; --j) { + removed[j].parent = layout; + } + return i; +} + +function insertAfter(item1, item2) { + if (item1 === item2) { + return; + } + var removed = new Array(); + + var child; + + var i; + for (i = layout.children.length - 1; i >= 0; --i) { + child = layout.children[i]; + if (child === item1) { + break; + } + + removed.push(child); + child.parent = root; + } + + item2.parent = layout; + + for (var j = removed.length - 1; j >= 0; --j) { + removed[j].parent = layout; + } + return i; +} + +function insertAtIndex(item, position) { + var removedItems = new Array(); + + for (var i = position; i < layout.children.length; ++i) { + var child = layout.children[position]; + child.parent = root; + removedItems.push(child); + } + + item.parent = layout; + for (var i in removedItems) { + removedItems[i].parent = layout; + } +} + +function insertAtCoordinates(item, x, y) { + var child = layout.childAt(x, y); + + if (!child || child === item) { + return -1; + } + item.parent = root; + + //PlasmaCore.Types.Vertical = 3 + if ((plasmoid.formFactor === 3 && y < child.y + child.height/2) || + (plasmoid.formFactor !== 3 && x < child.x + child.width/2)) { + return insertBefore(child, item); + } else { + return insertAfter(child, item); + } +} diff --git a/containments/panel/contents/config/main.xml b/containments/panel/contents/config/main.xml new file mode 100644 index 0000000000..61a525b9b8 --- /dev/null +++ b/containments/panel/contents/config/main.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/containments/panel/contents/ui/ConfigOverlay.qml b/containments/panel/contents/ui/ConfigOverlay.qml new file mode 100644 index 0000000000..d2aa42b8bb --- /dev/null +++ b/containments/panel/contents/ui/ConfigOverlay.qml @@ -0,0 +1,292 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.1 +import QtQuick.Layouts 1.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 + +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +MouseArea { + id: configurationArea + z: 1000 + anchors { + fill: parent + rightMargin: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? toolBox.width : 0 + bottomMargin: (plasmoid.formFactor === PlasmaCore.Types.Vertical) ? toolBox.height : 0 + } + hoverEnabled: true + + property bool isResizingLeft: false + property bool isResizingRight: false + property Item currentApplet + + property int lastX + property int lastY + + onPositionChanged: { + if (currentApplet && currentApplet.applet && + currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + if ((mouse.y - handle.y) < units.largeSpacing || + (mouse.y - handle.y) > (handle.height - units.largeSpacing)) { + configurationArea.cursorShape = Qt.SizeVerCursor; + } else { + configurationArea.cursorShape = Qt.ArrowCursor; + } + } else { + if ((mouse.x - handle.x) < units.largeSpacing || + (mouse.x - handle.x) > (handle.width - units.largeSpacing)) { + configurationArea.cursorShape = Qt.SizeHorCursor; + } else { + configurationArea.cursorShape = Qt.ArrowCursor; + } + } + } else { + configurationArea.cursorShape = Qt.ArrowCursor; + } + + if (pressed) { + if (currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + + if (isResizingLeft) { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + handle.y += (mouse.y - lastY); + handle.height = currentApplet.height + (currentApplet.y - handle.y); + } else { + handle.x += (mouse.x - lastX); + handle.width = currentApplet.width + (currentApplet.x - handle.x); + } + + lastX = mouse.x; + lastY = mouse.y; + return; + + } else if (isResizingRight) { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + handle.height = mouse.y - handle.y; + } else { + handle.width = mouse.x - handle.x; + } + + lastX = mouse.x; + lastY = mouse.y; + return; + } + } + + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + currentApplet.y += (mouse.y - lastY); + handle.y = currentApplet.y; + } else { + currentApplet.x += (mouse.x - lastX); + handle.x = currentApplet.x; + } + + lastX = mouse.x; + lastY = mouse.y; + + var item = currentLayout.childAt(mouse.x, mouse.y); + + if (item && item !== placeHolder) { + placeHolder.width = item.width; + placeHolder.height = item.height; + placeHolder.parent = configurationArea; + var posInItem = mapToItem(item, mouse.x, mouse.y); + + if ((plasmoid.formFactor === PlasmaCore.Types.Vertical && posInItem.y < item.height/2) || + (plasmoid.formFactor !== PlasmaCore.Types.Vertical && posInItem.x < item.width/2)) { + LayoutManager.insertBefore(item, placeHolder); + } else { + LayoutManager.insertAfter(item, placeHolder); + } + } + + } else { + var item = currentLayout.childAt(mouse.x, mouse.y); + if (root.dragOverlay && item && item !== lastSpacer) { + root.dragOverlay.currentApplet = item; + } else { + root.dragOverlay.currentApplet = null; + } + } + } + onCurrentAppletChanged: { + if (!root.dragOverlay.currentApplet) { + return; + } + + handle.x = currentApplet.x; + handle.y = currentApplet.y; + handle.width = currentApplet.width; + handle.height = currentApplet.height; + } + onPressed: { + if (!root.dragOverlay.currentApplet) { + return; + } + + if (currentApplet.applet.pluginName == "org.kde.plasma.panelspacer") { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + if ((mouse.y - handle.y) < units.largeSpacing) { + configurationArea.isResizingLeft = true; + configurationArea.isResizingRight = false; + } else if ((mouse.y - handle.y) > (handle.height - units.largeSpacing)) { + configurationArea.isResizingLeft = false; + configurationArea.isResizingRight = true; + } else { + configurationArea.isResizingLeft = false; + configurationArea.isResizingRight = false; + } + + } else { + if ((mouse.x - handle.x) < units.largeSpacing) { + configurationArea.isResizingLeft = true; + configurationArea.isResizingRight = false; + } else if ((mouse.x - handle.x) > (handle.width - units.largeSpacing)) { + configurationArea.isResizingLeft = false; + configurationArea.isResizingRight = true; + } else { + configurationArea.isResizingLeft = false; + configurationArea.isResizingRight = false; + } + } + } + + lastX = mouse.x; + lastY = mouse.y; + placeHolder.width = currentApplet.width; + placeHolder.height = currentApplet.height; + LayoutManager.insertBefore(currentApplet, placeHolder); + currentApplet.parent = root; + currentApplet.z = 900; + } + onReleased: { + if (!root.dragOverlay.currentApplet) { + return; + } + + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + currentApplet.applet.configuration.length = handle.height; + } else { + currentApplet.applet.configuration.length = handle.width; + } + + configurationArea.isResizingLeft = false; + configurationArea.isResizingRight = false; + + LayoutManager.insertBefore(placeHolder, currentApplet); + placeHolder.parent = configurationArea; + currentApplet.z = 1; + + handle.x = currentApplet.x; + handle.y = currentApplet.y; + handle.width = currentApplet.width; + handle.height = currentApplet.height; + LayoutManager.save(); + } + Item { + id: placeHolder + visible: configurationArea.containsMouse + Layout.fillWidth: currentApplet ? currentApplet.Layout.fillWidth : false + Layout.fillHeight: currentApplet ? currentApplet.Layout.fillHeight : false + } + + Connections { + target: currentApplet + onXChanged: handle.x = currentApplet.x + onYChanged: handle.y = currentApplet.y + onWidthChanged: handle.width = currentApplet.width + onHeightChanged: handle.height = currentApplet.height + } + + Rectangle { + id: handle + visible: configurationArea.containsMouse + color: theme.backgroundColor + radius: 3 + opacity: currentApplet ? 0.5 : 0 + PlasmaCore.IconItem { + source: "transform-move" + width: Math.min(parent.width, parent.height) + height: width + anchors.centerIn: parent + } + Rectangle { + anchors { + left: parent.left + top: parent.top + bottom: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? parent.bottom : undefined + right: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? undefined : parent.right + } + visible: currentApplet.applet.pluginName == "org.kde.plasma.panelspacer" + width: units.largeSpacing + height: units.largeSpacing + color: theme.textColor + } + Rectangle { + anchors { + right: parent.right + top: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? parent.top : undefined + bottom: parent.bottom + left: (plasmoid.formFactor !== PlasmaCore.Types.Vertical) ? undefined : parent.left + } + visible: currentApplet.applet.pluginName == "org.kde.plasma.panelspacer" + width: units.largeSpacing + height: units.largeSpacing + color: theme.textColor + } + Behavior on x { + enabled: !configurationArea.pressed + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on y { + enabled: !configurationArea.pressed + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on width { + enabled: !configurationArea.pressed + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on height { + enabled: !configurationArea.pressed + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + Behavior on opacity { + NumberAnimation { + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + } +} diff --git a/containments/panel/contents/ui/main.qml b/containments/panel/contents/ui/main.qml new file mode 100644 index 0000000000..3dd531fe5b --- /dev/null +++ b/containments/panel/contents/ui/main.qml @@ -0,0 +1,328 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.1 +import QtQuick.Layouts 1.0 +import org.kde.plasma.plasmoid 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.draganddrop 2.0 as DragDrop + +import "plasmapackage:/code/LayoutManager.js" as LayoutManager + +DragDrop.DropArea { + id: root + width: 640 + height: 48 + +//BEGIN properties + Layout.minimumWidth: currentLayout.Layout.minimumWidth + Layout.maximumWidth: currentLayout.Layout.maximumWidth + Layout.preferredWidth: currentLayout.Layout.preferredWidth + + Layout.minimumHeight: currentLayout.Layout.minimumHeight + Layout.maximumHeight: currentLayout.Layout.maximumHeight + Layout.preferredHeight: currentLayout.Layout.preferredHeight + + property Item toolBox + + property Item dragOverlay + + property bool isHorizontal: plasmoid.formFactor != PlasmaCore.Types.Vertical +//END properties + +//BEGIN functions +function addApplet(applet, x, y) { + var container = appletContainerComponent.createObject(root) + print("Applet added in test panel: " + applet + applet.title + " at: " + x + ", " + y); + + applet.parent = container; + container.applet = applet; + applet.anchors.fill = container; + applet.visible = true; + container.visible = true; + + //is there a DND placeholder? replace it! + if (dndSpacer.parent === currentLayout) { + LayoutManager.insertBefore(dndSpacer, container); + dndSpacer.parent = root; + return; + + //if the provided position is valid, try it + } else if (x >= 0 && y >= 0) { + var index = LayoutManager.insertAtCoordinates(container, x, y); + print("Applet " + applet.id + " " + applet.title + " was added in position " + index) + + //give up: enqueue the applet after all the others + } else { + //if lastspacer is here, enqueue after it + if (lastSpacer.parent === currentLayout) { + LayoutManager.insertBefore(lastSpacer, container); + //else put it in last position + } else { + container.parent = currentLayout; + } + } + + if (applet.Layout.fillWidth) { + lastSpacer.parent = root; + } +} + + +function checkLastSpacer() { + lastSpacer.parent = root + + var expands = false; + + if (isHorizontal) { + for (var container in currentLayout.children) { + var item = currentLayout.children[container]; + if (item.Layout && item.Layout.fillWidth) { + expands = true; + } + } + } else { + for (var container in currentLayout.children) { + var item = currentLayout.children[container]; + if (item.Layout && item.Layout.fillHeight) { + expands = true; + } + } + } + if (!expands) { + lastSpacer.parent = currentLayout + } + +} + +//END functions + +//BEGIN connections + Component.onCompleted: { + currentLayout.isLayoutHorizontal = isHorizontal + LayoutManager.plasmoid = plasmoid; + LayoutManager.root = root; + LayoutManager.layout = currentLayout; + LayoutManager.restore(); + containmentSizeSyncTimer.restart(); + } + + onDragEnter: { + LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y) + } + + onDragMove: { + LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y) + } + + onDragLeave: { + dndSpacer.parent = root; + } + + onDrop: { + plasmoid.processMimeData(event.mimeData, event.x, event.y); + } + + + Containment.onAppletAdded: { + addApplet(applet, x, y); + LayoutManager.save(); + } + + Containment.onAppletRemoved: { + var flexibleFound = false; + for (var i = 0; i < currentLayout.children.length; ++i) { + if (currentLayout.children[i].applet.Layout.fillWidth) { + flexibleFound = true; + break + } + } + if (!flexibleFound) { + lastSpacer.parent = currentLayout; + } + + LayoutManager.save(); + } + + Plasmoid.onUserConfiguringChanged: { + if (plasmoid.immutable) { + if (dragOverlay) { + dragOverlay.destroy(); + } + return; + } + + if (plasmoid.userConfiguring) { + if (!dragOverlay) { + var component = Qt.createComponent("ConfigOverlay.qml"); + dragOverlay = component.createObject(root); + component.destroy(); + } else { + dragOverlay.visible = true; + } + } else { + dragOverlay.visible = false; + dragOverlay.destroy(); + } + } + + Plasmoid.onFormFactorChanged: containmentSizeSyncTimer.restart(); + Plasmoid.onImmutableChanged: containmentSizeSyncTimer.restart(); + onToolBoxChanged: containmentSizeSyncTimer.restart(); +//END connections + +//BEGIN components + Component { + id: appletContainerComponent + Item { + id: container + visible: false + + Layout.fillWidth: applet && applet.Layout.fillWidth + Layout.onFillWidthChanged: { + if (plasmoid.formFactor != PlasmaCore.Types.Vertical) { + checkLastSpacer(); + } + } + Layout.fillHeight: applet && applet.Layout.fillHeight + Layout.onFillHeightChanged: { + if (plasmoid.formFactor == PlasmaCore.Types.Vertical) { + checkLastSpacer(); + } + } + + Layout.minimumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumWidth > 0 ? applet.Layout.minimumWidth : root.height) : root.width) + Layout.minimumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumHeight > 0 ? applet.Layout.minimumHeight : root.width) : root.height) + + Layout.preferredWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredWidth > 0 ? applet.Layout.preferredWidth : root.height) : root.width) + Layout.preferredHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredHeight > 0 ? applet.Layout.preferredHeight : root.width) : root.height) + + Layout.maximumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumWidth > 0 ? applet.Layout.maximumWidth : (Layout.fillWidth ? root.width : root.height)) : root.height) + Layout.maximumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumHeight > 0 ? applet.Layout.maximumHeight : (Layout.fillHeight ? root.height : root.width)) : root.width) + + property int oldX: x + property int oldY: y + + property Item applet + onAppletChanged: { + if (!applet) { + destroy(); + } + } + + PlasmaComponents.BusyIndicator { + z: 1000 + visible: applet && applet.busy + running: visible + anchors.centerIn: parent + } + onXChanged: { + translation.x = oldX - x + translation.y = oldY - y + translAnim.running = true + oldX = x + oldY = y + } + onYChanged: { + translation.x = oldX - x + translation.y = oldY - y + translAnim.running = true + oldX = x + oldY = y + } + transform: Translate { + id: translation + } + NumberAnimation { + id: translAnim + duration: units.longDuration + easing.type: Easing.InOutQuad + target: translation + properties: "x,y" + to: 0 + } + } + } +//END components + +//BEGIN UI elements + Item { + id: lastSpacer + parent: currentLayout + + Layout.fillWidth: true + Layout.fillHeight: true + } + + Item { + id: dndSpacer + width: (plasmoid.formFactor == PlasmaCore.Types.Vertical) ? currentLayout.width : theme.mSize(theme.defaultFont).width * 10 + height: (plasmoid.formFactor == PlasmaCore.Types.Vertical) ? theme.mSize(theme.defaultFont).width * 10 : currentLayout.height + } + + GridLayout { + id: currentLayout + property bool isLayoutHorizontal + + Layout.preferredWidth: { + var width = 0; + for (var i = 0; i < currentLayout.children.length; ++i) { + if (currentLayout.children[i].Layout) { + width += Math.max(currentLayout.children[i].Layout.minimumWidth, currentLayout.children[i].Layout.preferredWidth); + } + } + return width; + } + Layout.preferredHeight: { + var height = 0; + for (var i = 0; i < currentLayout.children.length; ++i) { + if (currentLayout.children[i].Layout) { + height += Math.max(currentLayout.children[i].Layout.minimumHeight, currentLayout.children[i].Layout.preferredHeight); + } + } + return height; + } + rows: 1 + columns: 1 + //when horizontal layout top-to-bottom, this way it will obey our limit of one row and actually lay out left to right + flow: isHorizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight + } + + onWidthChanged: { + containmentSizeSyncTimer.restart() + } + onHeightChanged: { + containmentSizeSyncTimer.restart() + } + + Timer { + id: containmentSizeSyncTimer + interval: 150 + onTriggered: { + currentLayout.x = 0 + currentLayout.y = 0 + currentLayout.width = root.width - (isHorizontal && toolBox && toolBox.visible ? toolBox.width : 0) + currentLayout.height = root.height - (!isHorizontal && toolBox && toolBox.visible ? toolBox.height : 0) + currentLayout.isLayoutHorizontal = isHorizontal + } + } +//END UI elements +} diff --git a/containments/panel/metadata.desktop b/containments/panel/metadata.desktop new file mode 100644 index 0000000000..bb81dceea5 --- /dev/null +++ b/containments/panel/metadata.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Encoding=UTF-8 +Keywords= +Name=Panel +Name[be]=Панель +Name[bn]=প্যানেল +Name[br]=Panell +Name[bs]=Panel +Name[ca]=Plafó +Name[ca@valencia]=Plafó +Name[cs]=Panel +Name[cy]=Panel +Name[da]=Panel +Name[de]=Kontrollleiste +Name[el]=Πίνακας +Name[en_GB]=Panel +Name[es]=Panel +Name[eu]=Panela +Name[fa]=تابلو +Name[fi]=Paneeli +Name[fr]=Tableau de bord +Name[ga]=Painéal +Name[gl]=Panel +Name[hu]=Panel +Name[ia]=Pannello +Name[ka]=პანელი +Name[kk]=Панель +Name[kn]=ಪುಟೀಪು (ಪಾನಲ್) +Name[ko]=패널 +Name[nb]=Panel +Name[nds]=Paneel +Name[nl]=Paneel +Name[pa]=ਪੈਨਲ +Name[pl]=Panel +Name[pt]=Painel +Name[pt_BR]=Painel +Name[ro]=Panou +Name[sk]=Panel +Name[sl]=Pult +Name[sr]=Панел +Name[sr@ijekavian]=Панел +Name[sr@ijekavianlatin]=Panel +Name[sr@latin]=Panel +Name[sv]=Panel +Name[tr]=Panel +Name[uk]=Панель +Name[uz]=Panel +Name[uz@cyrillic]=Панел +Name[vi]=Bảng điều khiển +Name[xh]=Iqela lenjongo ethile +Name[x-test]=xxPanelxx +Name[zh_CN]=面板 +Name[zh_TW]=面板 +Type=Service + +X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment +X-Plasma-API=declarativeappletscript +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Marco Martin +X-KDE-PluginInfo-Category= +X-KDE-PluginInfo-Email=mart@kde.org +X-KDE-PluginInfo-License=GPLv2+ +X-KDE-PluginInfo-Name=org.kde.panel +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-Plasma-MainScript=ui/main.qml +X-Plasma-ContainmentType=Panel diff --git a/containments/panel/plasma-containment-panel.desktop b/containments/panel/plasma-containment-panel.desktop new file mode 100644 index 0000000000..766d6be6e7 --- /dev/null +++ b/containments/panel/plasma-containment-panel.desktop @@ -0,0 +1,113 @@ +[Desktop Entry] +Name=Empty Panel +Name[bs]=prazan panel +Name[ca]=Plafó buit +Name[ca@valencia]=Plafó buit +Name[cs]=Prázdný panel +Name[da]=Tomt panel +Name[de]=Leere Kontrollleiste +Name[el]=Κενός πίνακας +Name[en_GB]=Empty Panel +Name[es]=Panel vacío +Name[eu]=Panel hutsa +Name[fi]=Tyhjä paneeli +Name[fr]=Tableau de bord vide +Name[ga]=Painéal Folamh +Name[gl]=Panel baleiro +Name[hr]=Prazan panel +Name[hu]=Üres panel +Name[ia]=Pannello vacue +Name[kn]=ಖಾಲಿ ಪುಟೀಪು (ಪ್ಯಾನಲ್) +Name[ko]=빈 패널 +Name[nb]=Tomt panel +Name[nds]=Leddig Paneel +Name[nl]=Leeg paneel +Name[pa]=ਖਾਲੀ ਪੈਨਲ +Name[pl]=Pusty panel +Name[pt]=Painel Vazio +Name[pt_BR]=Painel vazio +Name[ro]=Panou gol +Name[sk]=Prázdny panel +Name[sl]=Prazen pult +Name[sr]=празан панел +Name[sr@ijekavian]=празан панел +Name[sr@ijekavianlatin]=prazan panel +Name[sr@latin]=prazan panel +Name[sv]=Tom panel +Name[tr]=Boş Panel +Name[uk]=Порожня панель +Name[vi]=Thanh điều khiển trống +Name[x-test]=xxEmpty Panelxx +Name[zh_CN]=空面板 +Name[zh_TW]=空白面板 +Comment=A simple linear panel +Comment[ast]=Un panel llinial simple +Comment[bs]=Jednostavan linearni panel +Comment[ca]=Un plafó lineal senzill +Comment[ca@valencia]=Un plafó lineal senzill +Comment[cs]=Jednoduchý přímý panel +Comment[da]=Et simpelt lineært panel +Comment[de]=Eine einfache, gerade Kontrollleiste +Comment[el]=Ένας απλός γραμμικός πίνακας +Comment[en_GB]=A simple linear panel +Comment[es]=Un sencillo panel lineal +Comment[et]=Lihtne sirge paneel +Comment[eu]=Panel lineal xume bat +Comment[fi]=Yksinkertainen lineaarinen paneeli +Comment[fr]=Un tableau de bord linéaire simple +Comment[ga]=Painéal simplí líneach +Comment[gl]=Un panel simple +Comment[he]=לוח ישר פשוט +Comment[hr]=Jednostavan pravocrtni panel +Comment[hu]=Egy egyszerű, lineáris panel +Comment[ia]=Un simple pannello linear +Comment[is]=Einfalt línulegt spjald +Comment[it]=Un semplice pannello lineare +Comment[ja]=簡単なリニアパネル +Comment[kk]=Жәй панель +Comment[km]=បន្ទះ​លីនេអ៊ែរ​ធម្មតា +Comment[kn]=ಒಂದು ಸರಳ ಹಾಗು ರೇಖೀಯ ಫಲಕ +Comment[ko]=간단한 선형 패널 +Comment[lt]=Paprastas tiesinis pultas +Comment[lv]=Vienkāršs, lineārs panelis +Comment[mr]=सोपे रेषीय पटल +Comment[nb]=En enkelt lineært panel +Comment[nds]=En eenfach liekweg Paneel +Comment[nl]=Een eenvoudig lineair paneel +Comment[pa]=ਸਧਾਰਨ ਲੀਨੀਅਰ ਪੈਨਲ +Comment[pl]=Prosty, liniowy panel +Comment[pt]=Um painel linear simples +Comment[pt_BR]=Um painel linear simples +Comment[ro]=Un panou liniar simplu +Comment[ru]=Простая линейная панель +Comment[sk]=Jednoduchý lineárny panel +Comment[sl]=Preprost linearen pult +Comment[sr]=Једноставан линеарни панел +Comment[sr@ijekavian]=Једноставан линеарни панел +Comment[sr@ijekavianlatin]=Jednostavan linearni panel +Comment[sr@latin]=Jednostavan linearni panel +Comment[sv]=En enkel linjär panel +Comment[th]=พาเนลแนวยาวแบบพื้นฐาน +Comment[tr]=Basit bir doğrusal panel +Comment[ug]=ئاددىي بىر سىزىقلىق تاختا +Comment[uk]=Проста лінійна панель +Comment[wa]=On simpe et lineyåre sicriftôr +Comment[x-test]=xxA simple linear panelxx +Comment[zh_CN]=简单的线性面板 +Comment[zh_TW]=簡單的線性面板 +Icon= +Type=Service +X-KDE-ServiceTypes=Plasma/Applet,Plasma/Containment +X-Plasma-ContainmentCategories=panel +NoDisplay=true + +X-KDE-Library=plasma_containment_panel +X-KDE-PluginInfo-Author=The Plasma Team +X-KDE-PluginInfo-Email=plasma-devel@kde.org +X-KDE-PluginInfo-Name=panel +X-KDE-PluginInfo-Version=1.0 +X-KDE-PluginInfo-Website=http://plasma.kde.org/ +X-KDE-PluginInfo-Category=Containments +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true diff --git a/design/CHANGELOG-4.2 b/design/CHANGELOG-4.2 new file mode 100644 index 0000000000..0dead00351 --- /dev/null +++ b/design/CHANGELOG-4.2 @@ -0,0 +1,263 @@ +libplasma 3.0 / KDE 4.2 +======================= + +libplasma +--------- +* Build + * libplasma has moved to kdelibs from kdebase-workspace and as such there is no longer a need to use FindPlasma.cmake. FindKDE4 now provides all the necessary plasma CMake bits needed, and using libplasma does not create a kdebase-workspace dependency for your application anymore. + +* Features + * Symbol Versioning: limit loading of plugins to those that match the libplasma version + * NEW: ToolTipManager for Plasma style tooltips + * NEW: Wallpaper plugins for Containments + * NEW: Context for coordinating and publishing Context information, such as the current Activity or phsyical location + * Applet + * sizeHintChanged() signal. A containment (such as a panel) can adjust its size based on changed sizehints of an applet + * ContextConstraint events and access to the current Context object + * Shortcut editor in Applet configuration dialog allows setting of global shortcuts per-widget + * NEW: Plasma::Extender and Plasma::ExtenderItem, allowing visual, relocatable extensions to Applet + * NEW: PopupApplet, which switches between an icon with a popup in a Horizontal/Vertical containment (such as a panel) and the widget directly on the canvas in a Planer containment (such as a desktop), the icon can be replaced with custom graphics or widgets by the implementation + * Containment + * Support dropping of arbitrary data if the mimetypes are supported by an applet + * Activity naming and Context support + * Toolbox can be positioned in any corner or edge + * Toolbox actions are displayed as an always open toolbar when zoomed out for improved usability + * Corona + * addOffscreenWidget/removeOffscreenWidget: manage canvas items that should not appear in a primary view (e.g. Extenders) + * "screen" information querying added to Corona to allow different approaches for viewports; e.g. using KWindowSystem and QDesktopWidget for the Plasma shell, but window coordinates for plasmodviewer or other non-desktop apps. + * Package system + * PackageStructure supports arbitrary URIs (in addition to auto-discovery for package) structure description files. + * Package removal + * Package browsing interface can be provided by the PackageStructure plugin, allowing for 3rd party widget collectionsto offer online browsing and fetching customizations + * FrameSvg + * setting the margins via in-SVG hints + * paintPanel API additions to make it more like QPainter and Plasma::Svg + * Runners + * TryExec key in .desktop file now supported, allowing runners that rely on an external application to be conditional loaded at runtime + * Service + * Allow enabling/disabling of operations at runtime + * Associate widgets with operations + * Theme + * Support compressed SVGs (*.svgz) + * Supports a pixmap cache and a SVG element rects cache for faster startup + * Widgets + * NEW: Plasma::Slider based on QSlider + * NEW: Plasma::TabBar based on QTabBar, usable as both a standalone tabbar or as a tabwidget + * NEW: Plasma::Frame used to visually group widgets + * NEW: Plasma::TreeView used to put tree views or simple list in the canvas + * NEW: Plasma::BusyWidget used to indicate the loading of something + * NEW: Plasma::ToolButton based on QToolButton + * Plasma::PushButton is svg-themed + +* Significant Fixes + * WebContent painting update synchronization (fixes, among other things, scrolling) + * Prevent crash when Containment that AppletBrowser is associated with is deleted + * Applet handles work with all icon sizes (user system settings) + * Fix View so that when a new activity is added, don't move more than necessary; + fixes dragging lock + * Dramatically fewer full paints by properly watching the exposed rect area, which for full screen Containments or large/complex Applets is quite significant in terms of performance + * Fix on-exit crashes related to focus handling issues in QGraphicsView + * Prevention of premature calls to Applet::constraintsEvent + * Applets now resize in "real time" without the pixelation + * Numerous crash fixes pushed upstream to QGraphicsView as well (focus resetting, scene queries on deletion..) + +Developer Documentation +----------------------- +* Design documentation + * NEW: dataengine + * NEW: tooltips + * NEW: wallpaper + * NEW: widgets + * NEW: javascript + +* Tutorials + * NEW: Extenders http://techbase.kde.org/Development/Tutorials/Plasma/UsingExtenders + +Desktop Theme +------------- +* NEW: widgets/button for theming pushbuttons +* NEW: widgets/frame for theming Plasma::Frame used also in other widgets +* NEW: widgets/scrollbars to theme Plasma::ScrollBar and views scrollbars in libplasma +* NEW: widgets/configuration-icons: little icons used for configuration purposes across Plasma +* NEW: widgets/extender-background, widgets/extender-dragger: SVGs for new Extender widget +* NEW: widgets/tooltip: tooltip SVGa +* NEW: widgets/calendar +* NEW: widgets/containment-controls: icons and buttons for sizing panels and other containment tasks +* NEW: widgets/monitor: monitor for use in displaying mockups of on-screen content +* NEW: widget/glowbar: a glow for use by offscreen panels to indicate their location +* NEW: dialogs/kickoff: theming for the kickoff launcher menu +* color roles for buttons text and background added +* Plasma::Slider follows theme +* Applet handle all svg-themed +* The default Oxygen desktop theme radically improved across the board + +Plasma Desktop Shell +-------------------- +* Features + * Desktop + * New Containment configuration for all desktop containments: wallpapers, activity type, theme + * Panel + * Resizes itself when an applet changes its sizehint according to its maximum and minimum sizes + * Autohide and windows-cover-panel options + * Easier drag and drop to panel by showing an empty area between the two applets nearest to the mouse cursor + +* Significant Fixes + * Reposition toolbox when zooming out/in to avoid panel overlap + * Draw the missing part of the toolbox when repositioned because of a panel + * MS Windows compile fixes + +Other Shells +------------ +* plasmoidviewer new command line options: + * --list lists known applets + * --formfactor (-f) + * --containment (-c) + * --wallpaper (-w) + * --pixmapcache (-p) + +Tools +----- +* Plasma Engine Explorer + * Remove/update sources via context menu + * NEW: Plasma::Service interaction UI, using DataEngine::serviceForSource +* plasmapkg + * now supports listing, updating and removing packages +* NEW: Destkop Theme Details + * Customize and create new desktop themes with kcmshell4 destkopthemedetails + +Plugins/Addons +-------------- +* Features + * Plasmoids and Containments + * NEW: Incoming messages: listens to various F/OSS email and IM apps for messages arriving + * NEW: Leave A Note: let people leave you notes on your computer, particularly handy for Plasma widets on the screensaver + * NEW: Previewer: drop files to preview them right on your desktop or panels + * NEW: System monitor + * NEW: Web browser: a WebKit browser in a desktop widget! + * NEW: Activity bar: quick switcher for Plasma activities + * NEW: Conway's game of life + * NEW: RSSNow! fancy online news ticker + * NEW: News, simple online news ticker + * NEW: Pastebin, drop text/data to upload it to a pastebin server + * NEW: Text snippets generator + * NEW: Timer + * NEW: Bouncing ball, throw it and watch it bounce around! + * NEW: Calendar + * NEW: Character selector + * NEW: Eyes + * NEW: LCD Weather Station plasmoid + * NEW: Quicklaunch plasmoid + * Task bar + * Grouping: manually or by application + * Sorting: manually or by program name + * Limit windows shown by desktop, screen or minimized status + * Multiple rows of windows + * Theming improved to look more consistent with other buttons and generally be more sexy + * System tray + * Supports hiding of icons + * Supports non-Freedesktop.org icons (e.g. full plasmoids or future creations) through a protocol abstraction + * Listens for and displays popup notifications and application jobs (e.g. file transfers) + * Now Playing media player controls: play, pause, stop, switch tracks and more from Plasma + * Notes + * Custom colors + * Export notes to file + * Text formatting, such as alignment, bold, italic, etc + * Clocks + * Custom colors for digital clock + * Standardized multi-timezone support in libplasmaclock + * Folder view + * Filtering improvements: mimetype and exclusion based. + * Sorting options, options for locking the icons in place and/or forcing grid alignment. + * Uses a top-to-bottom icon arrangement when used as a containment. + * Remembers icon positions. + * No longer blocks the GUI when loading large folders. + * Shows a busy animation while loading folders / laying out icons. + * Works in panels looking like a popup menu + * Default desktop containment + * Wheel mouse == switch desktop + * Creation of widgets on desktop containments puts them in empty areas, avoiding overlap + * Comics + * Respects web proxy and other relevant KDE settings + * Improved mouse interaction (middle mouse zooms, context menu, etc) + * Comicproviders can be written in any language supported by Kross + * Comicproviders can be downloaded via "Get Hot New Stuff" + * New comicproviders can be added on kde-files.org + * Lancelot + * Full keyboard support + * New lists with scrollbars + * Themes that match Plasma themes from kdeplasma-addons module + * Twitter + * When it is in the panel it is a popup, showing the avatar of the last person who sent a message and the numer of unread tweets as icon + * Trashcan + * Lets you configure system wide trash behaviour like size limits + + * DataEngines + * NEW: Web site icons (favicons) engine + * NEW: Desktop notifications engines + * NEW: System monitor engine based on ksysguard (cpu, memory, heat, sensors, etc) + * NEW: Network engine + * NEW: Application jobs (aka kuiserver) engine; shows any published KJobs such as file operations + * NEW: Executables: run commands and get their output from stdout and stderr + * NEW: RSS + * NowPlaying + * Plasma::Service for controlling media players + * supports MPRIS + * Powermanagement + * Added a new source for managing PowerDevil profiles + + * Runners + * NEW: Kate sessions runner + * NEW: Recent documents runner + * NEW: Spellcheck runner + * NEW: Konqueror history runner + * NEW: Konqueror sessions runner + * NEW: Konsole sessions runner + * NEW: Nepomuk search runner + * NEW: Power management controller (via PowerDevil) + * NEW: Places (as seen in dolphin, file dialog, kickoff, etc) runner + * Converter runner now does speed, masses and nautical distances; conversion code moved to a shared lib + + * ScriptEngines + * NEW: Google Gadgets + * NEW: Python Plasmoids + * NEW: Ruby Plasmoids + * MacOS Dashboard widgets: improved JS API compliance + * JavaScript: + * DataEngines + * Services + * layouts + * configuration data + * much more featureful plasmoid object replaces applet object + + * Wallpapers + * NEW: Image, Slideshow and Color plugins, based on previous code + * Directories recursed for images in Image and Slideshow plugin + * Slideshow images are randomized + +* Significant Fixes + * Various clocks ported to AppletClock for calendar and timezone consistency + * Pager crash fixes + * MS Windows compile fixes + * Taskbar shows thumbnails of windows on hover (4.1 regression) + * TwitterEngine respects web proxies and provides a proper Plasma::Service + * Kickoff + * proper menu size restoration + * Hide Shutdown and Restart options when those actions are not possible. + * Make Sleep and Hibernate entries appear and work + * use Plasma::Theme to improve visual harmony with the rest of Plasma + +KRunner +------- +* Features + * Plasma Screensaver: Plasma widget overlay for screensavers + * D-Bus autoactivation, so even if it has perma-crashed, selecting Run Command from Plasma will resurect it + * Alternate user interface: QuickSand + +* Significant Fixes + * Screensaver activation fixed to compensate for system clock changes + * Several crashes related to access of non thread safe code + +Platforms +--------- +Compile and runtime fixes for Microsoft Windows and Maemo + diff --git a/design/CHANGELOG-4.3 b/design/CHANGELOG-4.3 new file mode 100644 index 0000000000..6cb984cd85 --- /dev/null +++ b/design/CHANGELOG-4.3 @@ -0,0 +1,246 @@ +Significant changes in libplasma 3.1 / KDE 4.3 +============================================== +libplasma +--------- +* Features + * NEW: RunnerSyntax, class for describing query syntax + * AbstractRunners can now register their syntax for online documentation purposes + * Animator: no longer crashes when an animation is started/stopped on a widget already being animated during animation + * RunnerContext + * Introduced the isValid() method so runners can abort matches early + * Plasma::Dialogs now animate show/hide if composited window management is available + * Security + * Categories of applets can be excluded from the appletbrowser + * co-operative security + * Shortcuts + * Defaults changed + * NEW: Config dialog + * Theme + * Themes can now define options in the [Settings] group of the metadata.desktop file: + * UseNativeWidgetStyle=true and Plasma will default to native (QStyle) painting for all widgets + * FallbackTheme= to define which fallback theme to define which theme to use as the first fallback for missing elements + * Backgrounds can now have variable backgrounds + * Ability to list all known themes + * Extenders + * NEW: ExtenderGroup, class for grouping ExtenderItems. + * hasItem function in Extender to provide an easy way for applets to avoid duplication of ExtenderItems. + * Improved drag-and-drop + * Svg + * Ability to set Theme object to use + * Ability to turn off disk caching is not needed/desired + * Wallpaper: + * Cache for completed wallpaper renderings + * Threaded rendering of image files to specified size, scaling method and coloring + * Improved settings save/restore/management, including a configNeedsSaving signal + * DataEngine access modelled after the same facility in Applet + * Widgets + * NEW: SpinBox + * NEW: VideoWidget + * NEW: ScrollWidget. A widget that puts scrollbars when it contains a widget bigger than him. + * NEW: TextBrowser + * TabBar styling and interaction improvements (animations, click-n-flick, ..) + * WebView can scroll its contents by simply dragging a point in the page with the mouse + + +Other Libraries +--------------- +* NEW: KNotificationItem library added to kdelibs/experimental/ which provides access to the new system tray protocol (complete with legacy fallback support) +* NEW: ScreenPreviewWidget to libkworkspace that works with Plasma::Wallpaper or pixmaps that provides a nicely themed and appropriately sized "monitor" to show screen previews in +* NEW: RememberTheMilk library added to kdeplasma-addons/libs +* NEW: Conversion librarya dd to kdeplasma-addons/libs + * Add fuel efficiency + * Add time + * Add power + * Add currency + * Add energy + * Add pressure + * More SI Units + * Add beaufort scale to velocity + * Add delisle, newton, rankine, reaumur & romer to temperature +* libplasmaclock + * Text to speech service (KTTSD) to read aloud the time + * Holidays shown in pop-up calendar +* libtaskmanager: signficant stability fixes, particularly crashes in closeGroup or add(Task) caused by changes in the grouping strategy + +Developer Documentation +----------------------- +* Simple JavaScript API documentation +* System tray design + +Desktop Theme +------------- +* Features + * FrameSvg + * NEW: overlays for a filigrane effect, can be either random positioned, fixed, scaled or tiled + * configuration-icons + * NEW: collapse/restore icons for use in ExtenderGroup + * Desktop and panel toolboxes are now svg themed + +* Themes must now set the X-KDE-PluginInfo-Name entry in the metadata.desktop correctly, namely to the name of the directory containing the theme (e.g. default or Clean-Blend). While this was always the case, it was never relied on by libplasma. As of 4.3 there is now code that does rely on this being properly set. + +Plasma Desktop Shell +-------------------- +* Features + * Renamed binary from plasma to plasma-desktop; config files also changed as a result + * Desktop Toolbox: it's smaller and shows the activity name if any is set + * ZUI: the global actions such as add activity and lock desktop are on a global toolbox when the desktop is zoomed out. + * Configuration gui to activate a different activity for each desktop and to decouple the dashboard contents with desktop contents + * Panels + * access to spacers to control how widgets arrange themselves + * 'Windows go below' mode + + +Other Shells +------------ +* plasmoidviewer + * supports loading uninstalled packages by passing the path to the package + * can define the wallpaper to load + * can use a theme different from the one used in the workspace + * improved containment usage, so loaded plasmoids behave more like they do in plasma-desktop + * --theme switch to allow viewing plasmoids with different stylings + +Tools +----- +* NEW: plasmawallpaperviewer: view and configure wallpapers in a window, perfect for testing new wallpaper plugin features +* plasmaengineexplorer provides a --list command line switch + +Plugins/Addons +-------------- +* Features + * Plasmoids and Containments + * NEW: Bubble Monitor: track system status via a lava lamp style visualization + * NEW: Magnifique: View and magnify sections of the Plasma canvas + * NEW: Media player: Play video and audio files by dragging them on the desktop + * NEW: openDesktop Plasmoid: Basic interaction with openDesktop contacts + * NEW: RememberTheMilk: interface for the online time management service of the same name + * NEW: System Load Viewer: simple yet effective retro-style system load and memory usage display + * NEW: Unit converter + * NEW: Weather: 5 day forecasts and more in a visually stunning outfit + * Bouncing Ball: + * Theme support, including a new soccer ball + * Comics + * Added optional Nepomuk support when manually saving a comic strip. + * Added per comic setting to store the current position. + * File Watcher + * Added support for filtering (both regular expressions and exact matches are supported). + * Microblogging (was KDE Twitter) + * Added support for other Twitter API based services like identi.ca (that is based on laconi.ca) + * Pager + * User can choose to do nothing, toogle the desktop or the dashboard when he click on the current desktop. + * Notes + * Highlight current line + * Change font size with Control + Scrollwheel + * Folder View + * Added keyboard navigation to iconview. User can navigate using direction keys and launch using Enter/Return. + * Pastebin + * New look and feel + * Pasting through context menu + * Using knotification to tell the user that the data has been saved online + * History of pastebin URLs + * System tray + * New D-Bus based system tray protocol + * Ability to show/hide icons based on category + * Jobs show file/dir progress and ETA + * Jobs are grouped together: one group for running jobs and one for completed jobs. + * Completed jobs have a different appearence and allow the user to open the destination file/directory. + * Notifications now show custom images like kopete's contact images. + * Multiple trays in the same Plasma application supported. + * Can configure whether or not notifications/jobs should autohide shortly after appearing. + * Taskbar + * New popup menu for grouped tasks with animation and tooltips for each item + * Tooltips of grouped tasks can show tooltips of multiple windows + * Hovering of tasks (grouped or not) will request the window manager (at its discretion) to highlight those windows + * Web browser + * Real page zoom instead of just font scaling + * Can scroll the page by dragging the contents themselves + * LCD Weather Station + * New config dialog + * Use geolocation dataengine for initial city if available. + * Use Condition Icon for current weather and fallback to pressure if not available. + * Show pressure tendency arrows. BUG:184457 + * System monitor + * Handle new/removed network interfaces in network monitor + * NEW: Memory monitor. BUG:182704 + * temperature plotter uses now same range as analog meter + * Temperature widget now defaults to plotter in panel + * Show tooltips when in panel. BUG:180102 + * Advanced config page added + * Plotter labels added + * Timer + * A timer can have a title + * Count down is restored after a plasma shutdown/restart + * User can hide seconds. + * Lancelot + * theming: Scrollbars follow Plasma style + * actions for system buttons are configurable + * highlighted path in application browser + * clear documents history + * places are loaded from Dolphin + * applications in menu are sorted + * Quicklaunch + * Icons can be re-ordered with drag-and-drop, show tooltips and icon size is configurable, + retained even with resizing + + * DataEngines + * NEW: Akonadi engine: emails, contacts and microblogs from Akonadi + * NEW: Calendar: holiday and event information + * NEW: Geolocation: publishes location information based on GPS input or IP address; sports plugins + * NEW: Keystate: keyboard modifier and mouse button state information + * NEW: Metadata: access to Nepomuk data on files + * NEW: OCS engine: interface for scripted applets to Open Collaboration Services + * NEW: PotD: Grabs the "picture of the day" from various online sources + * NEW: RememberTheMilk: support for the online time management service + * Time engine can also report sun positioning, sunrise, sunset and moon phase information + + * Wallpapers + * NEW: Virus: artificial life simulation, watch it colonize and eat your wallpaper! + * NEW: Weather: selects wallpapers based on weather station information + * NEW: Mandelbrot: draws fractals on the desktop; click and drag or zoom in/out to explore the Mandelbrot set + * NEW: Marble: interactive desktop globe as your desktop background; powered by KDE's Marble + + * Runners + * Converter + * If not exact unit found offer possible mathes. + + * ScriptEngines + * Simple JavaScript API + * Support for Url objects + * Added new Plasma::Widget entries + * Completed LinearLayout API + * file() method to get paths from the Plasmoid's package + +* Bugfixes + * Plasmoids and Containments + * Show Desktop + * Fix keyboard shorcuts BUG:180661 + * News + * Better alternate background color for generated css. BUG: 185527 + * correctly use feed urls with parameters BUG:178936 + * LCD Weather Station + * Replace "N/A" with "-" (Looks better in lcd letters). BUG:186610 + * Make credit clickable. BUG:183984 + * Fix wind speed and unit on some data sources. + * System monitor + * Allow smaller minimum size. BUG:186501 + * Limit initial temperature count to 5. BUG:178314 + * Lock buttons when desktop is locked. BUG:178469 + * Fix config. BUG:181378 + * don't crash when removing an applet by it's own context menu BUG:178860 + * Display an IconWidget when there are no available sources. BUG: 178192 + * activate layout to calculate fixed size ratio correctly on applet start. BUG: 176268 + * Walpapers + * Slideshow mode of Image plugin takes ~97% less time to build the wallpaper list and allocates a fraction of the memory in the process. BUG: 190632 + +KRunner +------- +* Features + * Display all known syntax in the results area when Help button pressed + * Vertical display of results with new selection style and animation + * Configure parameters on matches by clicking on the configuration wrench, for matches that support options + +* Bugfixes + * Race conditions affecting proper selection of default item fixed (often known as the "I pressed and nothing happened!" bug) + + +Platforms +--------- diff --git a/design/CHANGELOG-4.4 b/design/CHANGELOG-4.4 new file mode 100644 index 0000000000..8abfc3eb45 --- /dev/null +++ b/design/CHANGELOG-4.4 @@ -0,0 +1,169 @@ +Significant changes in libplasma 3.2.0 / KDE SC 4.4 +=================================================== +libplasma +--------- +* Features + * ToolTipManager and ToolTipContent: Tips can now be set as clickable, allowing the mouse to enter them and select an item + * Corona + * Supports defining default ContainmentAction sets + * DataEngine: + * DataEngine::forceImmediateUpdateOfAllVisualizations() allows an engine to push the current data in sources out to all + visualizations without waiting for their timeout period. Useful for changes that can not wait, such as time updates + or data that becomes available with network availability. + * DataContainer::forceImmediateUpdate() allows engines to do a forced update on just one source. + * ContainmentActions plugins: allows context menus and mouse interaction to be defined separately from the containment + * Added Separator widget. + * Wallpapers can now accept drops by defining X-Plasma-DropMimeTypes in their .desktop file and connecting to the + urlDropped(KUrl) signal + * Widgets can be published on the network and be accessed remotely. In the case of scripted plasmoids the entire plasmoid package will be sent over, and in any case, dataengines and services will be routed to the remote machine. This is all completely transparent to applets. + * The applet handle supports resize, rotate and move with multitouch gestures on platforms that supports them + * WindowEffects: a class that permits to control KWin effects in an eas way, hiding the Xatom management + * Adding new Plasma::Animator based on Qt 4.6 Animation API (a.k.a. kinetic). The following animations are implemented: fade, grow, slide, rotation, pulser. + * Package: contentsHash() provides access to a SHA1 hash of the contents of the package + * Applet::SetAssociatedApplication(): It's possible to associate an application and/or a list of urls to an applet, a new icon will appear in the applet handle. + It will open that application or urls. + * KRunner: X-Plasma-Args= can be used by runners to specify plugin-specific setup (used in mediawiki runner to point to a mediawiki instance) + * Wallpapers can now specify a list of wallpaper-plugin specific contextual actions to be added to the context menu. +* Bugfixes + * Context menu handling on PopupApplets now matches what Applet gets + +Developer Documentation +----------------------- + +Desktop Theme +------------- + * NEW widgets/action-overlays used for overlays for icon actions, for instance select/deselect files in folderview + * NEW widgets/line-edit used to theme lineedits slider and editable comboboxes + * slider: new focus and hover indicators elements + * widgets/background: hint-overlay-pos-right and hint-overlay-pos-bottom to control where the overlay will be anchored + +Generic shell +------------- + * NEW library in workspace called plasmagenericshell that contains elements shared by the desktop shell, the netbook shell and the screensaver one, such as: + * Wallpaper setup UI + * Mouse plugins configuratin UI + * NEW Widgets Explorer that replaces the old applet browser. + It shows all the available widgets in an horizontal or vertical list + with a tabbar to chose the available categories and an input field to search among all installed widgets. + +Plasma Desktop Shell +-------------------- +* Features + * D-Bus + * NEW showDashboard bool + * NEW perVirtualDesktopViews bool and setPerVirtualDesktopViews bool + * Desktop Settings + * Desktop theme configuration has been moved to System Settings -> Style + * Workspace actions moved to System Settings -> Desktop + * Ability to select between plasma-desktop and plasma-netbook added in system settings + * ECMA Script; see kdebase/workspace/plasma/design/plasma-desktop-scripting for more info + * the plasma-desktop configuration can be interacted with via the interactive scripting console + * the initial layout can be set with scripts in share/apps/plasma-desktop/defaults/ + * updates to plasma-desktop can be pushed by placing scripts in share/apps/plasma-desktop/updates + * Uses the new Widgets Explorer +* Bugfixes + + +Plasma Netbook Shell +------------------- +New components: + * plasma-netbook shell: can be enabled instead of the Plasma Desktop Shell from a Systemsettings module + * Containments: + * Newspaper: desktop widgets ordered in two or more vertical columns + * Search and Launch: full screen krunner interface with bookmarks support for the search results + * Netpanel: a simple panel + * Applets: + * Searchbox: lauches searches on the Search and launch containment + * Current app control: provides a titlebar in the panel with a button to quickly switch windows + * Dataengines: + * Searchandlaunch: communication between searchbox and search and launch containment + * Shares the Widgets Explorer, wallpaper and mouse plugis settings with the other shells + + * Desktopthemes: + * A simpler version of air to be used there + + +Other Shells +------------ + +Tools +----- + +Plugins/Addons +-------------- +* Features + * Plasmoids and Containments + * NEW Blackboard: a simple paint canvas, it's possible to paint with the mouse or with multitouch events on platforms that supports them + * NEW KDE Observatory: keep track of the development of your favorite KDE projects + * NEW KIMPanel: KDE Input Method Panel for multibyte input + * NEW Knowledge Base: query the knowledgebase of opendesktop.org + * NEW On-screen keyboard + * NEW OpenDesktop.org Activities: activity information from opendesktop.org + * NEW Qalculate math expression evaluator, based on libqalculate + * NEW Spellcheck: a quick spell checking area + * NEW Webslice: a plasmoid displaying a part of a web page + * NEW Window list + * Battery: Improved layout, better support for bigger fonts + * Device notifier + * Visual revamp to make it look and feel more Plasma + * Supports non-removable volumes + * Can show/hide devices from the interface + * Popup autohides after 10s of innactivity + * Picture Frame: now supports loading and displaying of remote images + * Microblog: can view replies and direct messages + * Quicklaunch: ascending and descending sort for applications in quicklaunch applet. + * SystemTray + * now can embed other plasmoids + * supports the finalized version of the StatusNotifier specification + * old notifications remains accessible for a while, separed by application name, browseable with a tabbar widget + * Tasks + * clicking on a window preview now activates that window + * mouse over on a window preview highlights the window if the highlight windows KWin effect is activated + * control+click on a window group launches the KWin present windows effect if activated + * new taskbar animations + + * DataEngines + * NEW Pastebin + * Weather + * NEW wetter.com plugin allowing weather to be fetched from wetter.com + + * Runners + * NEW audioplayercontrol: control any MPRIS enabled audio application (amarok is the default) + * NEW plasma-desktop: "desktop console [script file]" triggers the interactive scripting window + * NEW solid: devices and hotplug support using Solid + * NEW mediawiki: generic mediawiki searching with .desktop files for wikipedia, techbase, wikitravel and userbase by default + * NEW windows: switch between and control windows and desktops + * Service runner: a query on a freedesktop application category, like "network" will show all applications of that category + * Bookmarks runner: the query "bookmarks" (or its translation) lists all the bookmarks + * Contacts runner: the query "contacts" shows all contacts + + * Wallpapers + * Image wallpaper combobox has been replaced with a nicer view. + * Image wallpaper offers 'Next Wallpaper Image' contextual action in slide-show mode. + + * ScriptEngines + * NEW JavaScript DataEngines + + * NEW ContainmentActions(es) + * NEW Switch Activity + * NEW Switch Desktop + * NEW Switch Window + * NEW Context Menu + * NEW Paste + * NEW App Launcher + +* Bugfixes + +KRunner +------- +* Features + +* Bugfixes + + +Platforms +--------- +* Features + +* Bugfixes + diff --git a/design/CHANGELOG-4.5 b/design/CHANGELOG-4.5 new file mode 100644 index 0000000000..4470900da6 --- /dev/null +++ b/design/CHANGELOG-4.5 @@ -0,0 +1,80 @@ +Significant changes in libplasma 3. / KDE SC 4. +================================================= +libplasma +--------- +* Features + +* Bugfixes + +Other Libraries +--------------- +* NEW: liblancelot-dataengines library added to kdeplasma-addons/libs + * data models: krunner, files, applications, devices, kopete, kmail + currently open documents, office apps, recent documents + kmail, kopete, basic xbel +* MOVED: liblancelot moved to kdeplasma-addons/libs + * new widget: TabBar + * animations support + +* plasmagenericshell: + * widget explorer's list and icons factored out into abstract classes for use in the activity manager + +Developer Documentation +----------------------- + +Desktop Theme +------------- + +Plasma Desktop Shell +-------------------- +* Features + * Desktop scripting + * Panel and Activity objects gain config read/write capabilities, same API that Widget has + * NEW: activity manager + * activities and containments are no longer 1:1 +* Bugfixes + + +Other Shells +------------ + +Tools +----- + +Plugins/Addons +-------------- +* Features + * Plasmoids and Containments + * Lancelot + * UI Animations + * Search history + * Section buttons can be made smaller (vertical tab-like) + * Runners configuration + * New icon + * Disk usage pie-charts + * Akonadi integration for unread messages + * Option to use Lancelot as an old-school menu with cascading popups + * Tab key completion + +KRunner +------- +* Features + * Drag and drop support + * Added optional libqalculate support to the calculator runner, enabling advanced operations such as unit/currency conversion, equation solving and more + +* Bugfixes + +Scripting +--------- +JavaScript + * Runners support QScript extensions and file and network I/O + * DataEngine support QScript extensions and file and network I/O + * Plasmoids + * Extender and ExtenderItem bindings + +Platforms +--------- +* Features + +* Bugfixes + diff --git a/design/CHANGELOG-4.6 b/design/CHANGELOG-4.6 new file mode 100644 index 0000000000..80054bb55b --- /dev/null +++ b/design/CHANGELOG-4.6 @@ -0,0 +1,53 @@ +Significant changes in libplasma 3. / KDE SC 4. +================================================= +libplasma +--------- +* Features + * ToolBox is a plugin and is dependent from the Corona + Widgets + * NEW: DeclarativeWidget, used to load QML files in any C++ plasmoid + +* Bugfixes + +Developer Documentation +----------------------- +* Plasma Shell design documentation http://techbase.kde.org/Development/Tutorials/Plasma/ShellDesign + +Desktop Theme +------------- + +Plasma Desktop Shell +-------------------- +* Features + * Activity Templates + +* Bugfixes + + +Other Shells +------------ + * Netbook + * Newspaper is generalized and is now in runtime to be used as application dashboard + +Tools +----- + +Plugins/Addons +-------------- + * DesktopToolbox and PanelToolBox plugins for Plasma-desktop + * NetToolBox plugin for the Netbook shell + * new dataengine: activities + +KRunner +------- +* Features + +* Bugfixes + + +Platforms +--------- +* Features + +* Bugfixes + diff --git a/design/CHANGELOG-template b/design/CHANGELOG-template new file mode 100644 index 0000000000..c8a52fc4d0 --- /dev/null +++ b/design/CHANGELOG-template @@ -0,0 +1,43 @@ +Significant changes in libplasma 3. / KDE SC 4. +================================================= +libplasma +--------- +* Features + +* Bugfixes + +Developer Documentation +----------------------- + +Desktop Theme +------------- + +Plasma Desktop Shell +-------------------- +* Features + +* Bugfixes + + +Other Shells +------------ + +Tools +----- + +Plugins/Addons +-------------- + +KRunner +------- +* Features + +* Bugfixes + + +Platforms +--------- +* Features + +* Bugfixes + diff --git a/design/README b/design/README new file mode 100644 index 0000000000..63299a9ae1 --- /dev/null +++ b/design/README @@ -0,0 +1,9 @@ +The files in this directory contain design notes on various part of the Plasma architecture. They are written using the "markdown" syntax and automatically sync'd to the plasma.kde.org website. + + +Markdown homepage: +* http://daringfireball.net/projects/markdown/ + +Markdown syntax reference: +* http://daringfireball.net/projects/markdown/syntax + diff --git a/design/activities b/design/activities new file mode 100644 index 0000000000..58c3bbc256 --- /dev/null +++ b/design/activities @@ -0,0 +1,85 @@ + +Overview +-------- + +Activities are the "what I'm doing" of context. +They provide a way to organize stuff by project - semantically, not spatially. They have many things +in common with virtual desktops, but are separate; see http://chani.wordpress.com/2010/02/20/the-limits-of-virtual-desktops/ for why. + +An activity has a name and icon, and is always tied to one or more containments; this gives an "anchor" to start with. From there, the user can customize the containment(s), associate windows in kwin, and associate other things (eg. files) in nepomuk. Applications could offer their own activity-specific settings (eg. a "show in this activity" option for dolphin Places) and/or use nepomuk's associations (eg. when a document associated with some activity is opened, notify the activities API so that kwin can automatically associate the window it's in with the activtiy it belongs to). + +While desktop containments are tied to one and only one activity, windows and nepomuk objects can be associated with as many as the user likes. + +an activity can be stopped; this saves out and quits all the activity's containments (and will later save the windows too). +each activity has a containment for each screen; if widgets-per-desktop is enabled, it has a containment for each desktop too. This way, the activity is fully global; after all, humans really aren't good at multitasking. activities are supposed to help you focus on the task at hand. + + +UI +--- + +in 4.5 +------ + +KWin's titlebar contextmenu has a submenu for setting which activities a window is on, much like its desktops submenu. +Plasma has an Activity Manager which allows you to create, stop, destroy, and activate activities. + +Future +------ + +* More convenient ways of associating windows with containments would be nice; drag&drop? +* Can the activity manager use compositing to get thumbnails instead of icons? + +Implementation +-------------- + +this is a general overview; more detailed and short-term plans are at http://techbase.kde.org/Projects/Plasma/ZUI + +In 4.5 +------ +all important code so far has been in kdebase. + +runtime/activitymanager/ is a kded service that manages activities; it controls the list of activities and which one is currrent. It uses a config file to store the IDs and names, so that this information is available even when nepomuk is down; other data, like the icon, is fetched through nepomuk. + +workspace/libs/kworkspace contains KActivityController, KActivityConsumer, and KActivityInfo - classes that talk to the activity manager over dbus and provide an easy API. Controller inherits Consumer, and is meant only for workspace (kwin and plasma); the other two are meant for use by any application, and will move to kdelibs when they've had a chance to mature. + +workspace/plasma/desktop/shell/ contains Activity, which manages both a KActivityInfo and all the associated containments. some management of activities is done in deskopcorona too. It also contains activitymanager/ - the activity management UI. + + +Future +------- + +* Chani needs to write some examples of activity-aware applications, and put them in kdeexamples/ +* we need to decide how plasma-netbook can best use activities (there's not as much multitasking on those devices..) + +* kwin needs to automatically associate a window with the activities for its resources. +* applications need to start advertising what resources they've got in what windows +* it needs to be easy to associate documents with activites (in dolphin?) + +* the taskbar & pager shouldn't show windows from other activities (but perhaps there should be a way to reach them in case you forget where one is) +* I'd like to see a plasmoid that can go in the panel for quick activity switching +* plasma needs a tool for managing which containments belong to which screens/desktops (the most common use case is someone unplugging a monitor and then remembering they need a widget from it) +* stopping an activity should stop all of it, not just plasma; we need to close down the applications in it, like a mini-session, so that they can be restored again when the activity is restored. +* when we have location available, it should be possible to associate activities with locations +* it'd be nice to set other settings based on activity, like IM availability or whether to show (non-critical) notifications + +and I'm sure applications can come up with all sorts of other useful features :) + + +On Sessions +----------- + +closing and restoring windows may be the hardest part of activities. It depends, at least in part, on the application being able to restore itself. +there is already a session protocol for restoring apps when you log in. it's per-process, not per-window. I've heard tell that a lot of applications do not implement it particularly well; iirc, saving and quitting are often done together. I forget whether this means that telling the application to save will make it quit or just do nothing. Each process gets a session key, and on login the application is passed this key and expectted to restore itself from whatever data it has saved for that key. + +There are plenty of warts to that old protocol, and there was an effort to replace it once (by some gnome people iirc?) but it's there and lots of applications use it (at least to *some* extent). + +I think it's worth trying to re-use it. If it works, it gives us some basic support for free, and it's much easier to get applications to be better at using an existing protocol than to try and talk them into supporting a brand new protocol. Remember, we want to save/restore not just kde apps or gtk apps but any other random apps the user needs, even proprietary ones. + +So, how do we re-use it? well, for an application that's on exactly one activity, that's easy: tell it to quit, store its sssion key somewhere along with the activity id, and when it's time to restore that activity you start it again with that key. +If an application is on >1 running activity, merely tell it that one of its activities has quit. if it's activity-aware it should close down stuff that belongs to that activity; if not, oh well, at least nothing is lost. When its last aactivity is closed, we tell it to quit, and save the key with every activity it was associated with, so that as soon as one of them is opened it gets restored. +We will have to be careful that logging out doesn't duplicate any session stuff that activites handle, of course; and once this is in place we may also be able to offer the option of only opening a single activity on login. + +Oh, and we'll have to watch that the windows created as an application is restored get associated with the correct activities. I'm not sure how much work that is; depends how hard it is to go from a WID to a PID to a session key. + +Bonus points if we can get these mini-sessions saving regularly too ;) + diff --git a/design/containmentactions b/design/containmentactions new file mode 100644 index 0000000000..c1c201d130 --- /dev/null +++ b/design/containmentactions @@ -0,0 +1,86 @@ +ContainmentActions +========== + +Overview +-------- +"ContainmentActions" are components that respond to mouse events, usually by either performing an +action or showing a menu with multiple actions. + +Timeline +-------- +Introduced in: libplasma x.x (KDE 4.4.0) + +Component Type +-------------- +ContainmentActions are plugins of ServiceType Plasma/ContainmentActions. + +Component Description +--------------------- +ContainmentAction plugins are registered using .desktop files. These files should be +named using the following naming scheme: + + plasma-containmentactions-.desktop + +If a containmentactions plugin provides a configuration UI, +it should include the line X-Plasma-HasConfigurationInterface=true. + +All other entries should follow the standard .desktop specification, +supplemented by the standard KPluginInfo keys. + +Component API +------------- +Subclasses: QObject + +*** Key Methods *** + + void contextEvent(QEvent *event); +Implement this method to get events. you'll probably want to check the event type and send different +events to your own methods; see the plugins in workspace for examples. +Currently you can expect to get mouse press, release, and wheel events. +If you're showing a menu you should use MousePress and ignore MouseRelease. +If you're performing an immediate action you should ignore MousePress and use MouseRelease. + +The incoming event will always have the buttons and modifiers that the user configured as the trigger, so +there's no sense in checking those values. + + void init(const KConfigGroup &config); +Do whatever initialization is needed here (not in the constructor). + +A configuration UI can optionally be provided by overloading the configuration methods: + QWidget* createConfigurationInterface(QWidget* parent); + void configurationAccepted(); + void save(KConfigGroup &config); + +when configurationAccepted is called, you should read from your config UI and extract all your data +from it; the UI may be deleted after the function returns. +when save is called, save that data to the provided config group. + +if your plugin needs to be configured before it is useful, call setConfigurationRequired() from +init(). + +Containment Interface +--------------------- +The Containment class supports loading and using containmentactions plugins. +Subclasses need do nothing to get this support. If a subclass has extra actions it wants in the +contextmenu, it can provide them in contextualActions() the same as before - but there's no longer +any need to return standard actions like "add widgets" and "run command". + +ContextActions plugins to use are set using the setContainmentActions(const QString &trigger, const QString &pluginName) +method. an empty string removes any plugin set for the given trigger. +Trigg format is determined by the static function ContextActions::eventToString(). + +User Configuration +------------------ +It is up to the host application to provide a configuration interface, such +as a dialog, to the user. + +*** Plasma Desktop Implementation *** + +A settings dialog is provided for the DesktopView (a second page in the same dialog as the wallpaper) + +This dialog allows selecting one trigger for each installed plugin. + +Future Work +----------- +* Current UI in shells/desktop/ needs work. + diff --git a/design/context b/design/context new file mode 100644 index 0000000000..c0571fc2cb --- /dev/null +++ b/design/context @@ -0,0 +1,33 @@ + +Context is about who i am, where i am, and what i'm doing. It's my identiity, my environment and my activities. + +Identity +--------- + +[note: I don't think I really grok this. someone please find a better way to explain it] +My identity is... me. And my various hats. My logins for IM, facebook, email, etc. My status. The ability to have a separate identity for work? social desktop stuff? +It's also your login - files, config, etc. + + +Environment +----------- + +My environment affects a lot of little things. The room lighting affects the ideal brightness of my screen. Battery state affects how aggressive the laptop's powersaving should be. Time of day and location can be good predictors of what i'm working on (or whether silent mode is a good idea). Location can also indicate what timezone and weather is most useful. Network availabiity and my device formfactor affect what i can do. Who's with me is important too- i don't want my private stuff out when there are people looking over my shoulder. The computer can't detect all of those, but it should take advantage of whatever information it *does* have. + + +Activities +---------- + +My activities affect how i work. Each project tends to have its own files, resources and tools - with some degree of overlap, of course. When i'm working on one, i want everything for that task at my fingertips, and all unrelated things out of my way. I may even want a separate identity for some of them... + +The current activity is what i'm doing *now*, and the others are things i have been doing (and probably will return to). + + +Implementation +-------------- + +Activities have been implemented; identity and environment have not. + +in libplasma, there is a Context class; this has become a class to hold context information that is *local* to a containment (like which activity it belongs to); each containment has its own Context*. global context, such as location, will probably be held elsewhere when it is implemented. + + diff --git a/design/dataengine b/design/dataengine new file mode 100644 index 0000000000..95242dc564 --- /dev/null +++ b/design/dataengine @@ -0,0 +1,62 @@ +DataEngine +========== + +Overview +-------- +A Plasma::DataEngine provides read access to data via a standardized API. DataEngine is design specifically with visualizations in mind: the data structure is simple, the data is implicitly shared amongst all visualizations and many requirements are provided by the infrastructure "for free" to a DataEngine to support this mission. + +The data is exposed as a simple two level tree; the first level is made up of "sources", each of which contains a dictionary of key/value pairs. The model is purposefully simplified in this manner to prevent complicated arbitrary data structures from being exported in ways that would make it more difficult than necessary for writers of visualizations (e.g. Plasmoids). + +Users of DataEngines are usually refered to as "visualizations" as they most often provide a user visible (or audible) representation of the data. + + +Timeline +-------- +DataEngine was a part of the original libplasma release. + + +Component Type +-------------- +DataEngines are plugins of ServiceType Plasma/DataEngine. + + +Component Management +-------------------- +The Plasma::DataEngineManager class provides a loader for DataEngine plugins as well as handles reference counting of them. DataEngineManager follows the singleton pattern. + +When a DataEngine's reference count becomes zero, the DataEngine is deleted by the DataEngineManager. Plasma::Applet uses the DataEngineManager internally to provide access to DataEngines for Plasmoids. DataEngines may also be loaded directly without using DataEngineManager, but then are not otherwise managed. + +If an engine is requested of DataEngineManager that either does not exist or can not be loaded (e.g. due to a flaw in the plugin library), then a NullEngine is returned. In all cases, however, DataEngineManager will return a valid object. + + +Sources +------- +Each source is represented internally by a Plasma::DataContainer. The DataContainer does two things: it holds the key/value dictionary and it manages multiple connections drawing data at different points in time (See: Polling). Each source in a DataEngine must have a unique name. + +Often a DataEngine implementation will not handle DataContainers directly, but let the DataEngine class manage them implicitly with calls to setData. However, a DataEngine can create it's own DataContainers; this is usually done when each DataContainer represents an asynchronous job, allowing for the job to be encapsulated. + +A DataEngine may create as many (or as few) sources on its own as is reasonable. This is useful for DataEngines which represent sets of data such as hotplugged devices which do not make sense as queryable items. + +Engines may also place an upper limit on the number of sources that may be active at any time. When this limit is reached, the least recently used source is dropped in favour of newer sources. + + +Visualizations +-------------- +Visualizations are notified via signals of new sources being added, existing sources being removed and the data in existing sources being changed. Visualizations may also query for the current state of a source without connecting to it. + +When connecting to a source, the object passed to the conntectSource method as the visualization will have its dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) slot called whenever the source changes or when the polling interval expires (whichever is later). + +When a source that doesn't exist is requested, the DataEngine is prompted to create a matching source via a sourceRequestEvent. The DataEngine is not required to create a source, however. Sources created in response to a sourceRequestEvent are automatically discarded when the last visualization connected to it disconnects. + + +Polling +------- +DataEngine allows both engine-wide polling as well as per-source/visualization polling. This is handled completely internally and results in updateSourceEvent calls. A visualization may request to be updated every N milliseconds; this will be rounded to the nearest 50ms and matched with other similar calls. Additionally, a DataEngine may request an all-sources-update every N millseconds. Multiple polling intervals on the same source are handled internally, and a minimum polling frequency may be set by the DataEngine to prevent too many calls to updateSourceEvent for the same source. + + +Services +-------- +A Plasma::Service may be associated with any source. Visualizations can retrieve the Service by calling serviceForSource. The returned service should already be associated by the DataEngine with the source in question. Therefore a Service to post to an online blogging service that is requested using the source that represents the account would post to that account. This prevents visualizations from having to load Services themselves from plugins or pre-configure them. It also allows DataEngines a way to provide mutators for sources. + +Unlike sources, Services are not shared. They are unique to the caller of serviceForSource and therefore do not need to be made multi-user safe. + diff --git a/design/ideas.txt b/design/ideas.txt new file mode 100644 index 0000000000..4ca3f0950f --- /dev/null +++ b/design/ideas.txt @@ -0,0 +1,53 @@ +Random ideas for animations usage + +== Animation code == + + - improve the design (in progress) + - rewind the animation ............................................ done! + - cache the animations ............................................ done! + - cache the animation parameters + - pulser using pixmap ............................................. done! + - fix opacity in pulser + - ZoomAnimation + - GeoAnimation + + +== Pimp my plasmoid == + +1) ublog + - edit box moved to inside of scrollwidget scrollwidget::ensureitemvisible() + - rotation when changing Timeline --> Replies --> Messages + - pulse on link selection + - fade in when selecting edit box + - drop shadow on photo + + +2) dictionary + - new busy widget + - kinetic scrolling + + +3) rss reader + - slide for post paging + - pulse for selection + + +4) weather plasmoid + - slide left <----> right for details X "3 days views" + - animated objects (sun, clouds, etc) + + +== plasma-netbook == + + - pulse the whole applet when click the maximize button in the +titlebar of the applets in the newspaper (maybe reuse it in plasma-desktop) + - grow/shrink on selection + - pulse on click + - animated layouts .................................................. done! + - kinetic scrolling: for scrollwheel events in panel ................ done! + + +== plasma widgets == + + - port then to new plasma::Animator + - tune up busy widget (small circles expand and fade out) diff --git a/design/notifications b/design/notifications new file mode 100644 index 0000000000..0939c82f76 --- /dev/null +++ b/design/notifications @@ -0,0 +1,67 @@ +Notifications visualization +=========================== + +Overview +-------- +Plasma-desktop offers facilities to display the visual notifications confirming to the Freedesktop's notification specification, this document describes the component used to achieve the visualization in the most informative, while less distracting way. + +Components +---------- +* Notification dataengine: this exposes the org.freedesktop.Notifications interface, collecting notifications arriving from all applications, in a cross-desktop fashion. + As all dataengines, it organizes the notification datafields in a Plasma::Dataengine::Data structure +* Systemtray widget: (TODO: move out of systray) the widget connects to the Notifications dataengine and provides a proper visualization for the arriving notifications. An important distinction is done between the "alert" aspect of them and a pure informative one, providing two different user interfaces for them. + +Visualization components +------------------------ + +Alert + +As soon as notifications arrive, they are placed in the NotificationStack widget: it is an automatic popup, so in order to disturb the user workflow as less as possible, the size is kept fairly small, limiting the maximum nuber of notification displayed. For the same reason ony one notification at a time is displayed: the oldest (newest?) one, with the others partially covered, but permitting to still see the title. +Moving the mouse over the title of the semi-hidden notifications will show them completely. +The NotificationStack window is always on top of every other window. +When a new notification arrives it is added in the NotificationStack with the following strategy: +* Let MAX be the maximum number of allowed notifications, usually 4 +* If the current displayed notifications is less than MAX place the new notification partially covered in the last position +* If MAX notifications are already there + * If there i at least one notification of the same application remove it (or the oldest if more than one) + * Elese remove the oldest notification from the stack +* Place the new notification partially covered in the last position + +To view partially hidden notifications is enough to move the mouse over its title. the notification will show, hiding the previously showing one. +Clicking on an action button, removes a notification from the stack. +Clicking anywhere in the stack area hides the whole stack, but in order to prevent accidental closing, only after a second of timeout after +* A new notification appeared +* A notification was open, closing the old one + + +Information + +If the user missed some notification, it's possible to view the old ones by manually invoking a different ui by hitting the "i" button. +The notifications are contained in a widget called NotificationScroller, that appears as a popup window. A tabbar lets the user filter the notifications by the sender application (useful for instance if the user is looking for informations about completition of an old running file tranfer or battery warning notices). +Notifications are in a scrolling view that permits a fairly large amount of those to be displayed without using too much screen space. +It features also the the following behaviour: +* If a new notification arrives the current status of the widget is not changed, to not interrupt the user workflow. (current selected tab and scrollbar value) +* If the user manually dismisses a notification, bot there and in the NotificationStack it goes away both in the NotificationStack and in the NotificationScroller + + +Notifications and jobs +---------------------- + +Alert + +* Completed jobs are treated as any other notification. They appear in the NotificationStack at first and are left available for a while in the NotificationScroller +* When there is at least one running job a tiny popup containing only a progressbar and a brief summary is always shown, unless the main popup with controls for each individual job is open. It shows the average of progress of all jobs, we will now refer to it as JobsOverview +* JobsOverview is shown on top of every other window at first, but other windows that gain focus after it can cover the JobsOverview window +* If the main popup is opened, JobsOverview is hidden, shown automatically again as soon as the main popup is closed. +* When the NotificationStack appears, the JobOverview is automatically moved to make room for the notifications, and moved back again when NotificationStack is hidden. + + +Information + +When the user opens the main widget popup that contains the NotificationScroller, if there are running jobs, they are shown individually as ExtenderItems in the same popup. The extenderItem contains: +* A title with the application icon, the job type (such as copying, moving or deleting) and controls to pause/stop or resume the job +* The body contains + * The source and destination URLs + * A progressbar to show the job status + * Optional extra informations such as file size, transfer speed and size already transfered + diff --git a/design/plasma-desktop-screen-handling b/design/plasma-desktop-screen-handling new file mode 100644 index 0000000000..d86078daf3 --- /dev/null +++ b/design/plasma-desktop-screen-handling @@ -0,0 +1,14 @@ +How Screens Get Managed +----------------------- +* PlasmaApp handles the views +* DesktopCorona handles the containments with the help of Activity classes + +So: +* When a screen is added: DesktopCorona tells the current Activity, which adds a new containment if needed. PlasmaApp responds to their creation +* When a screen is removed: PlasmaApp removes the associated view(s); we don't want the Containment to go away, however, since the screen may return +* When a screen changes geometry: the Views (DesktopView, PanelView) change their geometry and that of their containments if needed + +Future work: +* Migration of panels from non-existent screens to existing screens (perhaps asking if the user would like them to migrate?) +* 'hibernation' of containments from non-existent screens (Activity will handle this) + diff --git a/design/plasmoids b/design/plasmoids new file mode 100644 index 0000000000..701857317e --- /dev/null +++ b/design/plasmoids @@ -0,0 +1,82 @@ +Plasmoids +========= + +What is a widget? +================ +In the context of Plasma, a "widget" is a single, self-contained graphical object on the canvas. They can be added and removed individually, configured separately from other widgets, etc. These "mini appliations" are sometimes referred to in other widget platforms as "applets", "apps", "gadgets", "karambas", "desklets". We chose the word "widget" for Plasma as it is used by other some other existing systems. + +The API of a widget is defined by the host "ScriptEngine", with the exception of native Plasma widgets written in C++ which allows plugins in loadable librareis which use the API of the Plasma library directly. Currently Plasma supports both such "native" widgets written in C++, ones written in various dynamic languages (Plasmoids) as well as: + +* SuperKaramba's karambas +* Enlightenment 17 edje content +* MacOS dashboard widgets (though not all) + +These are loaded via host AppletScriptEngine plugins that bridge between the widget itself and Plasma's canvas. + +What is a Plasmoid? +================== +A Plasmoid is a widget that can be loaded into Plasma that uses the native Plasma API and comes packaged in a single archive file that includes the code, metadata, images, configuration defintions, etc. Plasmoids may be currently written in the following languages / APIs: + +* HTML/JavaScript widgets (essentially "web pages for Plasma"): they are limited to a small subset of the Plasma library API and DataEngines +* Simplified JavaScript: these are written in JavaScript but use a managed set of API from the Plasma library and elsewhere; these are the most likely to be widely portable between Plasma instances and are the most securable. +* Full JavaScript: a work in progress, this provides full access to the Plasma, KDE and Qt APIs +* Ruby: full access to the Plasma, KDE, Qt and other Ruby APIs are provided +* Python: full access to the Plasma, KDE, Qt and other Python APIs are provided + +There are tutorials for the various APIs avaiable here: http://techbase.kde.org/Development/Tutorials/Plasma + +The Plasmoid Package +==================== +A Plasmoid package is a single archive file compressed using the zip compression algorithm. By convention they have a .plasmoid suffix. + +The layout of a Plasmoid package is as follows, starting with the root (/) being the top of the zip archive: + +metadata.desktop: a .desktop file (INI format) following the standard KPluginInfo layout. See more about this file below. +contents/ + code/ -> where all the scripts are kept + main -> by default, the name of the script to start the Plasmoid from + config/ -> KConfigXT and INI files describing configuration variables + main.xml -> main config file, KConfigXT xml + default-configrc -> default configuration, INI file + configui/ -> Qt Designer files describing configuration dialog pages + config.ui -> main configuration UI + images/ -> image files of various formats + translations/ -> po files for individual translations; each translation should appear in subdirectories named after the language code + ui/ -> user interface description files, usually Qt Designer + +The Metadata File +================= +The metadata.desktop file contains information about the widget that is critical to proper function. This file is a standard "INI format" file with one group in it called [Desktop Entry]. A typical such file appears below: + +[Desktop Entry] +Name=JavaScript Animations +Comment=An example showing how animations can be used from JavaScript +Encoding=UTF-8 +Icon=plasma +ServiceTypes=Plasma/Applet +Type=Service +X-KDE-PluginInfo-Author=Aaron Seigo +X-KDE-PluginInfo-Category=Examples +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-Email=plasma-devel@kde.org +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-PluginInfo-License=BSD +X-KDE-PluginInfo-Name=javascript-animations-example +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-Website=http://plasma.kde.org/ +X-Plasma-API=javascript + +The icon can either refer to a file in the root of the package by the same name, or a standard icon theme icon name. + +Important fields include: + + * X-KDE-PluginInfo-Name= what the widget will be referred to internally and MUST be unique; as such a "reverse domain name" approach is a good idea, e.g. "org.foo.somewidget". + * X-Plasma-API entry defines which language and API the widget is written for and dictates which ScriptEngine will be loaded for it. + +Useful optional fields include: + * X-Plasma-MainScript= path relative to the contents/ dir of the package; used to override the default of "contents/code/main" + +Installing and Replacing +======================== +Plasmoid packages can be installed and removed from the Add Widgets interfaces of various Plasma applications, such as plasma desktop, or directly using the plasmapkg binary. See the output of `plasmapkg --help` for more information on using that utility. + diff --git a/design/remotewidgets b/design/remotewidgets new file mode 100644 index 0000000000..27d501da02 --- /dev/null +++ b/design/remotewidgets @@ -0,0 +1,40 @@ +Overview +-------- + +Since KDE 4.4, libplasma supports publishing and accessing plasma applets across the network. This allows users to use plasma applets as visualization on remote data. What happens when accessing a remote applet is the following: + +* A connection is established, and the server can check the clients credentials and decide whether or not to allow access. The plasma shell running on the server can decide which policies to use to determine whether or not access is granted. See the section 'security' in this document for more information. +* In the case of a scripted plasmoid, the entire plasmoid package is sent to the client. The client puts the package in a temporary directory, and loads the scripted plasmoid from there. In the case of a binary applet, just the plugin name is sent over so the client can just load the appropriate plugin. This unfortunately requires the client to have the same plugin installed as the server, so scripted plasmoids are obviously preferred. +* Whenever this remoted plasmoid calls dataEngine() or serviceForSource() these calls return a special subclass of DataEngine/Service that actually invokes the dataengine or service on the remote machine. This is all completely transparent to the applet. These subclasses are located in the "private/" directory in libplasma and are called RemoteDataEngine and RemoteService. On the first call to dataEngine/serviceForSource, the server is notified and publishes the requested dataEngine or Service, if that hasn't already happened. Publishing happens through RemoteDataEngine and RemoteService's counterparts: ServiceProvider and DataEngineProvider, also both private classes. + +Public API +---------- + +The remote widgets feature adds some new public API to libplasma, mostly aimed at plasma shells. They allow a shell to: +* Access remote widgets. (AccessManager/AccessAppletJob) +* Obtain a list of remote widgets that are announced on the network, and receive notifications when widgets appear/disappear. (AccessManager) +* Publish widgets on the network. (Applet::publish(), Applet::unpublish(), Applet::isPublished()) +* Set one of the sensible default security policy on incoming connections... (AuthorizationManager) +* ... or provide an own implementation of a security policy by implementing an AuthorizationInterface and setting it as customAuthorizationInterface in AuthorizationManager. + +Security +-------- + +The plasma shell can control the security aspects of remote widgets, combined with a system wide config file (/etc/plasma-remotewidgets.conf) containing rules that can allow/disallow certain machines access to certain published widgets/services/engines. As a plasma shell you've got the following options: + +* Use one of the sensible presets in which case you don't have to case about security. The only thing you'll need to do is set the desired behavior using AuthorizationManager::self()->setAuthorizationPolicy(). This will set the AuthorizationInterface implementation to one of the ones built in into libplasma. Do note that even when you whish to use the default policy (DenyAll), you should still call this function, since that automatically locks this value so a potential malicious plasma plugin can't change this to serve it's own evil desires. +* Supply your own behavior by implementing AuthorizationInterface, set authorizationPolicy to custom, and use AuthorizationManager::self()->setAuthorizationInterface() to your own implementation. + +Security wise, every incoming message will get processed as follows: + +Every message that gets sent to the server get's a signature appended. Signing happens with an RSA key that is generated for you if it doesn't exist already, and then stored in the kde wallet, so your private key for signing doesn't change from that moment on. When starting a connection, the full credentials of the client are sent along, later messages just contain a hash of the key to identify the sender without having to put all the information in every message. +Whenever a message is received and the Credential's trustLevel is at least ValidCredentials (meaning, the signature of the message is at least valid for the public key), the combination service name and public key signature is used to see if there are any AuthorizationRules that already match this request. These are both rules defined in /etc/plasma-remotewidgets.conf and rules that are created for the current plasma session only. If a matching rule is found, it is applied (that is, the message is either accepted or denied). Else a new rule is created, that is at that moment still Undefined. This rule, containing an instance of Credential that can be used to obtain a trustLevel, will be passed to the active AuthorizationInterface's authorizationRequest. The interface can then decide to either accept or deny the request, or request PIN pairing, in which case the user will have to enter the same password on both client and server to establish a connection. +NOT YET IMPLEMENTED: additionally, a message can also be signed with a GPG key, in which case the trustLevel can go beyond ValidCredentials. Either by having that key in your trusted keyring, or, for UltimateCredentials, having it signed by the plasma overlords themselves. + +JOLIE +----- + +For the actual communication, the sodep protocol is used (JOLIE's native protocol), through the QtJolie library. At the moment, as the library has not yet been released, a branch private to libplasma is used. JOLIE itself is not yet a runtime dependency, QtJolie just claims a socket, listens to incoming sodep messages, and routes them to the appropriate destination. At some point in the near future, when QtJolie gets some more functionality, we'll want to use JOLIE's metaservice to route the messages, which adds the added benefit that we can communicate with metaservice through jolie, and have metaservice convert it into other protocols. A nice addition is that we can then use secure sodep so all the data will get encrypted. And with the addition of a new Service subclass it will also become very easy to access SOAP webservices. + + + diff --git a/design/screensaver b/design/screensaver new file mode 100644 index 0000000000..37c703335d --- /dev/null +++ b/design/screensaver @@ -0,0 +1,61 @@ +Plasma and the Screensaver +========================== + +There are three main pieces to the screensaver picture, two of which involve plasma. +first is lockprocess, which manages the other two. second is the [k|x]screensaver binaries which just draw +pretty pictures. third is plasma-overlay, which does the plasma stuff. + +lockprocess +----------- +This process manages plasma and the screensaver binaries, and ensures that once the screen is locked +it *stays* locked until proper authentication is provided. It provides the unlock dialog too. +If a screensaver or plasma-overlay +crashes or becomes unresponsive, lockprocess will keep going, ensuring that a locked screen stays locked and can +still be unlocked by the user. It's as small as possible to keep the chances of it itself crashing very small. +The screensaver binaries are brought in via XEmbed, while communication with plasma-overlay happens +over dbus. +lockprocess also filters all keyboard and mouse events, passing them on to plasma-overlay as +necessary. if it suspects that plasma-overlay is dead (ie. dbus failure), it won't pass on events, +ensuring that the user never ends up with an unresponsive screensaver. + +plasma-overlay +-------------- +This process is a plasma shell; it has a corona and a simple view, and loads its own containment. +The containment used by plasma-overlay is very basic; just a customcontainment with a cashew +and applet handles. + +the user can add applets, but not containments. there's configuration for transparency if you have +compositing, or wallpaper if not (random wallpaper slideshow is my poor-man's-screensaver). all +configuration and applet add/remove are disabled when the screen is locked. + +it communicates with lockprocess over dbus. lockprocess will send it into an idle mode after a while +(where any events trigger the unlock dialog, and plasma-overlay uses a different transparency +setting), and tell it to go into active mode when there's activity again. when an unlock action in +plasma is activated, plasma-overlay asks lockprocess for permission, and lockprocess will ask the +user for their password (or whatever other authentication method). + +when the screen is locked, plasma-overlay offers two actions to the user: leave screensaver and +configure widgets. the first is what you'd expect; you enter your password and all of lockprocess goes +away, letting you back into your desktop. the second is more like unlocking widgets in +plasma-desktop: it brings you into configuration mode where you can add, remove and configure +widgets. this config mode can also be reached from the screensaver kcm module. from config mode you +can exit at any time without entering a password; you can also re-lock the screen, of course. + +if lockprocess vanishes from dbus, plasma-overlay will assume that it missed a signal to quit and +will commit suicide. :) this is intentional; I got sick of dbus race conditions leaving me with a +plasma-overlay hanging around if I moved the mouse just after the screensaver began to run. + +security +--------- + +Plasmoids on the screensaver obviously present a security risk. this is being minimized as described +in the security document. +what makes it interesting is that we're less concerned with malicious +plasmoids and more with malicious (or mischevious) users; a locked screen left unattended should not +end up with goatse on it, or files deleted. + +Future Work +----------- +* Multi-screen support would be awesome +* Plasmify the unlock dialog (either by using plasma theming or by having plasma-overlay run it) + diff --git a/design/security b/design/security new file mode 100644 index 0000000000..f3dee85e43 --- /dev/null +++ b/design/security @@ -0,0 +1,57 @@ +Security +======== + +overview +-------- + +plasma will have three types of security: +-co-operative +-trust-based +-enforced + +co-operative security +--------------------- + +this is fairly basic security for plasmoids. +the idea is, shells (like plasma-overlay) can specify a list of constraints in their desktop file, and then all plasmoids that require the disabled feature don't show up in the appletbrowser. also, plasmoids that would like a certain feature but don't *need* it can check hasAuthorization() and turn it off when it's not allowed. +This type of security relies heavily on plasmoid developers. Each plasmoid's .desktop file must list what features the plasmoid requires, and be kept up to date with the code. X-Plasma-Requires- can be set to Required, Unused, or Optional. Example: X-Plasma-Requires-FileDialog=Required +Features the plasmoid would like but does not require should be guarded by hasAuthorization, and set to Optional in the .desktop. [example](http://websvn.kde.org/?view=rev&revision=967792). +All the plasmoids in workspace and kdeplasma-addons should probably be reviewed before release. some of them don't have an active maintainer to take responsibility. + +Currenly, plasmoids that don't mention a constraint are assumed to not use it. however, by release time the opposite should be true. this is just so that they don't *all* disappear from the screensaver before anyone has a chance to review their plasmoids. +Note that this will not remove existing instances of plasmoids. It only hides them from the appletbrowser. Users who really really want to can edit the config file to add unsafe applets. + +Existing constraints/features: +-FileDialog. When this is restricted, use of open or save dialogs is forbidden. Reason: users can delete files from there and cause all kinds of havoc. +-LaunchApp. When this is restricted, running other applications or opening urls (generally done through KRun) is forbidden. Reason: although they're not accessible from the screensaver, they can still pile up and need to be closed after the screen's unlocked. + +^^ this is obviously not a final list. more will be added soon. + +possible problems: +-the API isn't designed for constraints changing at runtime. does anyone think that's likely to matter someday? +-I have no idea how this will affect alien widgets. personally I'd be fine with banning those from the screensaver until proper, full security can be implemented. + + +trust-based security +-------------------- + +gpg signing of plasmoids + + +enforced security +---------------- + +This is security that doesn't rely on plasmoid developers. Mostly it's about disabling access to features via the scripting API, so that plasmoids using that API absolutely cannot use the disabled features. + +it'd be nice if we could use KAuthorized to enforce some stuff on the c++ applets... I tried, but didn't get anywhere. + + +misc +---- + +I'm not sure what categories these fall under. + +category exclusion: entire categories of plasmoids can be excluded from hte appletbrowser. for example, application launchers are excluded from the screensaver because they'd never ever be wanted there. + +configuration locking: on the screensaver, config dialogs can't be accessed while the screen is locked. however, it's possible for a c++ plasmoid to override showConfigurationInterface and circumvent this. + diff --git a/design/standardEffects b/design/standardEffects new file mode 100644 index 0000000000..6205bac978 --- /dev/null +++ b/design/standardEffects @@ -0,0 +1,22 @@ +Standard Graphical Effects +========================== + +This document lists the standard effects provided by (or yet to be implemented) in libplasma. + +CrossFade +--------- +Fades between two images. + +Parameters: + * Source image + * Destination image + * Timelapse (0 -> use standard time setting) + +Spin +---- +Creates the illusion of spinning an item to show its back. + +Parameters: + * Source QGraphicsItem + * Destination QGraphicsItem + diff --git a/design/systemtraywidget b/design/systemtraywidget new file mode 100644 index 0000000000..8bd9f689fe --- /dev/null +++ b/design/systemtraywidget @@ -0,0 +1,55 @@ +The system tray widget is divided into three parts: core, ui and protocols. + +Core +---- +Core provides the three basic concepts that drive the widget: + * Task: an icon in the tray + * Notification: a visual notification from an application + * Job: a long running job such as a file transfer + +Protocol implements a source for Tasks, Notifications and/or Jobs and has a set +of signals used to announce the coming and going of its items. At its discretion, +a Protocol can create (or destroy) Tasks, Notifications and Jobs at any time. + +A Manager class is provided in Core that looks after and tracks the three kinds of items +along with all the Protocols. The Manager instantiates the Protocols and relays the +critical signals, allowing the widget to simply pay attention to the Manager and +treat all Tasks, Notifications and Jobs as if they came from the same place. The Manager +is able to treat all Protocols generically using the Protocol API. + +All Task implementations provide a way to return a QGraphicsWidet for given host. +The mapping between hosts and widgets is handled automatically by the Task class, and +this, along with the central Manager, allows any Task to be shared simultaneously across +multiple widgets. + +Notifications and Jobs don't have this problem as they simply provide access to +data which the ui is reponsible for showing in some way. + +Also provided in the core is a Task specifically for managing the Extenders of a host +Plasma::Applet for Jobs and Notifications call, rather creatively, ExtenderTask. + + +Protocols +--------- +The following protocols currently exist: + +DBusSystemTrayProtocol: support for the dbus driven NotificationItem; it provides Tasks; + for information on the design of this protocol, consult the + KStatusNotifierItem documentation + +FdoProtocol: support for the XEmbed based freedesktop.org system tray specification; + it provides Tasks, though these tasks do not work properly in more than one + widget at a time due to limitations in the XEmbed system + +JobsProtocol: access to the applicationjobs DataEngine; it provides Jobs + +NotificationsProtocol: access to the notificadtions DataEngine; it provides Notifications + +PlasmoidProtocol: features Plasmoids-wrapped-in-Tasks; is not currently fully functional + + +The UI +------ +The user interface consists of a Plasma::Applet class, a layout class and a TasksArea which +contains the Tasks published. The UI features the ability to order as well as hide items, +register new Tasks, etc. diff --git a/design/tooltips b/design/tooltips new file mode 100644 index 0000000000..7d4bbb5874 --- /dev/null +++ b/design/tooltips @@ -0,0 +1,39 @@ +Tooltips +========== + +Overview +-------- +libplasma provides facilities to manage tooltips that display extended information in a visually pleasing and consistent manner for QGraphicsWidgets. These tooltip windows are themed using Plasma::Theme. + +Timeline +-------- +Introduced in: libplasma 2.1 (KDE 4.2.0) + +Component Type +-------------- +ToolTipManager is a QObject subclass in libplasma. +ToolTip is an internal QWidget subclass in libplasma. + +Registering Tooltips +-------------------- +ToolTipManger is quite simple to use: simply call setWidgetToolTipContent using the struct ToolTipContent. This causes the widget to be registered if it isn't already. Alternatively, for widgets that fill the data on demand, call registerWidget directly. + +Widgets are unregistered automatically upon destruction, but can also be manually unregsitered by calling ToolTipMnager::unregisterWidget. + +An event filter is registered on each registered widget and hover events that occur trigger calls to showToolTip and hideToolTip. The hover events are not, however, filtered out. + +Note: If another event filter is placed on registered widget that filters out these events, it may be necessary to manually call showToolTip and hideToolTip. + +ToolTip Updates +--------------- +Updating tooltip data is supported by means of invoking slots on the associated widget if they exist. In particular, just prior to being shown the toolTipAboutToShow method is invoked and when hiding the toolTipHidden method is invoked. + +ToolTip Visualization +--------------------- +The internal (non-exported) ToolTip class is used to actually display the tooltips. These are associated with widgets and created as necessary. + +ToolTip displays are only created when data is set, and are deleted if an empty ToolTipData struct is passed in. This keeps memory usage due to ToolTip objects down. + +Future Work +----------- +N/A diff --git a/design/wallpaper b/design/wallpaper new file mode 100644 index 0000000000..ae623266e4 --- /dev/null +++ b/design/wallpaper @@ -0,0 +1,99 @@ +Wallpapers +========== + +Overview +-------- +"Wallpapers" are components that paint the background for Containments that +do not provide their own background rendering. + +Timeline +-------- +Introduced in: libplasma 2.1 (KDE 4.2.0) + +Component Type +-------------- +Wallpapers are plugins of ServiceType Plasma/Wallpaper. + +Component Description +--------------------- +Wallpaper plugins are registered using .desktop files. These files should be +named using the following naming scheme: + + plasma-wallpaper-.desktop + +If a wallpaper plugin provides more than on mode (e.g. Single Image, Wallpaper) +it should include a Actions= entry in the .desktop file, listing the possible +actions. An actions group should be included to provide for translatable names. + +Example: + +> Actions=SingleImage,Slideshow +> +> [Desktop Action SingleImage] +> Name=Image +> Icon=image-jpg + +All other entries should follow the standard .desktop specification, +supplemented by the standard KPluginInfo keys. + +If a wallpaper plugin should be constrained to a specific set of FormFactors, +include a list of those FormFactors using the X-Plasma-FormFactors key. + +Defined categories for wallpapers include: + * Single Image + * Slideshow + * Animated + * OpenGL + * Interactive + +Component API +------------- +Subclasses: QObject + +*** Key Properties *** + +boundingRect: the geometry to paint the wallpaper into +formFactors: the Plasma::FormFactors this wallpaper supports (e.g. Planar) + +*** Key Methods *** + +The update(QRectF) signal must be emitted whenever the wallpaper needs a repaint. +This might happen in response to the wallpaper changing (such as in a slidshow) +or due to an animation update. Keeping the exposed area to a minimum is important. + +Painting is done in the paint(QPainter *painter, const QRectF &exposed area) +method, and will be called when a paint operation should be done, either due to +an external event or in response to an update request from the wallpaper. + +A configuration UI can optionally be provided by overloading the configuration +method. + +Containment Interface +--------------------- +The Containment class supports loading and using a wallpaper plugin. +Subclasses need do nothing to get this support, and can opt out of +wallpaper support by calling setDrawWallpaper(false). + +When a wallpaper plugin is used, Wallpaper::paint is called from +Applet::paint. + +The Wallpaper plugin to use is set using the setWallpaper(const QString &pluginName) +method. + +User Configuration +------------------ +It is up to the host application to provide a configuration interface, such +as a dialog, to the user to embed the wallpaper config in. + +*** Plasma Desktop Implementation *** + +A setting dialog is provided by the View (DesktopView, PanelView, etc). + +This dialog allows selecting both the Containment type for +the current Activity associated with the view as well as selecting the +Wallpaper plugin for the Containment. + +Future Work +----------- +* Wallpapers should be ScriptEngine-able +* Ability to define which wallpapers a Containment is compatible with? \ No newline at end of file diff --git a/design/widgets b/design/widgets new file mode 100644 index 0000000000..62be62987e --- /dev/null +++ b/design/widgets @@ -0,0 +1,43 @@ +Widgets +======= + +Overview +-------- + +Within libplasma there are a collection of widgets (Plasma::PushButton, Plasma::Slider, Plasma::TabWidget, Plasma::WebContent, etc.) which all follow a common API theme. The intention of this API is to provide a very simple way for users to create plasma applets. Plasma is not primarily a widget library, and so a simple wrapping of native Qt widgets is provided. + +By providing a consistent, simple API that hides details like QGraphicsProxyWidget, the bar is lowered to entry and the time to create Applets is reduced. + +The API can be used both for scripting and from C++. For the simple ECMAScript API for instance, this API will be all that is provided allowing untrusted applets to be run with a great measure of safety as they will not have access to any dangerous facilities. + +From C++ or more advanced scripting APIs (such as the 'full' ECMAScript bindings) you can gain access to a pointer to the underlying Qt widget contained within the QGraphicsProxy via the nativeWidget() method, allowing access all of its methods. For most simple uses however, this should be unnecessary as you can do most of the customisation using the Qt stylesheet facilities. + +All widgets have a stylesheet, which is a string property containing a Qt stylesheet. This allows for simple but powerful configuration of the widgets - for example you can configure the alignment of the text in the label using the text-align property, or the font using the font property. Using this you can do some extremely advanced interfaces without having to learn how Qt works. + +A nice side effect of the way this API is defined is that it is possible to implement the simple widget API inside a web browser using HTML, javascript and HTML stylesheets to provide the implementation. + +Standardized API +---------------- + +Properties, setters and getters are defined for: + + * parent widget + * text + * image (supports SVG as well as pixmap) + * stylesheet + * native widget + +Widgets may add to this standardized API the most commonly used or important signals, slots and properties from the widget in question. Plasma::Checkbox, for instance, adds the toggled(bool) signal and properties for the checked state. These additions should be kept the essentials only to keep within the spirit of the simplicity and safety of the API; remember that the full widget is available via nativeWidget(). + +Look and Feel +------------- + +For most widgets, we let the QStyle do the painting. + +For certain widgets (e.g. Plasma::PushButton), the painting is overridden to blend in better with a Plasma based interface. This can be done without reimplemeting the entire native Qt widget by reimplementing the paint methods in either the QGraphicsWidget or a subclass of the native Qt Widget. Another approach is to use a custom QStyle, which is how Plasma::Slider gets its look with minimal code. + +Creating a New Widget +--------------------- + +Included with the libplasma sources is a make_widget.sh script and a set of templates in the widgets/ directory. Running it with the name of the widget to create (e.g. make_widget.sh CoolWidget) will create a base implementation of a widget using the standard API. From there, only the widget specific signals, slots and properties need be added. + diff --git a/desktoppackage/Messages.sh b/desktoppackage/Messages.sh new file mode 100644 index 0000000000..aef1b02337 --- /dev/null +++ b/desktoppackage/Messages.sh @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +$XGETTEXT `find . -name \*.qml` -L Java -o $podir/plasma_shell_org.kde.desktop.pot +rm -f rc.cpp diff --git a/desktoppackage/contents/activitymanager/ActivityBrowser.qml b/desktoppackage/contents/activitymanager/ActivityBrowser.qml new file mode 100644 index 0000000000..aa6b36265c --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityBrowser.qml @@ -0,0 +1,160 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.activities 0.1 as Activities + +Item { + id: root + width: 208 + + property int spacing: 2 * units.smallSpacing + + property bool showingDialog: + newActivityDialog.visible || + activityList.showingDialog + + Connections { + target: parent + onVisibleChanged: { + newActivityDialog.close(); + activityList.closeDialogs(); + } + } + + signal closeRequested() + + focus: true + + Keys.onPressed: { + if (newActivityDialog.visible || activityList.showingDialog) { + event.accepted = false; + } else { + if (event.key == Qt.Key_Escape) { + if (heading.showSearch) + heading.showSearch = false; + else + root.closeRequested(); + + } else if (event.key == Qt.Key_Up) { + console.log("UP KEY"); + + } else if (event.key == Qt.Key_Down) { + console.log("DOWN KEY"); + + } else if (event.key == Qt.Key_Return || event.key == Qt.Key_Enter) { + console.log("ENTER KEY"); + + } else if (event.key == Qt.Key_Tab) { + console.log("TAB KEY"); + + } else { + console.log("OTHER KEY"); + heading.showSearch = true; + + } + } + } + + // Rectangle { + // anchors.fill : parent + // opacity : .4 + // color : "white" + // } + + Heading { + id: heading + + anchors { + top: parent.top + left: parent.left + right: parent.right + + topMargin: units.largeSpacing + } + } + + PlasmaExtras.ScrollArea { + anchors { + top: heading.bottom + bottom: bottomPanel.top + left: parent.left + right: parent.right + topMargin: root.spacing + } + + flickableItem: ActivityList { + id: activityList + + filterString: heading.searchString.toLowerCase() + + onShowingDialogChanged: + if (showingDialog) newActivityDialog.close() + } + } + + Item { + id: bottomPanel + + height: newActivityButton.height + units.largeSpacing + + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + + PlasmaComponents.ToolButton { + id: newActivityButton + + text: "Create activity..." + iconSource: "list-add" + + width: parent.width + + onClicked: { + activityList.closeDialogs(); + newActivityDialog.open(newActivityDialog.height / 2); + } + + opacity: 1 - newActivityDialog.opacity + } + + ActivityCreationDialog { + id: newActivityDialog + + z: 100 + + anchors.bottom: newActivityButton.bottom + anchors.left: newActivityButton.left + anchors.right: newActivityButton.right + + onAccepted: { + activityList.model.addActivity(activityName, function (id) { + activityList.model.setActivityIcon(id, newActivityDialog.activityIconSource, function() {}); + }) + } + } + } +} + diff --git a/desktoppackage/contents/activitymanager/ActivityCreationDialog.qml b/desktoppackage/contents/activitymanager/ActivityCreationDialog.qml new file mode 100644 index 0000000000..fc5ff78572 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityCreationDialog.qml @@ -0,0 +1,197 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.platformcomponents 2.0 as PlasmaPlatformComponents +import org.kde.activities 0.1 as Activities + +PlasmaCore.FrameSvgItem { + id: root + + signal accepted() + signal canceled() + + imagePath: "dialogs/background" + + property alias activityName: activityNameText.text + property alias activityIconSource: activityIconButton.iconSource + + property alias acceptButtonText: acceptButton.text + property alias cancelButtonText: cancelButton.text + + property string activityId: "" + + MouseArea { + anchors.fill: parent + hoverEnabled: true + } + + function open(verticalPosition) + { + y = verticalPosition - height / 2; + opacity = 1; + } + + function close() + { + opacity = 0; + iconDialog.closeDialog(); + } + + opacity: 0 + visible: false + Behavior on opacity { PropertyAnimation { duration: units.shortDuration } } + Behavior on y { PropertyAnimation { + duration: root.visible ? units.shortDuration : 0 + } } + onOpacityChanged: visible = (opacity > 0) + + PlasmaCore.FrameSvgItem { + id: shadowFrame + + imagePath: "dialogs/background" + prefix: "shadow" + + z: -1 + + anchors { + fill: parent + + leftMargin : -margins.left + topMargin : -margins.top + rightMargin : -margins.right + bottomMargin : -margins.bottom + } + } + + height: content.height + margins.top + margins.bottom + dialogButtons.height + + Item { + id: content + + anchors { + left : parent.left + right : parent.right + top : parent.top + + topMargin : root.margins.top + leftMargin : root.margins.left + bottomMargin : root.margins.bottom + rightMargin : root.margins.right + } + + PlasmaComponents.Button { + id: activityIconButton + + anchors { + left: parent.left + top: parent.top + } + + width: height + height: activityNameLabel.height + activityNameText.height + + PlasmaPlatformComponents.IconDialog { + id: iconDialog + } + + onClicked: { + var newIcon = iconDialog.openDialog() + if (newIcon != "") { + activityIconButton.iconSource = newIcon; + } + } + + } + + height: activityNamePanel.height + + Column { + id: activityNamePanel + anchors { + left: activityIconButton.right + top: parent.top + right: parent.right + + leftMargin: units.largeSpacing + } + + PlasmaComponents.Label { + id: activityNameLabel + text: i18n("Activity name:") + + elide: Text.ElideRight + + width: parent.width + } + + PlasmaComponents.TextField { + id: activityNameText + + width: parent.width + + // text: "" + } + + Item { + height: units.largeSpacing + width: parent.width + } + } + } + + PlasmaComponents.ButtonRow { + id: dialogButtons + + anchors { + right: parent.right + bottom: parent.bottom + rightMargin: root.margins.right + bottomMargin: root.margins.bottom + } + + exclusive: false + + PlasmaComponents.Button { + id: acceptButton + + text: i18n("Create") + iconSource: "list-add" + onClicked: { + root.close(); + root.accepted(); + } + } + + PlasmaComponents.Button { + id: cancelButton + + text: i18n("Cancel") + iconSource: "dialog-close" + onClicked: { + root.close(); + root.canceled(); + } + } + } +} diff --git a/desktoppackage/contents/activitymanager/ActivityDeletionDialog.qml b/desktoppackage/contents/activitymanager/ActivityDeletionDialog.qml new file mode 100644 index 0000000000..42197face4 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityDeletionDialog.qml @@ -0,0 +1,131 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +PlasmaCore.FrameSvgItem { + id: root + + signal accepted() + signal canceled() + + imagePath: "dialogs/background" + + property string activityId: "" + + + + + + + + MouseArea { + anchors.fill: parent + hoverEnabled: true + } + + function open(verticalPosition) + { + y = verticalPosition - height / 2; + opacity = 1; + } + + function close() + { + opacity = 0; + } + + opacity: 0 + visible: false + Behavior on opacity { PropertyAnimation { duration: units.shortDuration } } + Behavior on y { PropertyAnimation { + duration: root.visible ? units.shortDuration : 0 + } } + onOpacityChanged: visible = (opacity > 0) + + PlasmaCore.FrameSvgItem { + id: shadowFrame + + imagePath: "dialogs/background" + prefix: "shadow" + + z: -1 + + anchors { + fill: parent + + leftMargin : -margins.left + topMargin : -margins.top + rightMargin : -margins.right + bottomMargin : -margins.bottom + } + } + + height: content.height + margins.top + margins.bottom + Column { + id: content + + anchors { + left: parent.left + right: parent.right + + topMargin: root.margins.top + leftMargin: root.margins.left + bottomMargin: root.margins.bottom + rightMargin: root.margins.right + } + + PlasmaComponents.Label { + text: i18n("Are you sure you want to delete the activity?") + width: parent.width + } + + Item { + height: units.largeSpacing + width: parent.width + } + + PlasmaComponents.ButtonRow { + exclusive: false + + PlasmaComponents.Button { + text: i18n("Delete") + iconSource: "list-remove" + onClicked: { + root.close(); + root.accepted(); + } + } + PlasmaComponents.Button { + text: i18n("Cancel") + iconSource: "dialog-close" + onClicked: { + root.close(); + root.canceled(); + } + } + + } + + } +} diff --git a/desktoppackage/contents/activitymanager/ActivityItem.qml b/desktoppackage/contents/activitymanager/ActivityItem.qml new file mode 100644 index 0000000000..6cb436ef40 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityItem.qml @@ -0,0 +1,186 @@ +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras + +Item { + id: root + + property int innerPadding : units.largeSpacing + + property bool current : false + property bool inFocus : false + + property alias title : title.text + property alias icon : icon.source + + property string background : "" + + onBackgroundChanged: if (background[0] != '#') { + // We have a proper wallpaper, hurroo! + backgroundWallpaper.source = background + backgroundColor.visible = false + + } else { + // We have only a color + backgroundColor.color = background + backgroundColor.visible = true + } + + signal clicked + signal configureClicked + signal stopClicked + + width : 200 + height : width * 1 / units.displayAspectRatio + + // Background until we get something real + PlasmaCore.FrameSvgItem { + id: highlight + imagePath: "widgets/viewitem" + visible: root.current || root.inFocus + + anchors { + fill: parent + rightMargin: -highlight.margins.right + bottomMargin: -highlight.margins.bottom + } + + prefix: + root.current ? "selected" : "normal" + + } + + Item { + anchors { + fill: parent + + leftMargin: highlight.margins.left + topMargin: highlight.margins.top + } + + // Background until we get something real + Rectangle { + id: backgroundColor + anchors.fill: parent + color: "black" + + opacity: .5 + } + + Image { + id: backgroundWallpaper + anchors.fill: parent + + visible: !backgroundColor.visible + } + + // Title and the icon + + Rectangle { + id: shade + + color : "black" + opacity : .5 + + height : title.height + 2 * title.anchors.margins + width : parent.width + + anchors { + bottom : parent.bottom + left : parent.left + right : parent.right + } + } + + PlasmaCore.IconItem { + id: icon + + width : units.iconSizes.medium + height : width + + anchors { + bottom : parent.bottom + left : parent.left + margins : root.innerPadding + } + } + + PlasmaComponents.Label { + id: title + + color : "white" + elide : Text.ElideRight + + anchors { + bottom : parent.bottom + left : icon.right + right : parent.right + margins : root.innerPadding * 2 + } + } + + // Controls + + MouseArea { + id: rootArea + + anchors.fill : parent + hoverEnabled : true + + onClicked : root.clicked() + } + + ControlButton { + id: stopButton + + onClicked: root.stopClicked() + + icon: "close" + + anchors { + right : parent.right + top : parent.top + margins : root.innerPadding + } + } + + ControlButton { + id: configButton + + onClicked: root.configureClicked() + + icon: "configure" + + anchors { + left : parent.left + top : parent.top + margins : root.innerPadding + } + } + + states: [ + State { + name: "plain" + PropertyChanges { target: stopButton; opacity: 0 } + PropertyChanges { target: configButton; opacity: 0 } + }, + State { + name: "showControls" + PropertyChanges { target: stopButton; opacity: 1 } + PropertyChanges { target: configButton; opacity: 1 } + } + ] + + transitions: [ + Transition { + NumberAnimation { + properties : "opacity" + duration : units.shortDuration + } + } + ] + + state: rootArea.containsMouse ? "showControls" : "plain" + } +} diff --git a/desktoppackage/contents/activitymanager/ActivityList.qml b/desktoppackage/contents/activitymanager/ActivityList.qml new file mode 100644 index 0000000000..8871647b53 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityList.qml @@ -0,0 +1,199 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.activities 0.1 as Activities + + +Flickable { + id: root + + /*contentWidth: content.width*/ + contentHeight: content.height + + property var model: activitiesModel + property string filterString: "" + property bool showingDialog: activityDeletionDialog.visible || activityConfigurationDialog.visible + + function closeDialogs() + { + activityDeletionDialog.close(); + activityConfigurationDialog.close(); + } + + Activities.ActivityModel { + id: activitiesModel + + shownStates: "Running,Stopping" + } + + Activities.ActivityModel { + id: stoppedActivitiesModel + + shownStates: "Stopped,Starting" + } + + ActivityDeletionDialog { + id: activityDeletionDialog + z: 10 + + width: parent.width + + onAccepted: { + activitiesModel.removeActivity(activityDeletionDialog.activityId, function () {}) + } + } + + ActivityCreationDialog { + id: activityConfigurationDialog + z: 10 + + acceptButtonText: i18n("Apply") + + width: parent.width + + onAccepted: { + var id = activityConfigurationDialog.activityId + activitiesModel.setActivityName(id, + activityConfigurationDialog.activityName, + function () {}); + activitiesModel.setActivityIcon(id, + activityConfigurationDialog.activityIconSource, + function () {}); + } + } + + Column { + id: content + + width: parent.width + + // Running activities + + Repeater { + model: activitiesModel + + ActivityItem { + + width: parent.width + + visible : (root.filterString == "") || + (title.toLowerCase().indexOf(root.filterString) != -1) + + title : model.name + icon : model.iconSource + background : model.background + current : model.current + innerPadding : 2 * units.smallSpacing + + onClicked : { + activitiesModel.setCurrentActivity(model.id, function () {}) + } + + onStopClicked : { + activitiesModel.stopActivity(model.id, function () {}); + } + + onConfigureClicked : { + activityConfigurationDialog.activityId = model.id; + activityConfigurationDialog.activityName = title; + activityConfigurationDialog.activityIconSource = icon; + + var selfLocation = mapToItem(root, width / 2, height / 2); + activityConfigurationDialog.open(selfLocation.y); + activityDeletionDialog.close(); + } + } + } + + // Stopped activities + + Item { + // spacer + width : parent.width + height : units.largeSpacing + } + + PlasmaExtras.Heading { + text: "Stopped activities:" + level: 3 + visible: stoppedActivitiesList.count > 0 + } + + Repeater { + id: stoppedActivitiesList + + model: stoppedActivitiesModel + + delegate: StoppedActivityItem { + id: stoppedActivityItem + + width: parent.width + + visible : (root.filterString == "") || + (title.toLowerCase().indexOf(root.filterString) != -1) + + title : model.name + icon : model.iconSource + innerPadding : 2 * units.smallSpacing + + onClicked : { + stoppedActivitiesModel.setCurrentActivity(model.id, function () {}) + } + + onDeleteClicked : { + activityDeletionDialog.activityId = model.id; + + var selfLocation = mapToItem(root, width / 2, height / 2); + activityDeletionDialog.open(selfLocation.y); + activityConfigurationDialog.close(); + } + + onConfigureClicked : { + activityConfigurationDialog.activityId = model.id; + activityConfigurationDialog.activityName = title; + activityConfigurationDialog.activityIconSource = icon; + + var selfLocation = mapToItem(root, width / 2, height / 2); + activityConfigurationDialog.open(selfLocation.y); + activityDeletionDialog.close(); + } + } + } + + add: Transition { + NumberAnimation { + properties: "x" + from: -100 + duration: units.shortDuration + } + } + + move: Transition { + NumberAnimation { + id: animation + properties: "y" + duration: units.longDuration + } + } + } +} + diff --git a/desktoppackage/contents/activitymanager/ActivityManager.qml b/desktoppackage/contents/activitymanager/ActivityManager.qml new file mode 100644 index 0000000000..ca10713735 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ActivityManager.qml @@ -0,0 +1,54 @@ +/* + * Copyright 2013 Marco Martin + * Copyright 2014 Ivan Cukic + * + * This program 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 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 Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.activities 0.1 as Activities + +Item { + id: main + signal closed() + + function parentClosed() { + activityBrowser.parentClosed(); + } + + //this is used to perfectly align the filter field and delegates + property int cellWidth: theme.mSize(theme.defaultFont).width * 30 + property int spacing: 2 * units.smallSpacing + + property int minimumWidth: cellWidth + 4 * 2 + property int minimumHeight: 0 + + property bool showingDialog: activityBrowser.showingDialog + + width: minimumWidth + + ActivityBrowser { + id: activityBrowser + + onCloseRequested: main.closed() + + anchors.fill: parent + } +} + diff --git a/desktoppackage/contents/activitymanager/ControlButton.qml b/desktoppackage/contents/activitymanager/ControlButton.qml new file mode 100644 index 0000000000..1e9854f5a1 --- /dev/null +++ b/desktoppackage/contents/activitymanager/ControlButton.qml @@ -0,0 +1,59 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore + +PlasmaCore.SvgItem { + id: root + + signal clicked + + property alias icon: innerIcon.elementId + + width : units.iconSizes.smallMedium + height : units.iconSizes.smallMedium + /*flat : false*/ + + svg: PlasmaCore.Svg { imagePath: "widgets/actionbutton" } + elementId : mouseArea.pressed ? "pressed" : "normal" + + PlasmaCore.SvgItem { + id: innerIcon + + anchors.centerIn: parent + + // TODO: Ugly X + width : units.iconSizes.small - (root.icon == "close" ? 4 : 0) + height : width + + svg: PlasmaCore.Svg { imagePath: "widgets/configuration-icons" } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + + onClicked: root.clicked() + } +} + + diff --git a/desktoppackage/contents/activitymanager/Heading.qml b/desktoppackage/contents/activitymanager/Heading.qml new file mode 100644 index 0000000000..ea0560ecb1 --- /dev/null +++ b/desktoppackage/contents/activitymanager/Heading.qml @@ -0,0 +1,118 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras + +Item { + id: root + + property alias showSearch : searchButton.checked + property alias searchString : searchText.text + + Keys.onPressed: { + if (event.key == Qt.Key_Escape) { + if (root.showSearch) { + event.accepted = true; + searchButton.checked = false; + } + } + } + + onShowSearchChanged: if (showSearch) searchText.focus = true + + height : heading.height + width : parent.width + + PlasmaComponents.ToolButton { + id: searchButton + iconSource: "edit-find" + + checkable: true + checked: root.showSearch + + anchors { + right : parent.right + top : parent.top + bottom : parent.bottom + } + + onCheckedChanged: { + if (!checked) searchText.text = ""; + } + } + + PlasmaExtras.Title { + id: heading + text: "Activities" + + anchors { + left : parent.left + right : searchButton.left + bottom : parent.bottom + top : parent.top + } + } + + PlasmaComponents.TextField { + id: searchText + + focus: true + + anchors { + left : parent.left + right : searchButton.left + bottom : parent.bottom + top : parent.top + } + + onTextChanged: { + if (text.length > 0) { + root.showSearch = true + } + } + } + + states: [ + State { + name: "normal" + PropertyChanges { target: searchText; opacity: 0 } + PropertyChanges { target: heading; opacity: 1 } + }, + State { + name: "search" + PropertyChanges { target: searchText; opacity: 1 } + PropertyChanges { target: heading; opacity: 0 } + } + ] + + transitions: [ + Transition { + NumberAnimation { + properties : "opacity" + duration : units.shortDuration + } + } + ] + + state: showSearch ? "search" : "normal" +} diff --git a/desktoppackage/contents/activitymanager/StoppedActivityItem.qml b/desktoppackage/contents/activitymanager/StoppedActivityItem.qml new file mode 100644 index 0000000000..c5dcb980d6 --- /dev/null +++ b/desktoppackage/contents/activitymanager/StoppedActivityItem.qml @@ -0,0 +1,158 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras + +Item { + id: root + + property int innerPadding: units.smallSpacing + + property alias title : title.text + property alias icon : icon.source + + /*signal clicked*/ + signal configureClicked + signal deleteClicked + signal clicked + + width : 200 + height : icon.height + innerPadding * 2 + + // Background until we get something real + PlasmaCore.FrameSvgItem { + id: highlight + imagePath: "widgets/viewitem" + visible: rootArea.containsMouse + + anchors { + fill: parent + rightMargin: -highlight.margins.right + bottomMargin: -highlight.margins.bottom + } + + prefix: "normal" + } + + Item { + anchors { + fill: parent + + leftMargin: highlight.margins.left + topMargin: highlight.margins.top + } + + // Title and the icon + + PlasmaCore.IconItem { + id: icon + + width : units.iconSizes.medium + height : width + + anchors { + left : parent.left + margins : root.innerPadding + verticalCenter: parent.verticalCenter + } + } + + PlasmaComponents.Label { + id: title + + elide : Text.ElideRight + + anchors { + left : icon.right + right : parent.right + margins : root.innerPadding * 2 + verticalCenter: parent.verticalCenter + } + } + + // Controls + + MouseArea { + id: rootArea + + anchors.fill : parent + hoverEnabled : true + + onClicked : root.clicked() + } + + ControlButton { + id: deleteButton + + onClicked: root.deleteClicked() + + icon: "delete" + + anchors { + right : parent.right + top : parent.top + margins : root.innerPadding + } + } + + ControlButton { + id: configButton + + onClicked: root.configureClicked() + + icon: "configure" + + anchors { + left : parent.left + top : parent.top + margins : root.innerPadding + } + } + + states: [ + State { + name: "plain" + PropertyChanges { target: deleteButton; opacity: 0 } + PropertyChanges { target: configButton; opacity: 0 } + }, + State { + name: "showControls" + PropertyChanges { target: deleteButton; opacity: 1 } + PropertyChanges { target: configButton; opacity: 1 } + } + ] + + transitions: [ + Transition { + NumberAnimation { + properties : "opacity" + duration : units.shortDuration + } + } + ] + + state: rootArea.containsMouse ? "showControls" : "plain" + } +} + + diff --git a/desktoppackage/contents/activitymanager/WindowPreview.qml b/desktoppackage/contents/activitymanager/WindowPreview.qml new file mode 100644 index 0000000000..295a1637dc --- /dev/null +++ b/desktoppackage/contents/activitymanager/WindowPreview.qml @@ -0,0 +1,75 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2014 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2.2 + +Image { + id: main + + width: 480 + height: 425 + + source: "images/window2.png" + anchors.centerIn: parent + + Item { + id: title + + + width: titleText.width + 32 + height: titleText.height + 32 + + Rectangle { + anchors.fill: parent + color: "black" + radius: 8 + opacity: .7 + } + + Text { + id: titleText + color: "white" + text: "Firefox" + font.pointSize: 24 + + anchors.centerIn: parent + } + + + + } + + Drag.active: mouseArea.drag.active + Drag.hotSpot.x: 32 + Drag.hotSpot.y: 32 + + MouseArea { + id: moudeArea + anchors.fill: parent + + drag { + target: title + } + + onClicked: console.log("Clicked") + } +} + + diff --git a/desktoppackage/contents/applet/AppletError.qml b/desktoppackage/contents/applet/AppletError.qml new file mode 100644 index 0000000000..790b57c7a6 --- /dev/null +++ b/desktoppackage/contents/applet/AppletError.qml @@ -0,0 +1,45 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Row { + id: root + + property alias reason: messageText.text + + clip: true + + PlasmaCore.IconItem { + id: icon + anchors.verticalCenter: parent.verticalCenter + width: units.iconSizes.huge + height: width + source: "dialog-error" + } + + PlasmaComponents.Label { + id: messageText + anchors.verticalCenter: parent.verticalCenter + width: parent.width - icon.width + wrapMode: Text.Wrap + } +} diff --git a/desktoppackage/contents/applet/CompactApplet.qml b/desktoppackage/contents/applet/CompactApplet.qml new file mode 100644 index 0000000000..5a15bdda1b --- /dev/null +++ b/desktoppackage/contents/applet/CompactApplet.qml @@ -0,0 +1,134 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +PlasmaCore.ToolTipArea { + id: root + objectName: "org.kde.desktop-CompactApplet" + anchors.fill: parent + + icon: plasmoid.icon + mainText: plasmoid.toolTipMainText + subText: plasmoid.toolTipSubText + location: plasmoid.location + active: !plasmoid.expanded + property Item fullRepresentation + property Item compactRepresentation + property Item expandedFeedback: expandedItem + + onCompactRepresentationChanged: { + compactRepresentation.parent = root; + compactRepresentation.anchors.fill = root; + compactRepresentation.visible = true; + root.visible = true; + } + + onFullRepresentationChanged: { + + //if the fullRepresentation size was restored to a stored size, or if is dragged from the desktop, restore popup size + if (fullRepresentation.width > 0) { + popupWindow.mainItem.width = fullRepresentation.width; + } else if (fullRepresentation.Layout && fullRepresentation.Layout.preferredWidth > 0) { + popupWindow.mainItem.width = fullRepresentation.Layout.preferredWidth + } else if (fullRepresentation.implicitWidth > 0) { + popupWindow.mainItem.width = fullRepresentation.implicitWidth + } else { + popupWindow.mainItem.width = theme.mSize(theme.defaultFont).width * 35 + } + + if (fullRepresentation.height > 0) { + popupWindow.mainItem.height = fullRepresentation.height; + } else if (fullRepresentation.Layout && fullRepresentation.Layout.preferredHeight > 0) { + popupWindow.mainItem.height = fullRepresentation.Layout.preferredHeight + } else if (fullRepresentation.implicitHeight > 0) { + popupWindow.mainItem.height = fullRepresentation.implicitHeight + } else { + popupWindow.mainItem.width = theme.mSize(theme.defaultFont).height * 25 + } + + fullRepresentation.parent = appletParent; + fullRepresentation.anchors.fill = fullRepresentation.parent; + } + + PlasmaCore.FrameSvgItem { + id: expandedItem + anchors.fill: parent + imagePath: "widgets/tabbar" + prefix: { + var prefix; + switch (plasmoid.location) { + case PlasmaCore.Types.LeftEdge: + prefix = "west-active-tab"; + break; + case PlasmaCore.Types.TopEdge: + prefix = "north-active-tab"; + break; + case PlasmaCore.Types.RightEdge: + prefix = "east-active-tab"; + break; + default: + prefix = "south-active-tab"; + } + if (!hasElementPrefix(prefix)) { + prefix = "active-tab"; + } + return prefix; + } + opacity: plasmoid.expanded ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: theme.shortDuration + easing: Easing.InOutQuad + } + } + } + + PlasmaCore.Dialog { + id: popupWindow + objectName: "popupWindow" + flags: Qt.WindowStaysOnTopHint + visible: plasmoid.expanded && fullRepresentation + visualParent: compactRepresentation ? compactRepresentation : null + location: plasmoid.location + hideOnWindowDeactivate: plasmoid.hideOnWindowDeactivate + + mainItem: Item { + id: appletParent + Layout.minimumWidth: (fullRepresentation && fullRepresentation.Layout) ? fullRepresentation.Layout.minimumWidth : 0 + Layout.minimumHeight: (fullRepresentation && fullRepresentation.Layout) ? fullRepresentation.Layout.minimumHeight: 0 + Layout.maximumWidth: (fullRepresentation && fullRepresentation.Layout) ? fullRepresentation.Layout.maximumWidth : Infinity + Layout.maximumHeight: (fullRepresentation && fullRepresentation.Layout) ? fullRepresentation.Layout.maximumHeight: Infinity + } + + onVisibleChanged: { + if (!visible) { + plasmoid.expanded = false + } else { + // This call currently fails and complains at runtime: + // QWindow::setWindowState: QWindow::setWindowState does not accept Qt::WindowActive + popupWindow.requestActivate(); + } + } + + } +} diff --git a/desktoppackage/contents/applet/DefaultCompactRepresentation.qml b/desktoppackage/contents/applet/DefaultCompactRepresentation.qml new file mode 100644 index 0000000000..ecfb5f880b --- /dev/null +++ b/desktoppackage/contents/applet/DefaultCompactRepresentation.qml @@ -0,0 +1,36 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore + +PlasmaCore.IconItem { + id: icon + + source: plasmoid.icon ? plasmoid.icon : "plasma" + active: mouseArea.containsMouse + + MouseArea { + id: mouseArea + + anchors.fill: parent + hoverEnabled: true + onClicked: plasmoid.expanded = !plasmoid.expanded + } +} \ No newline at end of file diff --git a/desktoppackage/contents/configuration/AppletConfiguration.qml b/desktoppackage/contents/configuration/AppletConfiguration.qml new file mode 100644 index 0000000000..cf8b7862f4 --- /dev/null +++ b/desktoppackage/contents/configuration/AppletConfiguration.qml @@ -0,0 +1,262 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 +import org.kde.plasma.configuration 2.0 + + +//TODO: all of this will be done with desktop components +Rectangle { + id: root + +//BEGIN properties + color: syspal.window + width: units.gridUnit * 40 + height: units.gridUnit * 30 +//END properties + +//BEGIN model + property ConfigModel globalConfigModel: globalAppletConfigModel + + ConfigModel { + id: globalAppletConfigModel + ConfigCategory { + name: "Keyboard shortcuts" + icon: "preferences-desktop-keyboard" + source: "ConfigurationShortcuts.qml" + } + } +//END model + +//BEGIN functions + function saveConfig() { + if (main.currentItem.saveConfig) { + main.currentItem.saveConfig() + } else { + for (var key in plasmoid.configuration) { + if (main.currentItem["cfg_"+key] !== undefined) { + plasmoid.configuration[key] = main.currentItem["cfg_"+key] + } + } + } + } + + function restoreConfig() { + for (var key in plasmoid.configuration) { + if (main.currentItem["cfg_"+key] !== undefined) { + main.currentItem["cfg_"+key] = plasmoid.configuration[key] + } + } + } +//END functions + + +//BEGIN connections + Component.onCompleted: { + if (configDialog.configModel && configDialog.configModel.count > 0) { + main.sourceFile = configDialog.configModel.get(0).source + main.title = configDialog.configModel.get(0).name + } else { + main.sourceFile = globalConfigModel.get(0).source + main.title = globalConfigModel.get(0).name + } + root.restoreConfig() +// root.width = mainColumn.implicitWidth +// root.height = mainColumn.implicitHeight + } +//END connections + +//BEGIN UI components + SystemPalette {id: syspal} + + ColumnLayout { + id: mainColumn + anchors { + fill: parent + margins: mainColumn.spacing //margins are hardcoded in QStyle we should match that here + } + property int implicitWidth: Math.max(contentRow.implicitWidth, buttonsRow.implicitWidth) + 8 + property int implicitHeight: contentRow.implicitHeight + buttonsRow.implicitHeight + 8 + + RowLayout { + id: contentRow + anchors { + left: parent.left + right: parent.right + } + spacing: units.largeSpacing + Layout.fillHeight: true + Layout.preferredHeight: parent.height - buttonsRow.height + + QtControls.ScrollView { + id: categoriesScroll + frameVisible: true + anchors { + top: parent.top + bottom: parent.bottom + } + visible: (configDialog.configModel ? configDialog.configModel.count : 0) + globalConfigModel.count > 1 + width: visible ? 100 : 0 + implicitWidth: width + Flickable { + id: categoriesView + contentWidth: width + contentHeight: childrenRect.height + anchors.fill: parent + + property Item currentItem: categoriesColumn.children[1] + + Item { + id: categories + width: parent.width + height: categoriesColumn.height + + Item { + width: parent.width + height: categoriesView.currentItem.height + y: categoriesView.currentItem.y + Rectangle { + color: syspal.highlight + radius: 3 + anchors { + fill: parent + margins: 2 + } + } + Behavior on y { + NumberAnimation { + duration: units.longDuration + easing.type: "InOutQuad" + } + } + } + Column { + id: categoriesColumn + width: parent.width + Repeater { + model: configDialog.configModel + delegate: ConfigCategoryDelegate { + onClicked: { + categoriesView.currentIndex = index + pageTitle.text = name; + } + + } + } + Repeater { + model: globalConfigModel + delegate: ConfigCategoryDelegate {} + } + } + } + } + } + Item { + anchors { + top: parent.top + bottom: parent.bottom + } + Layout.fillWidth: true + height: Math.max(categoriesScroll.height, main.currentItem != null ? main.currentItem.implicitHeight : 0) + + QtControls.Label { + id: pageTitle + anchors { + top: parent.top + left: parent.left + right: parent.right + } + font.pointSize: theme.defaultFont.pointSize*2 + text: main.title + } + + QtControls.StackView { + id: main + property string title: "" + anchors { + top: pageTitle.bottom + topMargin: units.largeSpacing / 2 + left: parent.left + right: parent.right + bottom: parent.bottom + } + clip: true + property string sourceFile + Timer { + id: pageSizeSync + interval: 100 + onTriggered: { + // root.width = mainColumn.implicitWidth + // root.height = mainColumn.implicitHeight + } + } + onImplicitWidthChanged: pageSizeSync.restart() + onImplicitHeightChanged: pageSizeSync.restart() + onSourceFileChanged: { + print("Source file changed in flickable" + sourceFile); + replace(Qt.resolvedUrl(sourceFile)) + /* + * This is not needed on a desktop shell that has ok/apply/cancel buttons, i'll leave it here only for future reference until we have a prototype for the active shell. + * root.pageChanged will start a timer, that in turn will call saveConfig() when triggered + + for (var prop in currentPage) { + if (prop.indexOf("cfg_") === 0) { + currentPage[prop+"Changed"].connect(root.pageChanged) + } + }*/ + } + } + } + } + RowLayout { + id: buttonsRow + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + QtControls.Button { + iconName: "dialog-ok" + text: i18n("Ok") + onClicked: { + if (main.currentItem.saveConfig !== undefined) { + main.currentItem.saveConfig(); + } else { + root.saveConfig(); + } + configDialog.close(); + } + } + QtControls.Button { + iconName: "dialog-ok-apply" + text: i18n("Apply") + onClicked: { + if (main.currentItem.saveConfig !== undefined) { + main.currentItem.saveConfig(); + } else { + root.saveConfig(); + } + } + } + QtControls.Button { + iconName: "dialog-cancel" + text: i18n("Cancel") + onClicked: configDialog.close() + } + } + } +//END UI components +} diff --git a/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml b/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml new file mode 100644 index 0000000000..76dd30d923 --- /dev/null +++ b/desktoppackage/contents/configuration/ConfigCategoryDelegate.qml @@ -0,0 +1,85 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import org.kde.plasma.core 2.0 as PlasmaCore + +MouseArea { + id: delegate + + anchors { + left: parent.left + right: parent.right + } +//BEGIN properties + width: childrenRect.width + height: childrenRect.height + 4 + property bool current: model.source == main.sourceFile + property string name: model.name +//END properties + +//BEGIN connections + onClicked: { + print("model source: " + model.source + " " + main.sourceFile); + if (delegate.current) { + return + } else { + if (typeof(categoriesView.currentItem) !== "undefined") { + categoriesView.currentItem = delegate; + } + main.sourceFile = model.source + main.title = model.name + root.restoreConfig() + } + } + onCurrentChanged: { + if (current) { + categoriesView.currentItem = delegate; + } + } +//END connections + +//BEGIN UI components + Column { + spacing: 4 + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + right: parent.right + topMargin: _m + } + PlasmaCore.IconItem { + anchors.horizontalCenter: parent.horizontalCenter + width: theme.IconSizeHuge + height: width + source: model.icon + } + QtControls.Label { + anchors { + left: parent.left + right: parent.right + } + text: model.name + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + color: current ? syspal.highlightedText : syspal.text + } + } +//END UI components +} diff --git a/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml b/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml new file mode 100644 index 0000000000..9985356fd1 --- /dev/null +++ b/desktoppackage/contents/configuration/ConfigurationContainmentActions.qml @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 + +Item { + id: root + + implicitWidth: childrenRect.width + implicitHeight: childrenRect.height + + property var prettyStrings: { + "LeftButton": i18n("Left-Button"), + "RightButton": i18n("Right-Button"), + "MidButton": i18n("Middle-Button"), + + "wheel:Vertical": i18n("Vertical-Scroll"), + "wheel:Horizontal": i18n("Horizontal-Scroll"), + + "ShiftModifier": i18n("Shift"), + "ControlModifier": i18n("Ctrl"), + "AltModifier": i18n("Alt"), + "MetaModifier": i18n("Meta") + } + + function saveConfig() { + configDialog.currentContainmentActionsModel.save(); + } + + Column { + anchors { + top: parent.top + topMargin: 25 + horizontalCenter: parent.horizontalCenter + } + + Repeater { + model: configDialog.currentContainmentActionsModel + delegate: RowLayout { + width: root.width + MouseEventInputButton { + defaultText: prettyStrings ? (prettyStrings[model.action.split(';')[1]] ? prettyStrings[model.action.split(';')[1]] + "+" : "") + prettyStrings[model.action.split(';')[0]] : "" + eventString: model.action + onEventStringChanged: { + configDialog.currentContainmentActionsModel.update(index, eventString, model.pluginName); + } + } + + QtControls.ComboBox { + id: pluginsCombo + Layout.fillWidth: true + model: configDialog.containmentActionConfigModel + textRole: "name" + property bool initialized: false + Component.onCompleted: { + for (var i = 0; i < configDialog.containmentActionConfigModel.count; ++i) { + if (configDialog.containmentActionConfigModel.get(i).pluginName == pluginName) { + pluginsCombo.currentIndex = i; + break; + } + } + pluginsCombo.initialized = true; + } + onCurrentIndexChanged: { + if (initialized && configDialog.containmentActionConfigModel.get(currentIndex).pluginName != pluginName) { + configDialog.currentContainmentActionsModel.update(index, action, configDialog.containmentActionConfigModel.get(currentIndex).pluginName); + } + } + } + QtControls.Button { + iconName: "configure" + width: height + enabled: model.hasConfigurationInterface + onClicked: { + configDialog.currentContainmentActionsModel.showConfiguration(index); + } + } + QtControls.Button { + iconName: "dialog-information" + width: height + onClicked: { + configDialog.currentContainmentActionsModel.showAbout(index); + } + } + QtControls.Button { + iconName: "list-remove" + width: height + onClicked: { + configDialog.currentContainmentActionsModel.remove(index); + } + } + } + } + MouseEventInputButton { + defaultText: i18n("Add Action"); + onEventStringChanged: { + configDialog.currentContainmentActionsModel.append(eventString, "org.kde.contextmenu"); + } + } + } + +} diff --git a/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml b/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml new file mode 100644 index 0000000000..09a0c942f7 --- /dev/null +++ b/desktoppackage/contents/configuration/ConfigurationContainmentAppearance.qml @@ -0,0 +1,106 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.configuration 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 + +ColumnLayout { + id: root + + property int formAlignment: pluginComboBox.x + (units.largeSpacing/2) + property string currentWallpaper: "" + +//BEGIN functions + function saveConfig() { + for (var key in configDialog.wallpaperConfiguration) { + if (main.currentItem["cfg_"+key] !== undefined) { + configDialog.wallpaperConfiguration[key] = main.currentItem["cfg_"+key] + } + } + configDialog.currentWallpaper = root.currentWallpaper; + configDialog.applyWallpaper() + } + + function restoreConfig() { + for (var key in configDialog.wallpaperConfiguration) { + if (main.currentItem["cfg_"+key] !== undefined) { + main.currentItem["cfg_"+key] = configDialog.wallpaperConfiguration[key] + } + } + } +//END functions + + Component.onCompleted: { + for (var i = 0; i < configDialog.wallpaperConfigModel.count; ++i) { + var data = configDialog.wallpaperConfigModel.get(i); + for(var j in data) print(j) + if (configDialog.currentWallpaper == data.pluginName) { + pluginComboBox.currentIndex = i + break; + } + } + } + + Row { + spacing: units.largeSpacing / 2 + Item { + width: units.largeSpacing + height: parent.height + } + QtControls.Label { + anchors.verticalCenter: pluginComboBox.verticalCenter + text: i18n("Wallpaper Type:") + } + QtControls.ComboBox { + id: pluginComboBox + model: configDialog.wallpaperConfigModel + width: theme.mSize(theme.defaultFont).width * 24 + textRole: "name" + onCurrentIndexChanged: { + var model = configDialog.wallpaperConfigModel.get(currentIndex) + root.currentWallpaper = model.pluginName + main.sourceFile = model.source + configDialog.currentWallpaper = model.pluginName + root.restoreConfig() + } + } + } + + Item { + id: emptyConfig + } + + QtControls.StackView { + id: main + Layout.fillHeight: true; + anchors { + left: parent.left; + right: parent.right; + } + property string sourceFile + onSourceFileChanged: { + if (sourceFile != "") { + replace(Qt.resolvedUrl(sourceFile)) + } else { + replace(emptyConfig); + } + } + } +} diff --git a/desktoppackage/contents/configuration/ConfigurationShortcuts.qml b/desktoppackage/contents/configuration/ConfigurationShortcuts.qml new file mode 100644 index 0000000000..4f004dc47a --- /dev/null +++ b/desktoppackage/contents/configuration/ConfigurationShortcuts.qml @@ -0,0 +1,33 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.kquickcontrols 2.0 + +Item { + width: childrenRect.width + height: childrenRect.height + + KeySequenceItem { + id: button + keySequence: plasmoid.globalShortcut + onKeySequenceChanged: { + plasmoid.globalShortcut = button.keySequence + } + } +} diff --git a/desktoppackage/contents/configuration/ContainmentConfiguration.qml b/desktoppackage/contents/configuration/ContainmentConfiguration.qml new file mode 100644 index 0000000000..af3903dadc --- /dev/null +++ b/desktoppackage/contents/configuration/ContainmentConfiguration.qml @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 + + +AppletConfiguration { + id: root + +//BEGIN model + globalConfigModel: globalContainmentConfigModel + + ConfigModel { + id: globalContainmentConfigModel + ConfigCategory { + name: "Wallpaper" + icon: "preferences-desktop-wallpaper" + source: "ConfigurationContainmentAppearance.qml" + } + ConfigCategory { + name: "Mouse Actions" + icon: "preferences-desktop-mouse" + source: "ConfigurationContainmentActions.qml" + } + } +//END model + +} diff --git a/desktoppackage/contents/configuration/MouseEventInputButton.qml b/desktoppackage/contents/configuration/MouseEventInputButton.qml new file mode 100644 index 0000000000..61b5c019c0 --- /dev/null +++ b/desktoppackage/contents/configuration/MouseEventInputButton.qml @@ -0,0 +1,71 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.0 as QtControls +import QtQuick.Layouts 1.0 +import org.kde.plasma.core 2.0 as PlasmaCore + + +QtControls.Button { + id: mouseInputButton + property string defaultText: i18n("Add Action") + text: defaultText + checkable: true + property string eventString + + implicitWidth: theme.mSize(theme.defaultFont).width * 15 + Layout.minimumWidth: implicitWidth + Layout.maximumWidth: implicitWidth + + onCheckedChanged: { + if (checked) { + text = i18n("Input Here"); + mouseInputArea.enabled = true; + } + } + MouseArea { + id: mouseInputArea + anchors.fill: parent + acceptedButtons: Qt.AllButtons + enabled: false + + onClicked: { + var newEventString = configDialog.currentContainmentActionsModel.mouseEventString(mouse.button, mouse.modifiers); + + if (eventString === newEventString || !configDialog.currentContainmentActionsModel.isTriggerUsed(newEventString)) { + eventString = newEventString; + mouseInputButton.text = defaultText; + mouseInputButton.checked = false; + enabled = false; + } + } + + onWheel: { + var newEventString = configDialog.currentContainmentActionsModel.wheelEventString(wheel.pixelDelta, wheel.buttons, wheel.modifiers); + + if (eventString === newEventString || !configDialog.currentContainmentActionsModel.isTriggerUsed(newEventString)) { + eventString = newEventString; + mouseInputButton.text = defaultText; + mouseInputButton.checked = false; + enabled = false; + } + } + } +} + diff --git a/desktoppackage/contents/configuration/PanelConfiguration.qml b/desktoppackage/contents/configuration/PanelConfiguration.qml new file mode 100644 index 0000000000..cf532d7db7 --- /dev/null +++ b/desktoppackage/contents/configuration/PanelConfiguration.qml @@ -0,0 +1,172 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons +import "panelconfiguration" + + +//TODO: all of this will be done with desktop components +PlasmaCore.FrameSvgItem { + id: dialogRoot + +//BEGIN Properties + width: 640 + height: 64 + imagePath: "dialogs/background" + + state: { + switch (panel.location) { + //TopEdge + case PlasmaCore.Types.TopEdge: + return "TopEdge" + //LeftEdge + case PlasmaCore.Types.LeftEdge: + return "LeftEdge" + //RightEdge + case PlasmaCore.Types.RightEdge: + return "RightEdge" + //BottomEdge + case PlasmaCore.Types.BottomEdge: + default: + return "BottomEdge" + } + } + + property bool vertical: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) +//END properties + +//BEGIN Connections + Connections { + target: panel + onOffsetChanged: ruler.offset = panel.offset + onMinimumLengthChanged: ruler.minimumLength = panel.minimumLength + onMaximumLengthChanged: ruler.maximumLength = panel.maximumLength + } +//END Connections + + +//BEGIN UI components + + Ruler { + id: ruler + state: dialogRoot.state + } + + ToolBar { + id: toolBar + } +//END UI components + +//BEGIN Animations + //when EdgeHandle is released animate to old panel position + ParallelAnimation { + id: panelResetAnimation + NumberAnimation { + target: panel + properties: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) ? "x" : "y" + to: { + switch (panel.location) { + case PlasmaCore.Types.TopEdge: + return panel.screenGeometry.y + panel.distance + case PlasmaCore.Types.LeftEdge: + return panel.screenGeometry.x + panel.distance + case PlasmaCore.Types.RightEdge: + return panel.screenGeometry.x + panel.screenGeometry.width - panel.width - panel.distance + case PlasmaCore.Types.BottomEdge: + default: + return panel.screenGeometry.y + panel.screenGeometry.height - panel.height - panel.distance + } + } + duration: units.shortDuration * 3 + } + + NumberAnimation { + target: configDialog + properties: (panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge) ? "x" : "y" + to: { + switch (panel.location) { + case PlasmaCore.Types.TopEdge: + return panel.screenGeometry.y + panel.height + panel.distance + case PlasmaCore.Types.LeftEdge: + return panel.screenGeometry.x + panel.width + panel.distance + case PlasmaCore.Types.RightEdge: + return panel.screenGeometry.x + panel.screenGeometry.width - panel.width - configDialog.width - panel.distance + case PlasmaCore.Types.BottomEdge: + default: + return panel.screenGeometry.y + panel.screenGeometry.height - panel.height - configDialog.height - panel.distance + } + } + duration: units.shortDuration * 3 + } + } +//END Animations + +//BEGIN States +states: [ + State { + name: "TopEdge" + PropertyChanges { + target: dialogRoot + enabledBorders: "TopBorder|BottomBorder" + } + PropertyChanges { + target: dialogRoot + implicitHeight: ruler.implicitHeight + toolBar.implicitHeight + } + }, + State { + name: "BottomEdge" + PropertyChanges { + target: dialogRoot + enabledBorders: "TopBorder|BottomBorder" + } + PropertyChanges { + target: dialogRoot + implicitHeight: ruler.implicitHeight + toolBar.implicitHeight + } + }, + State { + name: "LeftEdge" + PropertyChanges { + target: dialogRoot + enabledBorders: "LeftBorder|RightBorder" + } + PropertyChanges { + target: dialogRoot + implicitWidth: ruler.implicitWidth + toolBar.implicitWidth + } + }, + State { + name: "RightEdge" + PropertyChanges { + target: dialogRoot + enabledBorders: "LeftBorder|RightBorder" + } + PropertyChanges { + target: dialogRoot + implicitWidth: ruler.implicitWidth + toolBar.implicitWidth + } + } + ] +//END States +} diff --git a/desktoppackage/contents/configuration/panelconfiguration/EdgeHandle.qml b/desktoppackage/contents/configuration/panelconfiguration/EdgeHandle.qml new file mode 100644 index 0000000000..38e0915d27 --- /dev/null +++ b/desktoppackage/contents/configuration/panelconfiguration/EdgeHandle.qml @@ -0,0 +1,101 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + +PlasmaComponents.Button { + text: i18n("Screen Edge") + + KQuickControlsAddons.MouseEventListener { + anchors.fill: parent + property int lastX + property int lastY + property int startMouseX + property int startMouseY + onPressed: { + lastX = mouse.screenX + lastY = mouse.screenY + startMouseX = mouse.x + startMouseY = mouse.y + } + onPositionChanged: { + panel.screen = mouse.screen; + + var newLocation = panel.location; + //If the mouse is in an internal rectangle, do nothing + if ((mouse.screenX < panel.screenGeometry.x + panel.screenGeometry.width/3 || + mouse.screenX > panel.screenGeometry.x + panel.screenGeometry.width/3*2) || + (mouse.screenY < panel.screenGeometry.y + panel.screenGeometry.height/3 || + mouse.screenY > panel.screenGeometry.y + panel.screenGeometry.height/3*2)) + { + var screenAspect = panel.screenGeometry.height / panel.screenGeometry.width; + + if (mouse.screenY < panel.screenGeometry.y+(mouse.screenX-panel.screenGeometry.x)*screenAspect) { + if (mouse.screenY < panel.screenGeometry.y + panel.screenGeometry.height-(mouse.screenX-panel.screenGeometry.x)*screenAspect) { + newLocation = PlasmaCore.Types.TopEdge; + } else { + newLocation = PlasmaCore.Types.RightEdge; + } + + } else { + if (mouse.screenY < panel.screenGeometry.y + panel.screenGeometry.height-(mouse.screenX-panel.screenGeometry.x)*screenAspect) { + newLocation = PlasmaCore.Types.LeftEdge; + } else { + newLocation = PlasmaCore.Types.BottomEdge; + } + } + } + panel.location = newLocation + + switch (newLocation) { + case PlasmaCore.Types.TopEdge: + var y = Math.max(mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y, panel.height); + configDialog.y = y; + panel.distance = Math.max(y - panel.height - panel.screen.geometry.y, 0); + break + case PlasmaCore.Types.LeftEdge: + var x = Math.max(mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x, panel.width); + configDialog.x = x; + panel.distance = Math.max(x - panel.width - panel.screen.geometry.x, 0); + break; + case PlasmaCore.Types.RightEdge: + var x = Math.min(mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x, mouse.screen.geometry.x + mouse.screen.size.width - panel.width - configDialog.width); + configDialog.x = x; + panel.distance = Math.max(mouse.screen.size.width - (x - mouse.screen.geometry.x) - panel.width - configDialog.width, 0); + break; + case PlasmaCore.Types.BottomEdge: + default: + var y = Math.min(mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y, mouse.screen.geometry.y + mouse.screen.size.height - panel.height - configDialog.height); + configDialog.y = y; + panel.distance = Math.max(mouse.screen.size.height - (y - mouse.screen.geometry.y) - panel.height - configDialog.height, 0); + } + + lastX = mouse.screenX + lastY = mouse.screenY + } + onReleased: { + panel.distance = 0 + panelResetAnimation.running = true + } + } +} diff --git a/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml b/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml new file mode 100644 index 0000000000..6cdccc997d --- /dev/null +++ b/desktoppackage/contents/configuration/panelconfiguration/Ruler.qml @@ -0,0 +1,356 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + + +PlasmaCore.FrameSvgItem { + id: root + + property alias offset: offsetHandle.value + property alias minimumLength: minimumLengthHandle.value + property alias maximumLength: maximumLengthHandle.value + + imagePath: "widgets/containment-controls" + state: "BottomEdge" + implicitWidth: offsetHandle.width + minimumLengthHandle.width + implicitHeight: offsetHandle.height + minimumLengthHandle.height + + onMinimumLengthChanged: leftMinimumLengthHandle.value = minimumLength + onMaximumLengthChanged: leftMaximumLengthHandle.value = maximumLength + + Component.onCompleted: { + offsetHandle.value = panel.offset + minimumLengthHandle.value = panel.minimumLength + maximumLengthHandle.value = panel.maximumLength + leftMinimumLengthHandle.value = panel.minimumLength + leftMaximumLengthHandle.value = panel.maximumLength + } + + PlasmaCore.Svg { + id: containmentControlsSvg + imagePath: "widgets/containment-controls" + } + PlasmaCore.SvgItem { + id: centerMark + svg: containmentControlsSvg + elementId: dialogRoot.vertical ? "vertical-centerindicator" : "horizontal-centerindicator" + visible: panel.alignment == Qt.AlignCenter + width: dialogRoot.vertical ? parent.width : naturalSize.width + height: dialogRoot.vertical ? naturalSize.height : parent.height + anchors.centerIn: parent + } + + SliderHandle { + id: offsetHandle + graphicElementName: "offsetslider" + onValueChanged: panel.offset = value + } + SliderHandle { + id: minimumLengthHandle + alignment: panel.alignment | Qt.AlignLeft + visible: panel.alignment != Qt.AlignRight + offset: panel.offset + graphicElementName: "minslider" + onValueChanged: panel.minimumLength = value + minimumValue: (panel.alignment == Qt.AlignCenter) ? ((dialogRoot.vertical) ? root.height/2 : root.width/2) : ((dialogRoot.vertical) ? -height/2 : -width/2); + } + SliderHandle { + id: maximumLengthHandle + alignment: panel.alignment | Qt.AlignLeft + visible: panel.alignment != Qt.AlignRight + offset: panel.offset + graphicElementName: "maxslider" + onValueChanged: panel.maximumLength = value + minimumValue: (panel.alignment == Qt.AlignCenter) ? ((dialogRoot.vertical) ? root.height/2 : root.width/2) : ((dialogRoot.vertical) ? -height/2 : -width/2); + } + SliderHandle { + id: leftMinimumLengthHandle + alignment: panel.alignment | Qt.AlignRight + visible: panel.alignment != Qt.AlignLeft + offset: panel.offset + graphicElementName: "maxslider" + onValueChanged: panel.minimumLength = value + maximumValue: (panel.alignment == Qt.AlignCenter) ? ((dialogRoot.vertical) ? root.height/2-height : root.width/2-width) : ((dialogRoot.vertical) ? root.height-height/2 : root.width-width/2); + } + SliderHandle { + id: leftMaximumLengthHandle + alignment: panel.alignment | Qt.AlignRight + visible: panel.alignment != Qt.AlignLeft + offset: panel.offset + graphicElementName: "minslider" + onValueChanged: panel.maximumLength = value + maximumValue: (panel.alignment == Qt.AlignCenter) ? ((dialogRoot.vertical) ? root.height/2-height : root.width/2-width) : ((dialogRoot.vertical) ? root.height-height/2 : root.width-width/2); + } + + states: [ + State { + name: "TopEdge" + PropertyChanges { + target: root + prefix: "north" + height: root.implicitHeight + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: undefined + left: root.parent.left + right: root.parent.right + } + } + AnchorChanges { + target: offsetHandle + anchors { + top: undefined + bottom: root.bottom + left: undefined + right: undefined + } + } + AnchorChanges { + target: minimumLengthHandle + anchors { + top: root.top + bottom: undefined + left: undefined + right: undefined + } + } + AnchorChanges { + target: maximumLengthHandle + anchors { + top: undefined + bottom: root.bottom + left: undefined + right: undefined + } + } + AnchorChanges { + target: leftMinimumLengthHandle + anchors { + top: root.top + bottom: undefined + left: undefined + right: undefined + } + } + AnchorChanges { + target: leftMaximumLengthHandle + anchors { + top: undefined + bottom: root.bottom + left: undefined + right: undefined + } + } + }, + State { + name: "BottomEdge" + PropertyChanges { + target: root + prefix: "south" + height: root.implicitHeight + } + AnchorChanges { + target: root + anchors { + top: undefined + bottom: root.parent.bottom + left: root.parent.left + right: root.parent.right + } + } + AnchorChanges { + target: offsetHandle + anchors { + top: root.top + bottom: undefined + left: undefined + right: undefined + } + } + AnchorChanges { + target: minimumLengthHandle + anchors { + top: undefined + bottom: root.bottom + left: undefined + right: undefined + } + } + AnchorChanges { + target: maximumLengthHandle + anchors { + top: root.top + bottom: undefined + left: undefined + right: undefined + } + } + AnchorChanges { + target: leftMinimumLengthHandle + anchors { + top: undefined + bottom: root.bottom + left: undefined + right: undefined + } + } + AnchorChanges { + target: leftMaximumLengthHandle + anchors { + top: root.top + bottom: undefined + left: undefined + right: undefined + } + } + }, + State { + name: "LeftEdge" + PropertyChanges { + target: root + prefix: "west" + width: root.implicitWidth + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: root.parent.bottom + left: root.parent.left + right: undefined + } + } + AnchorChanges { + target: offsetHandle + anchors { + top: undefined + bottom: undefined + left: undefined + right: root.right + } + } + AnchorChanges { + target: minimumLengthHandle + anchors { + top: undefined + bottom: undefined + left: root.left + right: undefined + } + } + AnchorChanges { + target: maximumLengthHandle + anchors { + top: undefined + bottom: undefined + left: undefined + right: root.right + } + } + AnchorChanges { + target: leftMinimumLengthHandle + anchors { + top: undefined + bottom: undefined + left: root.left + right: undefined + } + } + AnchorChanges { + target: leftMaximumLengthHandle + anchors { + top: undefined + bottom: undefined + left: undefined + right: root.right + } + } + }, + State { + name: "RightEdge" + PropertyChanges { + target: root + prefix: "east" + width: root.implicitWidth + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: root.parent.bottom + left: undefined + right: root.parent.right + } + } + AnchorChanges { + target: offsetHandle + anchors { + top: undefined + bottom: undefined + left: parent.left + right: undefined + } + } + AnchorChanges { + target: minimumLengthHandle + anchors { + top: undefined + bottom: undefined + left: undefined + right: parent.right + } + } + AnchorChanges { + target: maximumLengthHandle + anchors { + top: undefined + bottom: undefined + left: parent.left + right: undefined + } + } + AnchorChanges { + target: leftMinimumLengthHandle + anchors { + top: undefined + bottom: undefined + left: undefined + right: parent.right + } + } + AnchorChanges { + target: leftMaximumLengthHandle + anchors { + top: undefined + bottom: undefined + left: parent.left + right: undefined + } + } + } + ] +} diff --git a/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml b/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml new file mode 100644 index 0000000000..87b9c546d7 --- /dev/null +++ b/desktoppackage/contents/configuration/panelconfiguration/SizeHandle.qml @@ -0,0 +1,57 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + +PlasmaComponents.Button { + text: panel.location == PlasmaCore.Types.LeftEdge || panel.location == PlasmaCore.Types.RightEdge ? i18n("Width") : i18n("Height") + KQuickControlsAddons.MouseEventListener { + anchors.fill: parent + property int startMouseX + property int startMouseY + onPressed: { + startMouseX = mouse.x + startMouseY = mouse.y + } + onPositionChanged: { + switch (panel.location) { + case PlasmaCore.Types.TopEdge: + configDialog.y = mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y + panel.thickness = configDialog.y - panel.y + break; + case PlasmaCore.Types.LeftEdge: + configDialog.x = mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x + panel.thickness = configDialog.x - panel.x + break; + case PlasmaCore.Types.RightEdge: + configDialog.x = mouse.screenX - mapToItem(dialogRoot, startMouseX, 0).x + panel.thickness = (panel.x + panel.width) - (configDialog.x + configDialog.width) + break; + case PlasmaCore.Types.BottomEdge: + default: + configDialog.y = mouse.screenY - mapToItem(dialogRoot, 0, startMouseY).y + panel.thickness = (panel.y + panel.height) - (configDialog.y + configDialog.height) + } + } + } +} diff --git a/desktoppackage/contents/configuration/panelconfiguration/SliderHandle.qml b/desktoppackage/contents/configuration/panelconfiguration/SliderHandle.qml new file mode 100644 index 0000000000..5a5c350776 --- /dev/null +++ b/desktoppackage/contents/configuration/panelconfiguration/SliderHandle.qml @@ -0,0 +1,173 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 +import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons + + +PlasmaCore.SvgItem { + id: root + svg: containmentControlsSvg + state: parent.state + width: naturalSize.width + height: naturalSize.height + + //value expressed by this slider + property int value + //name of the graphics to load + property string graphicElementName + //where the point "0" is + property int offset: 0 + //handle type: behave in different ways based on the alignment + property int alignment: panel.alignment + + property int minimumValue: (dialogRoot.vertical) ? -root.height/2 : -root.width/2 + property int maximumValue: (dialogRoot.vertical) ? root.parent.height : root.parent.width + + function syncPos() { + if (dialogRoot.vertical) { + if (alignment == Qt.AlignRight) { + y = root.parent.height - (value + offset + root.height/2) + } else if (alignment == Qt.AlignLeft) { + y = value + offset - root.height/2 + } else { + if (root.alignment & Qt.AlignRight) { + y = root.parent.height/2 - value/2 - offset + root.height/2 + } else if (root.alignment & Qt.AlignLeft) { + y = root.parent.height/2 + value/2 + offset - root.height/2 + } else { + y = root.parent.height/2 + value + offset -root.height/2 + } + } + } else { + if (alignment == Qt.AlignRight) { + x = root.parent.width - (value + offset + root.width/2) + } else if (alignment == Qt.AlignLeft) { + x = value + offset - root.width/2 + } else { + if (root.alignment & Qt.AlignRight) { + x = root.parent.width/2 - value/2 + offset - root.width/2 + } else if (root.alignment & Qt.AlignLeft) { + x = root.parent.width/2 + value/2 + offset -root.width/2 + } else { + x = root.parent.width/2 + value + offset -root.width/2 + } + } + } + } + onValueChanged: syncPos() + onOffsetChanged: syncPos() + onAlignmentChanged: syncPos() + Connections { + target: root.parent + onWidthChanged: syncPos() + onHeightChanged: syncPos() + } + + MouseArea { + drag { + target: parent + axis: (dialogRoot.vertical) ? Drag.YAxis : Drag.XAxis + minimumX: root.minimumValue + minimumY: root.minimumValue + maximumX: root.maximumValue + maximumY: root.maximumValue + } + anchors.fill: parent + onPositionChanged: { + if (dialogRoot.vertical) { + if (root.alignment == Qt.AlignRight) { + root.value = root.parent.height - (parent.y + offset + root.height/2) + } else if (alignment == Qt.AlignLeft) { + root.value = parent.y - offset + root.height/2 + //Center + } else { + if (root.alignment & Qt.AlignRight) { + root.value = (root.parent.height/2 - parent.y + offset)*2 + root.height/2 + } else if (root.alignment & Qt.AlignLeft) { + root.value = (parent.y - offset - root.parent.height/2)*2 + root.height/2 + } else { + var value = parent.y - root.parent.height/2 - offset + root.height/2 + //Snap + if (Math.abs(value) < 5) { + root.value = 0 + } else { + root.value = value + } + } + } + } else { + if (root.alignment == Qt.AlignRight) { + root.value = root.parent.width - (parent.x + offset + root.width/2) + } else if (alignment == Qt.AlignLeft) { + root.value = parent.x - offset + root.width/2 + //Center + } else { + if (root.alignment & Qt.AlignRight) { + root.value = (root.parent.width/2 - parent.x + offset)*2 + root.width/2 + } else if (root.alignment & Qt.AlignLeft) { + root.value = (parent.x - offset - root.parent.width/2)*2 + root.width/2 + } else { + var value = parent.x - root.parent.width/2 - offset + root.width/2 + //Snap + if (Math.abs(value) < 5) { + root.value = 0 + } else { + root.value = value + } + } + } + } + } + } + + states: [ + State { + name: "TopEdge" + PropertyChanges { + target: root + elementId: "north-" + graphicElementName + } + }, + State { + name: "BottomEdge" + PropertyChanges { + target: root + elementId: "south-" + graphicElementName + } + }, + State { + name: "LeftEdge" + PropertyChanges { + target: root + elementId: "west-" + graphicElementName + } + }, + State { + name: "RightEdge" + PropertyChanges { + target: root + elementId: "east-" + graphicElementName + } + } + ] +} diff --git a/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml b/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml new file mode 100644 index 0000000000..59a88ead03 --- /dev/null +++ b/desktoppackage/contents/configuration/panelconfiguration/ToolBar.qml @@ -0,0 +1,365 @@ +/* + * Copyright 2013 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 + +Item { + id: root + state: parent.state + implicitWidth: units.gridUnit * 10 + implicitHeight: row.height + 20 + + GridLayout { + id: row + columns: dialogRoot.vertical ? 1 : 2 + rows: dialogRoot.vertical ? 2 : 1 + anchors.centerIn: parent + + rowSpacing: units.smallSpacing + columnSpacing: units.smallSpacing + + EdgeHandle {} + SizeHandle {} + } + + PlasmaComponents.Label { + id: placeHolder + visible: false + text: i18n("Add Widgets...") + i18n("Add spacer") + i18n("More Settings...") + } + + GridLayout { + id: buttonsLayout + rows: 1 + columns: 1 + flow: plasmoid.formFactor == PlasmaCore.Types.Horizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight + + anchors.margins: rowSpacing + + property bool showText: plasmoid.formFactor == PlasmaCore.Types.Vertical || (row.x + row.width < root.width - placeHolder.width - units.iconSizes.small*4 - units.largeSpacing*5) + + rowSpacing: units.smallSpacing + columnSpacing: units.smallSpacing + + PlasmaComponents.Button { + text: buttonsLayout.showText ? i18n("Add Widgets...") : "" + iconSource: "list-add" + Layout.preferredWidth: panel.formFactor == PlasmaCore.Types.Vertical ? Math.max(implicitWidth, parent.width) : implicitWidth + onClicked: { + configDialog.showAddWidgetDialog(); + } + } + + PlasmaComponents.Button { + iconSource: "distribute-horizontal-x" + text: buttonsLayout.showText ? i18n("Add spacer") : "" + Layout.preferredWidth: panel.formFactor == PlasmaCore.Types.Vertical ? Math.max(implicitWidth, parent.width) : implicitWidth + onClicked: { + configDialog.addPanelSpacer(); + } + } + + PlasmaComponents.Button { + id: settingsButton + iconSource: "configure" + text: buttonsLayout.showText ? i18n("More Settings...") : "" + Layout.preferredWidth: panel.formFactor == PlasmaCore.Types.Vertical ? Math.max(implicitWidth, parent.width) : implicitWidth + onClicked: { + contextMenu.visible = !contextMenu.visible; + } + } + + PlasmaComponents.ToolButton { + iconSource: "window-close" + onClicked: { + configDialog.close() + } + } + + PlasmaCore.Dialog { + id: contextMenu + visualParent: settingsButton + location: plasmoid.location + type: PlasmaCore.Dialog.PopupMenu + flags: Qt.Popup | Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus + mainItem: Column { + id: menuColumn + width: units.gridUnit * 5 + height: units.gridUnit * 10 + Layout.minimumWidth: menuColumn.implicitWidth + Layout.minimumHeight: menuColumn.implicitHeight + spacing: units.smallSpacing + PlasmaExtras.Heading { + level: 3 + text: i18n("Panel Alignment") + } + PlasmaComponents.ButtonColumn { + spacing: 0 + anchors { + left: parent.left + right: parent.right + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Left") + checkable: true + checked: panel.alignment == Qt.AlignLeft + onClicked: panel.alignment = Qt.AlignLeft + flat: false + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Center") + checkable: true + checked: panel.alignment == Qt.AlignCenter + onClicked: panel.alignment = Qt.AlignCenter + flat: false + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Right") + checkable: true + checked: panel.alignment == Qt.AlignRight + onClicked: panel.alignment = Qt.AlignRight + flat: false + } + } + + PlasmaExtras.Heading { + level: 3 + text: i18n("Visibility") + } + PlasmaComponents.ButtonColumn { + spacing: 0 + anchors { + left: parent.left + right: parent.right + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Always visible") + checkable: true + checked: configDialog.visibilityMode == 0 + onClicked: configDialog.visibilityMode = 0 + flat: false + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Auto Hide") + checkable: true + checked: configDialog.visibilityMode == 1 + onClicked: configDialog.visibilityMode = 1 + flat: false + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Windows can cover") + checkable: true + checked: configDialog.visibilityMode == 2 + onClicked: configDialog.visibilityMode = 2 + flat: false + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Windows go below") + checkable: true + checked: configDialog.visibilityMode == 3 + onClicked: configDialog.visibilityMode = 3 + flat: false + } + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Maximize Panel") + iconSource: panel.formFactor == PlasmaCore.Types.Vertical ? "zoom-fit-height" : "zoom-fit-width" + onClicked: panel.maximize(); + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Lock Widgets") + iconSource: "document-encrypt" + onClicked: { + plasmoid.action("lock widgets").trigger(); + configDialog.close(); + } + } + PlasmaComponents.ToolButton { + anchors { + left: parent.left + right: parent.right + } + text: i18n("Remove Panel") + iconSource: "window-close" + onClicked: { + contextMenu.visible = false; + plasmoid.action("remove").trigger(); + } + } + } + } + + } +//BEGIN States + states: [ + State { + name: "TopEdge" + PropertyChanges { + target: root + height: root.implicitHeight + } + AnchorChanges { + target: root + anchors { + top: undefined + bottom: root.parent.bottom + left: root.parent.left + right: root.parent.right + } + } + AnchorChanges { + target: buttonsLayout + anchors { + verticalCenter: root.verticalCenter + top: undefined + bottom: undefined + left: undefined + right: root.right + } + } + PropertyChanges { + target: buttonsLayout + width: buttonsLayout.implicitWidth + } + }, + State { + name: "BottomEdge" + PropertyChanges { + target: root + height: root.implicitHeight + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: undefined + left: root.parent.left + right: root.parent.right + } + } + AnchorChanges { + target: buttonsLayout + anchors { + verticalCenter: root.verticalCenter + top: undefined + bottom: undefined + left: undefined + right: root.right + } + } + PropertyChanges { + target: buttonsLayout + width: buttonsLayout.implicitWidth + } + }, + State { + name: "LeftEdge" + PropertyChanges { + target: root + width: root.implicitWidth + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: root.parent.bottom + left: undefined + right: root.parent.right + } + } + AnchorChanges { + target: buttonsLayout + anchors { + verticalCenter: undefined + top: undefined + bottom: root.bottom + left: root.left + right: root.right + } + } + }, + State { + name: "RightEdge" + PropertyChanges { + target: root + width: root.implicitWidth + } + AnchorChanges { + target: root + anchors { + top: root.parent.top + bottom: root.parent.bottom + left: root.parent.left + right: undefined + } + } + AnchorChanges { + target: buttonsLayout + anchors { + verticalCenter: undefined + top: undefined + bottom: root.bottom + left: root.left + right: root.right + } + } + } + ] +//END States +} diff --git a/desktoppackage/contents/defaults b/desktoppackage/contents/defaults new file mode 100644 index 0000000000..08f4288c4f --- /dev/null +++ b/desktoppackage/contents/defaults @@ -0,0 +1,16 @@ +[Desktop] +Containment=org.kde.desktopcontainment +ToolBox=org.kde.desktoptoolbox +RuntimePlatform= + +[Desktop][ContainmentActions] +RightButton;NoModifier=org.kde.contextmenu +MidButton;NoModifier=org.kde.paste +wheel:Vertical;NoModifier=org.kde.switchdesktop + +[Panel] +Containment=org.kde.panel +ToolBox=org.kde.paneltoolbox +[Panel][ContainmentActions] +RightButton;NoModifier=org.kde.contextmenu +MidButton;NoModifier=org.kde.paste diff --git a/desktoppackage/contents/explorer/AppletDelegate.qml b/desktoppackage/contents/explorer/AppletDelegate.qml new file mode 100644 index 0000000000..872ca38127 --- /dev/null +++ b/desktoppackage/contents/explorer/AppletDelegate.qml @@ -0,0 +1,116 @@ +/* + * Copyright 2011 Marco Martin + * + * This program 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 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 Library 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. + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 + +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.draganddrop 2.0 +import org.kde.kquickcontrolsaddons 2.0 + +PlasmaCore.FrameSvgItem { + id: background + width: list.delegateWidth + height: list.delegateHeight + + property variant icon: decoration + property string title: name + property string description: model.description + property string author: model.author + property string email: model.email + property string license: model.license + property string pluginName: model.pluginName + property bool local: model.local + + imagePath: "widgets/viewitem" + prefix: mouseArea.containsMouse ? "hover" : "normal" + + DragArea { + anchors.fill: parent + supportedActions: Qt.MoveAction | Qt.LinkAction + //onDragStarted: tooltipDialog.visible = false + delegateImage: decoration + mimeData { + source: parent + } + Component.onCompleted: mimeData.setData("text/x-plasmoidservicename", pluginName) + + QIconItem { + id: iconWidget + anchors.verticalCenter: parent.verticalCenter + x: y + width: units.iconSizes.huge + height: width + icon: background.icon + } + ColumnLayout { + anchors { + top: parent.top + bottom: parent.bottom + left: iconWidget.right + right: parent.right + + topMargin: background.margins.top + bottomMargin: background.margins.bottom + leftMargin: background.margins.left + rightMargin: background.margins.right + } + spacing: 4 + PlasmaExtras.Heading { + id: titleText + level: 4 + text: name + elide: Text.ElideRight + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + PlasmaComponents.Label { + text: description + font.pointSize: theme.smallestFont.pointSize + wrapMode: Text.WordWrap + elide: Text.ElideRight + maximumLineCount: 3 + Layout.fillWidth: true + Layout.fillHeight: true + } + } + QIconItem { + icon: running ? "dialog-ok-apply" : undefined + visible: running + width: units.iconSizes.small + height: width + anchors { + top: iconWidget.top + left: iconWidget.left + topMargin: units.smallSpacing + leftMargin: units.smallSpacing + } + } + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onDoubleClicked: widgetExplorer.addApplet(pluginName) + //onEntered: tooltipDialog.appletDelegate = background + //onExited: tooltipDialog.appletDelegate = null + } + } +} diff --git a/desktoppackage/contents/explorer/Tooltip.qml b/desktoppackage/contents/explorer/Tooltip.qml new file mode 100644 index 0000000000..0eafa19690 --- /dev/null +++ b/desktoppackage/contents/explorer/Tooltip.qml @@ -0,0 +1,148 @@ +/* + * Copyright 2011 Marco Martin + * + * This program 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 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 Library 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. + */ + +import QtQuick 2.1 +import QtQuick.Layouts 1.0 as Layouts +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras + +MouseArea { + id: main + + hoverEnabled: true + onEntered: toolTipHideTimer.running = false + onExited: toolTipHideTimer.running = true + + width: theme.mSize(theme.defaultFont).width * 35 + height: theme.mSize(theme.defaultFont).height * 16 + + property variant icon + property string title + property string description + property string author + property string email + property string license + property string pluginName + property bool local + + onClicked: tooltipDialog.visible = false + Connections { + target: tooltipDialog + onAppletDelegateChanged: { + if (!tooltipDialog.appletDelegate) { + return + } + icon = tooltipDialog.appletDelegate.icon + title = tooltipDialog.appletDelegate.title + description = tooltipDialog.appletDelegate.description + author = tooltipDialog.appletDelegate.author + email = tooltipDialog.appletDelegate.email + license = tooltipDialog.appletDelegate.license + pluginName = tooltipDialog.appletDelegate.pluginName + local = tooltipDialog.appletDelegate.local + } + } + PlasmaCore.IconItem { + id: tooltipIconWidget + anchors { + left: parent.left + top: parent.top + margins: 8 + } + width: units.iconSizes.huge + height: width + source: main.icon + } + Column { + id: nameColumn + spacing: 8 + anchors { + left: tooltipIconWidget.right + margins: 8 + top: parent.top + right: parent.right + } + + PlasmaExtras.Heading { + text: title + level: 2 + anchors.left: parent.left + anchors.right: parent.right + height: paintedHeight + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: description + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.Wrap + } + } + Layouts.GridLayout { + columns: 2 + anchors { + top: (nameColumn.height > tooltipIconWidget.height) ? nameColumn.bottom : tooltipIconWidget.bottom + topMargin: 16 + horizontalCenter: parent.horizontalCenter + } + PlasmaComponents.Label { + text: i18n("License:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + PlasmaComponents.Label { + id: licenseText + text: license + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: i18n("Author:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + PlasmaComponents.Label { + text: author + wrapMode: Text.Wrap + } + PlasmaComponents.Label { + text: i18n("Email:") + Layouts.Layout.alignment: Qt.AlignVCenter|Qt.AlignRight + } + PlasmaComponents.Label { + text: email + } + } + + PlasmaComponents.Button { + id: uninstallButton + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + } + opacity: local ? 1 : 0 + Behavior on opacity { + NumberAnimation { duration: units.longDuration } + } + iconSource: "application-exit" + text: i18n("Uninstall") + onClicked: { + widgetExplorer.uninstall(pluginName) + tooltipDialog.visible = false + } + } +} diff --git a/desktoppackage/contents/explorer/WidgetExplorer.qml b/desktoppackage/contents/explorer/WidgetExplorer.qml new file mode 100644 index 0000000000..a95214d398 --- /dev/null +++ b/desktoppackage/contents/explorer/WidgetExplorer.qml @@ -0,0 +1,287 @@ +/* + * Copyright 2011 Marco Martin + * + * This program 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 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 Library 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. + */ + +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.kquickcontrolsaddons 2.0 +import QtQuick.Window 2.1 +import org.kde.plasma.private.shell 2.0 + +Item { + id: main + + width: 240 + height: 800//Screen.height + //this is used to perfectly align the filter field and delegates + property int cellWidth: theme.mSize(theme.defaultFont).width * 10 + + property int minimumWidth: theme.mSize(theme.defaultFont).width * 12 + property int minimumHeight: 800//topBar.height + list.delegateHeight + (widgetExplorer.orientation == Qt.Horizontal ? scrollBar.height : 0) + 4 + + property alias containment: widgetExplorer.containment + + property Item getWidgetsButton + property Item categoryButton + + signal closed() + + WidgetExplorer { + id: widgetExplorer + //view: desktop + onShouldClose: main.closed(); + } + + PlasmaComponents.ModelContextMenu { + id: categoriesDialog + visualParent: main.categoryButton + model: widgetExplorer.filterModel + + onClicked: { + list.contentX = 0 + list.contentY = 0 + main.categoryButton.text = model.display + widgetExplorer.widgetsModel.filterQuery = model.filterData + widgetExplorer.widgetsModel.filterType = model.filterType + } + } + + PlasmaComponents.ModelContextMenu { + id: getWidgetsDialog + visualParent: main.getWidgetsButton + model: widgetExplorer.widgetsMenuActions + onClicked: model.trigger() + } + /* + PlasmaCore.Dialog { + id: tooltipDialog + property Item appletDelegate + location: PlasmaCore.Types.RightEdge //actually we want this to be the opposite location of the explorer itself + + type: PlasmaCore.Dialog.Tooltip + flags:Qt.Window|Qt.WindowStaysOnTopHint|Qt.X11BypassWindowManagerHint + + onAppletDelegateChanged: { + if (!appletDelegate) { + toolTipHideTimer.restart() + toolTipShowTimer.running = false + } else if (tooltipDialog.visible) { + tooltipDialog.visualParent = appletDelegate + } else { + tooltipDialog.visualParent = appletDelegate + toolTipShowTimer.restart() + toolTipHideTimer.running = false + } + } + mainItem: Tooltip { id: tooltipWidget } + + Behavior on y { + NumberAnimation { duration: units.longDuration } + } + } + Timer { + id: toolTipShowTimer + interval: 500 + repeat: false + onTriggered: { + tooltipDialog.visible = true + } + } + Timer { + id: toolTipHideTimer + interval: 1000 + repeat: false + onTriggered: tooltipDialog.visible = false + } + */ + + Loader { + id: topBar + property Item categoryButton + + sourceComponent: verticalTopBarComponent + anchors { + top: parent.top + left: parent.left + right: parent.right + topMargin: 0 + leftMargin: units.smallSpacing + rightMargin: units.smallSpacing + } + } + Component { + id: verticalTopBarComponent + + Column { + anchors.top: parent.top + anchors.left:parent.left + anchors.right: parent.right + spacing: 4 + + PlasmaComponents.ToolButton { + anchors.right: parent.right + iconSource: "window-close" + onClicked: main.closed() + } + PlasmaComponents.TextField { + anchors { + left: parent.left + right: parent.right + } + clearButtonShown: true + placeholderText: i18n("Enter search term...") + onTextChanged: { + list.contentX = 0 + list.contentY = 0 + widgetExplorer.widgetsModel.searchTerm = text + } + Component.onCompleted: forceActiveFocus() + } + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + id: categoryButton + text: i18n("Categories") + onClicked: categoriesDialog.open(0, categoryButton.height) + } + Component.onCompleted: { + main.categoryButton = categoryButton + } + } + } + + PlasmaExtras.ScrollArea { + anchors { + top: topBar.bottom + left: parent.left + right: parent.right + bottom: bottomBar.top + topMargin: units.smallSpacing + leftMargin: units.smallSpacing + bottomMargin: units.smallSpacing + } + flickableItem: ListView { + id: list + + property int delegateWidth: list.width + property int delegateHeight: theme.defaultFont.pixelSize * 7 - 4 + + snapMode: ListView.SnapToItem + model: widgetExplorer.widgetsModel + + clip: true //TODO work out why this is this needed + + delegate: AppletDelegate {} + + //slide in to view from the left + add: Transition { + NumberAnimation { + properties: "x" + from: -list.width + to: 0 + duration: units.shortDuration * 3 + + } + } + + //slide out of view to the right + remove: Transition { + NumberAnimation { + properties: "x" + to: list.width + duration: units.shortDuration * 3 + } + } + + //if we are adding other items into the view use the same animation as normal adding + //this makes everything slide in together + //if we make it move everything ends up weird + addDisplaced: list.add + + //moved due to filtering + displaced: Transition { + NumberAnimation { + properties: "y" + duration: units.shortDuration * 3 + } + } + } + } + + Loader { + id: bottomBar + + sourceComponent: verticalBottomBarComponent + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + leftMargin: units.smallSpacing + rightMargin: units.smallSpacing + bottomMargin: units.smallSpacing + } + } + + Component { + id: verticalBottomBarComponent + Column { + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + + spacing: units.smallSpacing + + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + id: getWidgetsButton + iconSource: "get-hot-new-stuff" + text: i18n("Get new widgets") + onClicked: getWidgetsDialog.open() + } + + Repeater { + model: widgetExplorer.extraActions.length + PlasmaComponents.Button { + anchors { + left: parent.left + right: parent.right + } + iconSource: widgetExplorer.extraActions[modelData].icon + text: widgetExplorer.extraActions[modelData].text + onClicked: { + widgetExplorer.extraActions[modelData].trigger() + } + } + } + + Component.onCompleted: { + main.getWidgetsButton = getWidgetsButton + } + } + } +} + diff --git a/desktoppackage/contents/layout.js b/desktoppackage/contents/layout.js new file mode 100644 index 0000000000..303e7af164 --- /dev/null +++ b/desktoppackage/contents/layout.js @@ -0,0 +1,18 @@ + +var panel = new Panel +panel.screen = 0 +panel.location = 'bottom' +panel.addWidget("org.kde.plasma.kickoff") +panel.addWidget("org.kde.plasma.pager") +panel.addWidget("org.kde.plasma.taskmanager") +panel.addWidget("org.kde.plasma.systemtray") +panel.addWidget("org.kde.plasma.digitalclock") + +for (var i = 0; i < screenCount; ++i) { + var desktop = new Activity + desktop.name = i18n("Desktop") + desktop.screen = i + desktop.wallpaperPlugin = 'org.kde.image' + + //var clock = desktop.addWidget("org.kde.analogclock"); +} diff --git a/desktoppackage/contents/loader.qml b/desktoppackage/contents/loader.qml new file mode 100644 index 0000000000..316a736f44 --- /dev/null +++ b/desktoppackage/contents/loader.qml @@ -0,0 +1,51 @@ +/* vim:set foldmethod=marker: + * + * Copyright (C) 2013 Ivan Cukic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * or (at your option) any later version, as published by the Free + * Software Foundation + * + * 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. + */ + +import QtQuick 2 +import org.kde.solid 1.0 as Solid +import org.kde.plasma.platformcomponents 2.0 as Platform + +Item { + id: main + + property string shell : "org.kde.desktop" + property bool willing : true + property int priority : 1 + + // This is not needed, but allows the + // handler to know whether its shell is loaded + property bool loaded : false + + default property var children + /* This seems to crash not being able to address Solid.Device, which seems to be + a problem with latest Qt 5.3. Pleas re-enable only after consultation with + plasma-devel@kde.org */ + /* + Solid.Devices { + id: keyboards + query: "IS Keyboard" + } + */ + Platform.Application { + application: "krunner" + running: main.loaded + } +} + diff --git a/desktoppackage/contents/views/Desktop.qml b/desktoppackage/contents/views/Desktop.qml new file mode 100644 index 0000000000..5c7087993e --- /dev/null +++ b/desktoppackage/contents/views/Desktop.qml @@ -0,0 +1,194 @@ +/* + * Copyright 2012 Marco Martin + * Copyright 2014 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents +import "../activitymanager" +import "../explorer" + + +Rectangle { + id: root + color: Qt.rgba(0, 0, 0, 0.2) + width: 1024 + height: 768 + + property Item containment + + function toggleWidgetExplorer(containment) { + console.log("Widget Explorer toggled"); + + if (sidePanelStack.state == "widgetExplorer") { + sidePanelStack.state = "closed"; + } else { + sidePanelStack.setSource(Qt.resolvedUrl("../explorer/WidgetExplorer.qml"), {"containment": containment}) + sidePanelStack.state = "widgetExplorer"; + } + } + + function toggleActivityManager() { + console.log("Activity manger toggled"); + if (sidePanelStack.state == "activityManager") { + sidePanelStack.state = "closed"; + } else { + sidePanelStack.setSource(Qt.resolvedUrl("../activitymanager/ActivityManager.qml")) + sidePanelStack.state = "activityManager"; + } + } + + PlasmaCore.Dialog { + id: sidePanel + location: PlasmaCore.Types.LeftEdge + type: PlasmaCore.Dialog.Dock + flags: Qt.Window|Qt.WindowStaysOnTopHint|Qt.X11BypassWindowManagerHint + + hideOnWindowDeactivate: true + + onVisibleChanged: { + if (!visible) { + sidePanelStack.state = "closed"; + } else { + sidePanel.requestActivate(); + // get the current available screen geometry and subtract the dialog's frame margins + sidePanelStack.height = containment ? containment.availableScreenRect(containment.screen).height - sidePanel.margins.top - sidePanel.margins.bottom : 1000; + } + } + + mainItem: Loader { + id: sidePanelStack + asynchronous: true + height: 1000 //start with some arbitrary height, will be changed from onVisibleChanged + width: item ? item.width: 0 + onLoaded: { + if (sidePanelStack.item) { + item.closed.connect(function(){sidePanelStack.state = "closed";}); + + if (sidePanelStack.state == "activityManager") { + sidePanel.hideOnWindowDeactivate = Qt.binding(function() { return !sidePanelStack.item.showingDialog; }) + } else { + sidePanel.hideOnWindowDeactivate = true; + } + } + sidePanel.visible = true; + } + onStateChanged: { + if (sidePanelStack.state == "closed") { + sidePanelStack.source = ""; //unload all elements + sidePanel.visible = false; + } + } + } + } + + onContainmentChanged: { + print("New Containment: " + containment); + print("Old Containment: " + internal.oldContainment); + //containment.parent = root; + + internal.newContainment = containment; + + if (containment != null) { + containment.visible = true; + } + if (containment != null) { + if (internal.oldContainment != null && internal.oldContainment != containment) { + if (internal.newContainment != null) { + switchAnim.running = true; + } + } else { + containment.anchors.left = root.left; + containment.anchors.top = root.top; + containment.anchors.right = root.right; + containment.anchors.bottom = root.bottom; + internal.oldContainment = containment; + } + } + } + + //some properties that shouldn't be accessible from elsewhere + QtObject { + id: internal; + + property Item oldContainment: null; + property Item newContainment: null; + } + + SequentialAnimation { + id: switchAnim + ScriptAction { + script: { + if (containment) { + containment.anchors.left = undefined; + containment.anchors.top = undefined; + containment.anchors.right = undefined; + containment.anchors.bottom = undefined; + } + internal.oldContainment.anchors.left = undefined; + internal.oldContainment.anchors.top = undefined; + internal.oldContainment.anchors.right = undefined; + internal.oldContainment.anchors.bottom = undefined; + + if (containment) { + internal.oldContainment.z = 0; + internal.oldContainment.x = 0; + containment.z = 1; + containment.x = root.width; + } + } + } + ParallelAnimation { + NumberAnimation { + target: internal.oldContainment + properties: "x" + to: internal.newContainment != null ? -root.width : 0 + duration: 400 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: internal.newContainment + properties: "x" + to: 0 + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + ScriptAction { + script: { + if (containment) { + containment.anchors.left = root.left; + containment.anchors.top = root.top; + containment.anchors.right = root.right; + containment.anchors.bottom = root.bottom; + internal.oldContainment.visible = false; + internal.oldContainment = containment; + } + } + } + } + + + Component.onCompleted: { + //configure the view behavior + desktop.stayBehind = true; + desktop.fillScreen = true; + print("View org.kde.desktop QML loaded") + } +} diff --git a/desktoppackage/contents/views/Panel.qml b/desktoppackage/contents/views/Panel.qml new file mode 100644 index 0000000000..5ed55e54ca --- /dev/null +++ b/desktoppackage/contents/views/Panel.qml @@ -0,0 +1,181 @@ +/* + * Copyright 2012 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 2.010-1301, USA. + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 + +import org.kde.plasma.core 2.0 as PlasmaCore + + +PlasmaCore.FrameSvgItem { + id: root + width: 640 + height: 32 + imagePath: "widgets/panel-background" + visible: false //adjust borders is run during setup. We want to avoid painting till completed + + property Item containment + + function adjustBorders() { + //print("PANEL ADJUST BORDERS"); + var borders = PlasmaCore.FrameSvg.AllBorders; + if (!containment) { + // Containment seems to never be set + // (or not reachable from here at least) + // FIXME: investigate why containment is null + print("FIXME Panel borders hardcoded in Panel.qml"); + borders = borders & ~PlasmaCore.FrameSvg.BottomBorder; + borders = borders & ~PlasmaCore.FrameSvg.LeftBorder; + borders = borders & ~PlasmaCore.FrameSvg.RightBorder; + root.enabledBorders = borders; + return; + } + + switch (containment.location) { + case PlasmaCore.Types.TopEdge: + borders = borders & ~PlasmaCore.FrameSvg.TopBorder; + break; + case PlasmaCore.Types.LeftEdge: + borders = borders & ~PlasmaCore.FrameSvg.LeftBorder; + break; + case PlasmaCore.Types.RightEdge: + borders = borders & ~PlasmaCore.FrameSvg.RightBorder; + break; + case PlasmaCore.Types.BottomEdge: + default: + print("PANEL disable bottom border"); + borders = borders & ~PlasmaCore.FrameSvg.BottomBorder; + break; + } + + if (panel.x <= panel.screen.geometry.x) { + borders = borders & ~PlasmaCore.FrameSvg.LeftBorder; + } + if (panel.x + panel.width >= panel.screen.geometry.x + panel.screen.geometry.width) { + borders = borders & ~PlasmaCore.FrameSvg.RightBorder; + } + if (panel.y <= panel.screen.geometry.y) { + borders = borders & ~PlasmaCore.FrameSvg.TopBorder; + } + if (panel.y + panel.height >= panel.screen.geometry.y + panel.screen.geometry.height) { + borders = borders & ~PlasmaCore.FrameSvg.BottomBorder; + } + + root.enabledBorders = borders; + + containmentParent.anchors.topMargin = Math.min(root.margins.top, Math.max(1, root.height - units.iconSizes.smallMedium)); + + containmentParent.anchors.bottomMargin = Math.min(root.margins.bottom, Math.max(1, root.height - units.iconSizes.smallMedium)); + + //Base the left/right margins on height as well, to have a good radial simmetry + containmentParent.anchors.leftMargin = Math.min(root.margins.left, Math.max(1, root.height - units.iconSizes.smallMedium)); + + containmentParent.anchors.leftMargin = Math.min(root.margins.left, Math.max(1, root.height - units.iconSizes.smallMedium)); + } + + onContainmentChanged: { + print("New panel Containment: " + containment); + containment.parent = containmentParent; + containment.visible = true; + containment.anchors.fill = containmentParent; + + containment.locationChanged.connect(adjustBorders); + if (containment.Layout) { + containment.Layout.minimumWidthChanged.connect(minimumWidthChanged); + containment.Layout.maximumWidthChanged.connect(maximumWidthChanged); + containment.Layout.preferredWidthChanged.connect(preferredWidthChanged); + + containment.Layout.minimumHeightChanged.connect(minimumHeightChanged); + containment.Layout.maximumHeightChanged.connect(maximumHeightChanged); + containment.Layout.preferredHeightChanged.connect(preferredHeightChanged); + } + adjustBorders(); + } + + function minimumWidthChanged() { + if (containment.formFactor === PlasmaCore.Types.Horizontal) { + panel.width = Math.max(panel.width, containment.Layout.minimumWidth); + } + } + function maximumWidthChanged() { + if (containment.formFactor === PlasmaCore.Types.Horizontal) { + panel.width = Math.min(panel.width, containment.Layout.maximumWidth); + } + } + function preferredWidthChanged() { + if (containment.formFactor === PlasmaCore.Types.Horizontal) { + panel.width = Math.min(panel.maximumLength, Math.max(containment.Layout.preferredWidth, panel.minimumLength)); + } + } + + function minimumHeightChanged() { + if (containment.formFactor === PlasmaCore.Types.Vertical) { + panel.height = Math.max(panel.height, containment.Layout.minimumWidth); + } + } + function maximumHeightChanged() { + if (containment.formFactor === PlasmaCore.Types.Vertical) { + panel.height = Math.min(panel.height, containment.Layout.maximumWidth); + } + } + function preferredHeightChanged() { + if (containment.formFactor === PlasmaCore.Types.Vertical) { + panel.height = Math.min(panel.maximumLength, Math.max(containment.Layout.preferredHeight, panel.minimumLength)); + } + } + + Item { + id: containmentParent + anchors { + fill: parent + leftMargin: root.margins.left + topMargin: root.margins.top + rightMargin: root.margins.right + bottomMargin: root.margins.bottom + } + } + + Connections { + target: panel + onXChanged: { + adjustBorders(); + } + onYChanged: { + adjustBorders(); + } + onWidthChanged: { + adjustBorders(); + } + onHeightChanged: { + adjustBorders(); + } + } + + Connections { + target: panel.screen + onGeometryChanged: { + adjustBorders(); + } + } + + Component.onCompleted: { + print("PanelView QML loaded") + adjustBorders(); + visible = true + } +} diff --git a/desktoppackage/metadata.desktop b/desktoppackage/metadata.desktop new file mode 100644 index 0000000000..8d6468dbe4 --- /dev/null +++ b/desktoppackage/metadata.desktop @@ -0,0 +1,131 @@ +[Desktop Entry] +Comment=Desktop view furniture +Comment[ca]=Accessori de vista d'escriptori +Comment[ca@valencia]=Accessori de vista d'escriptori +Comment[da]=Møbler til skrivebordsvisning +Comment[de]=Einrichtung der Ansicht einer Arbeitsfläche +Comment[el]=Παρουσίαση της επιφάνειας εργασίας +Comment[es]=Accesorio de vista del escritorio +Comment[fi]=Työpöydän sisustus +Comment[fr]=Aménagement du bureau +Comment[gl]=Contidos da vista do escritorio +Comment[hu]=Munkaasztal nézet bútor +Comment[ia]=Vista de accessorio de Scriptorio +Comment[kk]=Үстел көрініс әбзелдері +Comment[ko]=데스크톱 보기 가구 +Comment[nb]=Skrivebord, vis møbler +Comment[nds]=Möbelmang för Schriefdisch-Ansicht +Comment[nl]=Meubilair voor weergave op het bureaublad +Comment[pa]=ਡੈਸਕਟਾਪ ਵੇਖਣ ਫਰਨੀਚਰ +Comment[pl]=Widok umeblowania pulpitu +Comment[pt]=Disposição do ecrã +Comment[pt_BR]=Acessório de visualização da área de trabalho +Comment[sk]=Zobrazenie plochy nábytok +Comment[sl]=Delovna površina prikaza namizja +Comment[sr]=Намештај приказа површи +Comment[sr@ijekavian]=Намештај приказа површи +Comment[sr@ijekavianlatin]=Nameštaj prikaza površi +Comment[sr@latin]=Nameštaj prikaza površi +Comment[sv]=Visa skrivbordsmöbler +Comment[tr]=Masaüstü mobilya görünümü +Comment[uk]=Компоненти для перегляду стільниці +Comment[x-test]=xxDesktop view furniturexx +Comment[zh_TW]=桌面檢視設備 +Encoding=UTF-8 +Keywords= +Name=Desktop +Name[af]=Werkskerm +Name[ar]=سطح المكتب +Name[ast]=Escritoriu +Name[be]=Працоўны стол +Name[be@latin]=Rabočy stoł +Name[bg]=Работен плот +Name[bn]=ডেস্কটপ +Name[bn_IN]=ডেস্কটপ +Name[br]=Gorretaol +Name[ca]=Escriptori +Name[ca@valencia]=Escriptori +Name[cs]=Pracovní plocha +Name[csb]=Pùlt +Name[cy]=Penbwrdd +Name[da]=Skrivebord +Name[de]=Arbeitsfläche +Name[el]=Επιφάνεια εργασίας +Name[en_GB]=Desktop +Name[eo]=Labortablo +Name[es]=Escritorio +Name[et]=Töölaud +Name[eu]=Mahaigaina +Name[fa]=رومیزی +Name[fi]=Työpöytä +Name[fr]=Bureau +Name[fy]=Buroblêd +Name[ga]=Deasc +Name[gl]=Escritorio +Name[gu]=ડેસ્કટોપ +Name[he]=שולחן עבודה +Name[hi]=डेस्कटॉप +Name[hne]=डेस्कटाप +Name[hsb]=Dźěłowy powjerch +Name[hu]=Munkaasztal +Name[ia]=Scriptorio +Name[id]=Desktop +Name[it]=Desktop +Name[ka]=სამუშაო დაფა +Name[kk]=Жұмыс үстелі +Name[kn]=ಗಣಕತೆರೆ +Name[ko]=데스크톱 +Name[ku]=Sermasê +Name[lt]=Darbastalis +Name[mai]=डेस्कटाप +Name[mk]=Работна површина +Name[ml]=പണിയിടം +Name[mr]=डेस्कटॉप +Name[ms]=Ruang Kerja +Name[nb]=Skrivebord +Name[nds]=Schriefdisch +Name[ne]=डेस्कटप +Name[nl]=Bureaublad +Name[nn]=Skrivebord +Name[oc]=Burèu +Name[or]=ଡ଼େସ୍କଟପ +Name[pa]=ਡੈਸਕਟਾਪ +Name[pl]=Pulpit +Name[pt]=Ambiente de Trabalho +Name[pt_BR]=Área de trabalho +Name[ro]=Birou +Name[se]=Čállinbeavdi +Name[si]=වැඩතලය +Name[sk]=Plocha +Name[sl]=Namizje +Name[sr]=Површ +Name[sr@ijekavian]=Површ +Name[sr@ijekavianlatin]=Površ +Name[sr@latin]=Površ +Name[sv]=Skrivbord +Name[ta]=பணிமேசை +Name[te]=రంగస్ఠలం +Name[tg]=Мизи корӣ +Name[th]=พื้นที่ทำงาน +Name[tr]=Masaüstü +Name[uk]=Стільниця +Name[uz]=Ish stoli +Name[uz@cyrillic]=Иш столи +Name[vi]=Màn hình nền +Name[wa]=Sicribanne +Name[xh]=Desktop +Name[x-test]=xxDesktopxx +Name[zh_CN]=桌面 +Name[zh_TW]=桌面 +Type=Service + +X-KDE-ServiceTypes=Plasma/Shell +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Marco Martin +X-KDE-PluginInfo-Category= +X-KDE-PluginInfo-Email=mart@kde.org +X-KDE-PluginInfo-License=GPLv2+ +X-KDE-PluginInfo-Name=org.kde.desktop +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-Plasma-MainScript=layout.js diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000000..60a02b6f63 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(kcontrol) +add_subdirectory(kfontview) +add_subdirectory(plasma-desktop) diff --git a/doc/kcontrol/CMakeLists.txt b/doc/kcontrol/CMakeLists.txt new file mode 100644 index 0000000000..20c3b5bba9 --- /dev/null +++ b/doc/kcontrol/CMakeLists.txt @@ -0,0 +1,24 @@ +add_subdirectory(clock) +add_subdirectory(colors) +add_subdirectory(desktopthemedetails) +add_subdirectory(joystick) +add_subdirectory(kcmaccess) +add_subdirectory(kcmstyle) +add_subdirectory(solid-actions) +add_subdirectory(solid-hardware) +add_subdirectory(splashscreen) +add_subdirectory(powerdevil) + +if ( Q_WS_X11 ) +add_subdirectory(autostart) +add_subdirectory(bell) +add_subdirectory(cursortheme) +add_subdirectory(fonts) +add_subdirectory(fontinst) +add_subdirectory(keys) +add_subdirectory(keyboard) +add_subdirectory(mouse) +add_subdirectory(paths) +add_subdirectory(kcmsmserver) +add_subdirectory(khotkeys) +endif () diff --git a/doc/kcontrol/autostart/CMakeLists.txt b/doc/kcontrol/autostart/CMakeLists.txt new file mode 100644 index 0000000000..68faa5f00a --- /dev/null +++ b/doc/kcontrol/autostart/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/autostart) diff --git a/doc/kcontrol/autostart/index.docbook b/doc/kcontrol/autostart/index.docbook new file mode 100644 index 0000000000..c16f8a3d7c --- /dev/null +++ b/doc/kcontrol/autostart/index.docbook @@ -0,0 +1,183 @@ + + + +]> +
    + +Autostart + +&Anne-Marie.Mahfouf; + + + +2013-12-05 +&kde; 4.12 + + +KDE +System Settings +autostart +desktop file +script file + + + + +Autostart Manager + +This module is a configuration tool for managing what programs start up with your personal &kde;. It allows you to add programs or scripts so they automatically start during the startup of your &kde; session and to manage them. + +Please note that in this module all changes are immediately applied. + +The program scans ~/.config/autostart/, your KDE Autostart folder ($KDEHOME/Autostart as default), $KDEHOME/env and $KDEHOME/shutdown folders to check what programs and scripts are already there and displays them. It allows you to manage them easily. + + +Note that you can change the location of your Autostart +folder in Account Details Paths +in the Common Appearance and Behaviour category of the &systemsettings; and set a different folder +than $KDEHOME/Autostart. + + +Files display +The main part of the module displays the programs that are loaded when &kde; starts and scripts that are run when &kde; starts, shutdowns or before &kde; starts. + + +Name + + +You cannot amend this column. It states the name of the program or script you want to start with &kde;. The name is extracted from the Desktop file from the Name key for a program and is the filename for a script. + + + + +Command + + +This column lists the commands that are run to start the program. Commands can be modified through the Properties button or by double clicking the program/script row. The command is extracted from the Desktop file from the Exec key. + + +For a script the command is the path to the script. + + + + +Status + + +This setting is only available for programs through Desktop files. You can keep a program in the Autostart folder but disable it from being run at &kde; start. Setting the program to Disabled will not run it on start. + + +Setting a program to Disabled sets the Desktop file Hidden property to true in the Autostart folder. + + + + +Run On + + +Programs (Desktop files) can only be run on startup. Scripts can be run on Startup, Shutdown or Pre-KDE Startup. This column allows you to change when your script is run. Startup is when &kde; starts, shutdown is when you log out of &kde; and pre-KDE startup is before &kde; starts. + + +Scripts and desktop files set to run on Startup are copied or symlinked in $KDEHOME/Autostart and will be run during &kde; startup. + + +Scripts set on to be ran on Shutdown are copied or symlinked in the $KDEHOME/shutdown directory and will be automatically run during &kde; shutdown after the user has logged out. + + +Scripts set to run at Pre-&kde; Startup are copied or symlinked in $KDEHOME/env and are sourced during &kde; startup (the startkde script will look for scripts here). + + +Only scripts with the sh extension can be read by &kde; for Pre-&kde; startup and Shutdown modes. + + + + + + + +Actions + +On the right you have some buttons to change the way Autostart is configure. You can add programs or scripts, remove them or change their properties. + + + +Add Program + + +Clicking this button displays the standard &kde; Choose Application dialog and allows you to choose which program you want to start. After choosing the program, clicking OK brings you the properties for this program. + + +This will copy the program Desktop file in your Autostart folder. + + + + +Add Script + + +This button opens a dialog which asks you for the location of the script you want to add. If you keep Create as symlink checked (default) then the script will be added as a symlink. If you uncheck this option then the script will be copied in the corresponding local folder. + + + +Remove + + +Remove will immediately remove the Desktop file for the program or the script or symbolic link in the Autostart folder. + + + +Properties + + +This button (only enabled for programs &ie; Desktop files) allows you to change the properties of the program or script. You have general properties, permissions properties, a preview when applicable and properties related to the application for programs. + + + +Advanced + + +This button only applies to programs (&ie; Desktop files). A dialog asks you if you only want the program to autostart only in &kde; (and not in other desktop environments you might run). By default, the program will autostart in all desktop environments you might run. Checking Autostart only in KDE will autostart the program only if you start the &kde; desktop environment. + + +This sets the value KDE to the OnlyShowIn key of the program Desktop file. + + + + + + +
    + + + diff --git a/doc/kcontrol/bell/CMakeLists.txt b/doc/kcontrol/bell/CMakeLists.txt new file mode 100644 index 0000000000..a6defe0757 --- /dev/null +++ b/doc/kcontrol/bell/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/bell) diff --git a/doc/kcontrol/bell/index.docbook b/doc/kcontrol/bell/index.docbook new file mode 100644 index 0000000000..dc561b65b2 --- /dev/null +++ b/doc/kcontrol/bell/index.docbook @@ -0,0 +1,64 @@ + + + +]> + +
    +System Bell + + +PatDowler +MatthiasHoelzer +MikeMcBride + + + +2011-11-28 +&kde; 4.8 + + +The system bell or beep is a feature of the X server, which +attempts to make good use of the available hardware. + +&kde; normally does not use the system bell; instead using its +own system notifications, which could include log entries, message +popups, or its own beep. You can configure these in the +Manage Notifications &systemsettings; module. + +It is not always possible for the X server to actually make +a beep sound with exactly the parameters selected due to hardware +limitations. For example, on most PCs, volume control is not very good +so the X server seems to fake low volume with a reduced duration of +the sound. Thus, if the settings do not seem to do anything, this is +because the X server and/or the hardware do not support anything +better. + + Select Use system bell instead of system notification +then you are able to set the following parameters for the bell: + + + + +Volume (percentage of maximum volume) +Here you can customize the volume of the system bell. + + + +Pitch (in Hz) +Here you can customize the pitch of the system bell. + + + +Duration (in milliseconds) +Here you can customize the duration of the system bell. + + + + +For further customization of the bell, see the Accessibility &systemsettings; module. + +You can use the Test button to hear how +the current settings will sound. + +
    diff --git a/doc/kcontrol/clock/CMakeLists.txt b/doc/kcontrol/clock/CMakeLists.txt new file mode 100644 index 0000000000..80d65e48ad --- /dev/null +++ b/doc/kcontrol/clock/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/clock) diff --git a/doc/kcontrol/clock/index.docbook b/doc/kcontrol/clock/index.docbook new file mode 100644 index 0000000000..69afa0a8da --- /dev/null +++ b/doc/kcontrol/clock/index.docbook @@ -0,0 +1,90 @@ + + + +]> + +
    + +Date & Time + +&Mike.McBride; &Mike.McBride.mail; + + + +2013-12-05 +4.12 + + +KDE +Systemsettings +clock +date +time +set +configure + + + + + +Date & Time + +You can use this module to alter the system date and time, using a +convenient graphical interface. + +As these settings do not only affect you as a user, +but rather the whole system, you must have system administrator (root) access to change the system date and +time. If you do not have this access level, this module will only show +you the current settings, but your changes will not be saved. + + +Date and Time + +If you check Set date and time automatically you are able +to select a Time server from the drop down box and all other +settings in this dialog are disabled. + + +The applications rdate or ntpdate are used in +this module to fetch date and time from a time server. This happens when you log in to &kde; +while being online or when you later connect to the Internet and access to time +servers is possible. +Both applications are simple NTP clients that set a system's clock +to match the time obtained by communicating with one or more NTP servers. +This is not sufficient, however, for maintaining an accurate clock in the long run. +This is useful for occasionally setting the time on machines that do not have full-time +network access, such as laptops. + + +If you do not use a time server, you are able to set the date manually +using the lower half of the tab. Simply +choose your month and year using the controls at the top of the calendar +and the day of the month by clicking on the day in the +calendar. +Use the controls at the bottom of the calendar +to select the current date, enter the date in the edit box or select the +week of the year from the drop down box. + +You set the time using the spin boxes at the bottom of the analog clock. +You can also directly enter your value. + + + + +Time Zone +To set a new time zone, simply select your area from the list below. +Use the filter box to find the desired Area or Region. + + + + +
    diff --git a/doc/kcontrol/colors/CMakeLists.txt b/doc/kcontrol/colors/CMakeLists.txt new file mode 100644 index 0000000000..df4ece2e0d --- /dev/null +++ b/doc/kcontrol/colors/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/colors) diff --git a/doc/kcontrol/colors/index.docbook b/doc/kcontrol/colors/index.docbook new file mode 100644 index 0000000000..b1e99097ec --- /dev/null +++ b/doc/kcontrol/colors/index.docbook @@ -0,0 +1,399 @@ + + + + +]> + +
    + +Colors + +&Matthew.Woehlke; &Matthew.Woehlke.mail; + + + +2013-11-05 +4.12 + + +KDE +KControl +color +kcm + + + + +Colors + + + Introduction + + The Color Selection module is comprised of several sections: + + + + The Scheme tab, + used to manage schemes. + + + The Options tab, + used to change the options of the current scheme. + + + The Colors tab, + used to change the colors of the current scheme. + + + The state effects tabs + (Inactive, Disabled), used to + change the state effects of the current scheme. + + + + Note: This documentation will sometimes refer to the + "current" scheme, or the "active" scheme. + The "current" scheme is the set of colors and color scheme options + that was most recently applied, &ie; what you would get if you choose + Cancel. The "active" scheme is the set of + colors as has been most recently edited by you, &ie; what you would get if + you choose Apply. + + + + Scheme Management + + The Scheme tab lets you manage the color schemes + on your machine. Only one scheme is active at once, but you may save schemes, + allowing you to quickly change the scheme later. When you have created a + scheme you like, you can save it with Save Scheme.... + You can remove schemes using Remove Scheme. + Note that system schemes cannot be removed; trying to do so will display an + error. + + &kde; ships with several schemes. If you have an Internet connection, + you can also browse and retrieve user-created schemes using Get + New Schemes.... + + + Importing Schemes + + You can also import schemes that you have downloaded or otherwise + obtained, as well as import &kde; 3 schemes. &kde; 4 color schemes are + named like "*.colors", while &kde; 3 schemes are named like + "*.kcsrc". + + Because &kde; 4 has many more color roles than &kde;, importing a + &kde; 3 scheme is different from importing a &kde; 4 scheme. When a + &kde; 4 scheme is imported, it becomes part of your saved scheme + collection. When a &kde; 3 scheme is imported, the colors that exist in + &kde; 3 are overlaid onto the active scheme, and the result is not + automatically saved into your collection. After importing a &kde; 3 scheme, + you will likely need to adjust the colors that are new in &kde; 4, as well + as the state effects. For best results, before importing a &kde; 3 scheme, + select a similar &kde; 4 scheme (you do not need to apply the scheme before + importing). + + + + + Color Scheme Options + + The Options tab allows you to change some + properties that deal with how the color scheme is used, as well as some + options that change the color scheme that are different from actually + assigning colors. + + + Apply inactive window color effects + — If checked, state effects (see below) will be applied to inactive + windows. This can help visually identify active versus inactive windows, + and may have aesthetic value, depending on your taste. However, some + users feel that it causes distracting "flickering" since + windows must be repainted when they become inactive. Unlike desktop + effects, color state effects do not require compositing support and will + work on all systems, however they will only work on &kde; 4 applications. + + Inactive selection changes color + — If checked, the current selection in elements which do not have + input focus will be drawn using a different color. This can assist visual + identification of the element with input focus in some applications, + especially those which simultaneously display several lists. + + Shade sorted column in lists + — If checked, multi-column lists will use a slightly different + color to paint the column whose information is being used to sort the + items in the list. + + Apply colors to non-KDE4 applications + — If checked, &kde; will attempt to export its color scheme so that + non-&kde; 4 applications will use the same colors. Most applications will + honor the exported scheme to varying degrees, though some may have bugs + or otherwise not honor the exported scheme. + + Contrast + — This slider controls the contrast of shaded elements, such as + frame borders and the "3D" effects used by most styles. A lower + value gives less contrast and therefore softer edges, while a higher + value makes such edges "stand out" more. + + + + + + + Colors + + The Colors tab allows you to change the colors in + the active color scheme. + + Creating or changing a scheme is a simple matter of clicking on the + swatch in the color list and selecting a new color. You can check your + changes at any time by pressing Apply. It is suggested + that you save your scheme (via the Scheme tab) when you + are done. + + The Common Colors set, which is displayed + initially, is not actually a "set" in the sense used by &kde; (see + next section), but presents a number of color roles in a way that makes it + easier to edit the scheme as a whole. When creating a new color scheme, you + will usually change these colors first, and use the other sets to tweak + specific colors if needed. + + Note that Common Colors makes available roles from + all sets. For example, "View Background" here is shorthand for the + Normal Background role from the View set. Also, setting colors that do not + refer to a specific set will change that color in all + sets. (As an exception, "Inactive Text" will change the color for + all sets except for Selection; there is a separate + "Selection Inactive Text" for Inactive Text in the Selection set.) + Some roles may not be visible under Common Colors at + all, and can only be changed (if needed) by selecting the appropriate + set. + + + Color Sets + + &kde; 4 breaks the color scheme into several sets based on the type + of user interface element, as follows: + + View — + information presentation elements, such as lists, trees, text input boxes, etc. + + Window — + window elements that are not buttons or views. + + Button — + buttons and similar elements. + + Selection — + selected text and items. + + Tooltip — + tool tips, "What's This" tips, and similar elements. + + Window Manager — + window title bars and related elements. + + + + Each set contains a number of color roles. Except for the Window + Manager colors, each set has the same roles. All colors are associated with + one of the above sets. + + + + Color Roles + + Each color set is made up of a number of roles which are available in + all other sets. (The Window Manager set is an exception; it has its own + unique roles that do not exist in any other set, and does not use the same + roles as the other sets.) In addition to the obvious Normal Text and Normal + Background, these roles are as follows: + + + Alternate Background — + used when there is a need to subtly change the background to aid in + item association. This might be used ⪚ as the background of a + heading, but is mostly used for alternating rows in lists, especially + multi-column lists, to aid in visually tracking rows. + + Link Text — + used for hyperlinks or to otherwise indicate "something which may + be visited", or to show relationships. + + Visited Text — + used for "something (⪚ a hyperlink) that has been + visited", or to indicate something that is "old". + + Active Text — + used to indicate an active element or attract attention, ⪚ alerts, + notifications; also for hovered hyperlinks. + + Inactive Text — + used for text which should be unobtrusive, ⪚ comments, + "subtitles", unimportant information, etc. + + Negative Text — + used for errors, failure notices, notifications that an action may be + dangerous (⪚ unsafe web page or security context), etc. + + Neutral Text — + used to draw attention when another role is not appropriate; ⪚ + warnings, to indicate secure/encrypted content, etc. + + Positive Text — + used for success notices, to indicate trusted content, etc. + + + + As well as the text roles, there are a few additional + "decoration" roles that are used for drawing lines or shading + UI elements (while the above may, in appropriate circumstances, also be + used for this purpose, the following are specifically + not meant for drawing text). These are: + + + Focus Decoration — + used to indicate the item which has active input focus. + + Hover Decoration — + used for mouse-over effects, ⪚ the "illumination" effects for + buttons. + + + + In addition, except for Inactive Text, there is a corresponding + background role for each of the text roles. Currently (except for Normal + and Alternate Background), these colors are not chosen by the user, but are + automatically determined based on Normal Background and the corresponding + Text color. These colors may be previewed by selecting one of the sets + other than "Common Colors". + + The choice of color role is left to the developer; the above are + guidelines intended to represent typical usage. + + + + Window Manager Colors + + As previously stated, the Window Manager set has its own roles, + independent of those in other sets. These are (currently) only accessible + via Common Colors, and are as follows: + + + Active Titlebar — + used to draw the title bar background, borders, and/or decorations for + the active window (that is, the one with input focus). Not all window + decorations will use this in the same way, and some may even use the + Normal Background from the Window set to draw the title bar. + + Active Titlebar Text — + used to draw the title bar text when Active Titlebar is used to draw + the title bar background. May also be used for other foreground + elements which use Active Titlebar as the background. + + + + The Inactive Titlebar [Text] roles are the same as the above, but for + inactive windows, rather than active windows. + + + + + + Color State Effects + + Color state effects are applied to interface elements in the inactive + (windows that do not have focus; only if Apply inactive window + color effects is enabled) or disabled states. By changing the + effects, the appearance of elements in these states can be changed. Usually, + inactive elements will have reduced contrast (text fades slightly into the + background) and may have slightly reduced intensity, while disabled elements + will have strongly reduced contrast and are often notably darker or lighter. + + + Three types of effect may be applied to each state (with the effects + of the two states being independent). These are Intensity, Color and + Contrast. The first two (Intensity, Color) control the overall color, while + the last (Contrast) deals with the foreground colors relative to the + background. + + + Intensity + + Intensity allows the overall color to be lightened or darkened. + Setting the slider to the middle produces no change. The available effects + are: + + + Shade — + makes everything lighter or darker in a controlled manner. Each + "tick" on the slider increases or decreases the overall + intensity (&ie; perceived brightness) by an absolute amount. + + Darken — + changes the intensity to a percentage of the initial value. A slider + setting halfway between middle and maximum results in a color half as + intense as the original. The minimum gives a color twice as intense as + the original. + + Lighten — + conceptually the opposite of darken; lighten can be thought of as + working with "distance from white", where darken works with + "distance from black". The minimum is a color twice as + "far" from white as the original, while halfway between + middle and maximum gives an intensity halfway between the original + color and white. + + + + + + Color + + Color also changes the overall color, but is not limited to + intensity. The available effects are: + + + Desaturate — + changes the relative chroma. The middle setting produces no change; + maximum gives a gray whose perceptual intensity equals that of the + original color. Lower settings increase the chroma, giving a color that + is less gray / more "vibrant" than the original. + + Fade — + smoothly blends the original color into a reference color. The minimum + setting on the slider produces no change; maximum gives the reference + color. + + Tint — + similar to Fade, except that the color (hue and chroma) changes more + quickly while the intensity changes more slowly as the slider value is + increased. + + + + + + Contrast + + The contrast effects are similar to the color effects, except they + apply to the text, using the background color as the reference color, and + desaturate is not available. Fade produces text that "fades out" + more quickly, but keeps its color longer, while Tint produces text that + changes color to match the background more quickly while keeping a greater + intensity contrast for longer (where "longer" means higher + settings on the slider). For Contrast effects, the minimum setting on the + slider produces no change, while maximum causes the text to completely + disappear into the background. + + + + + + +
    + diff --git a/doc/kcontrol/cursortheme/CMakeLists.txt b/doc/kcontrol/cursortheme/CMakeLists.txt new file mode 100644 index 0000000000..3d3639a5c8 --- /dev/null +++ b/doc/kcontrol/cursortheme/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/cursortheme) diff --git a/doc/kcontrol/cursortheme/index.docbook b/doc/kcontrol/cursortheme/index.docbook new file mode 100644 index 0000000000..85c605757d --- /dev/null +++ b/doc/kcontrol/cursortheme/index.docbook @@ -0,0 +1,59 @@ + + + +]> + +
    + +Cursor Theme + +&Mike.McBride; &Mike.McBride.mail; +&Brad.Hards; &Brad.Hards.mail; + + + +2013-06-02 +&kde; 4.11 + + +This is the documentation for the &kde; &systemsettings; module to +customize the mouse cursor appearance. + + + + +KDE +Systemsettings +mouse +cursor + + + + +This module allows you to select from a number of installed cursor themes. +A preview of the cursor display is shown above the list box. + + +The features provided by this module may not be available on some systems. +Your system may need to be updated to support cursor themes. + + + +If you have additional cursor themes available, you can install and remove +them using the buttons right to the list box. Note that you cannot remove the default themes. + + +Use the Get New Themes button to launch the Get Hot New Stuff dialog and +download additional themes from the Internet. + +Some themes allow to +choose the cursor size using the combobox below to the label Size. + + + +The size can be set to the resolution dependent or one of the sizes available for your system. + + +
    diff --git a/doc/kcontrol/desktopthemedetails/CMakeLists.txt b/doc/kcontrol/desktopthemedetails/CMakeLists.txt new file mode 100644 index 0000000000..b74bf99563 --- /dev/null +++ b/doc/kcontrol/desktopthemedetails/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/desktopthemedetails) diff --git a/doc/kcontrol/desktopthemedetails/clicking-apply.png b/doc/kcontrol/desktopthemedetails/clicking-apply.png new file mode 100644 index 0000000000000000000000000000000000000000..f57723b4db0cfdbb13eef0ab30d0449291f49b7b GIT binary patch literal 124555 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

    M~q&N0>a}$v#T|W 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

    !OxYq$r%CVom$EKZO5dV7^s>GfRheRLrMyz^ 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/desktopthemedetails/index.docbook b/doc/kcontrol/desktopthemedetails/index.docbook new file mode 100644 index 0000000000..19882edb2d --- /dev/null +++ b/doc/kcontrol/desktopthemedetails/index.docbook @@ -0,0 +1,182 @@ + + + +]> +

    + +Desktop Theme + + +Andrew +Lake + + + +2013-06-02 +&kde; 4.11 + + +KDE +System Settings +desktop +theme +plasma + + + + +Theme tab + +A list of available themes is displayed on this tab. Select a theme by clicking on an item in the list. + +Use the Get New Themes button to launch the Get Hot New Stuff dialog and +download additional themes from the Internet. + + + + +Details tab + +A &kde; plasma desktop theme is made up of several components or items, +consisting mostly in svg backgrounds and colors schemes. This module allows you +to customize your desktop Plasma theme and to replace theme items +with items from other themes or from files. + + +Desktop theme items consist in panel theme item, kickoff theme item, +analog clock, ... + + +If you want to change your current theme for a full new theme (for example from +Air to Glassified) then you can do so in the Theme tab. + + + +Quick start +First download one or several themes you want to use to customize your +desktop items by clicking the Get New Themes... +button in the Theme tab. + +All the available themes will be displayed on top, the current one being highlighted. + +In the theme list, select a base theme that will be used for most widgets and start +customizing each item you want to change with a new theme, for example you can +have the panel in Glassified theme, the widget +backgrounds in Air and so on. + +Here Air is the theme for most widgets and we changed the panel background +to Glassified, the Analog clock to Glassified and the Notes to Oxygen. + + + +Customizing your plasma theme + + + + + + Customizing your plasma theme + + + + + + +Clicking the Apply will create a new theme named +(Customized) and will apply it to your desktop. + + + + +Creating a custom theme +When the module is opened, it will show items from the current desktop +theme. If you would like to start customizing with a different theme, select it +from the box above the list of theme items. This theme from the box is the +starting theme, the base for your new customized desktop theme. + + +In the list of items, for each item you would like to replace, select +replacement item from the drop list for that item. You may select the +corresponding item from another theme, or you may select a file. &plasma; +desktop theme items are svg files, except for the color scheme which is a &kde; +color scheme file. + + + +Click Apply when all the changes have been made. This +will create a new theme named (Customized) which you can +select from the Appearance Settings dialog on the desktop. + + + + +Your custom theme + + + + + + Customized + + + + + + +The theme items listed are the most visible components of the plasma +desktop theme. Other theme components are not listed. Your newly created +theme will use these unlisted components from the theme that you selected at +the start of creating the customized theme. + + + + +Naming a custom theme + +To provide a name for your customized theme, click on the +More checkbox and +enter the name of the theme. You may also provide your name (author), a theme +version and a description of your theme. Click Apply +when done. + + + + +Removing a theme + +Select the theme you would like to remove from the box above the list of +theme items. Click on the More check box. Click the +Remove Theme button to +remove the selected theme. + + + + +Exporting a theme to a file + +You can share your newly customized theme with the community by exporting the +theme to a file. Select your customized theme from the box above the list +of theme items. Click on the More check box. Click the +Export Theme to +File.... Enter the name of the zip file to which the theme will be +saved. + + + + +
    + + diff --git a/doc/kcontrol/fontinst/CMakeLists.txt b/doc/kcontrol/fontinst/CMakeLists.txt new file mode 100644 index 0000000000..d21455a73d --- /dev/null +++ b/doc/kcontrol/fontinst/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/fontinst) diff --git a/doc/kcontrol/fontinst/index.docbook b/doc/kcontrol/fontinst/index.docbook new file mode 100644 index 0000000000..66a48c526d --- /dev/null +++ b/doc/kcontrol/fontinst/index.docbook @@ -0,0 +1,109 @@ + + + +]> + +
    +Font Management + + +&Craig.Drummond; &Craig.Drummond.Mail; + + + + +2013-06-19 +&kde; 4.11 + + +KDE +Systemsettings +fonts + + + + +Font Management + +This module is responsible for installing, un-installing, previewing and managing your fonts. + + +Font Groups +There are 4 special pre-defined font groups: + + + All Fonts This will display all fonts, both personal and system-wide. + Personal Fonts The fonts shown will be your personal fonts, and will not be available to other users. + System Fonts The fonts shown will be those available to all users. Installing a font system-wide, or removing a system-wide font, will require administrator privileges. + Unclassified This will list all fonts that have not been placed into any user-defined groups. This group will only appear if you have some user-defined groups. + +To add a font to a group, drag it from the list of fonts onto a group. To remove a font from a group, drag the font onto the All Fonts group. +Below this list you find buttons to create a new group, remove a group and enable or disable the fonts in the current group. +In the context menu of this list you have additional menuitems to print font samples and export a font to a zip archive. + + +Enabling and Disabling +Users with many fonts may find it useful to only have certain fonts enabled (or active) at certain times. To facilitate this, this module will allow you to disable individual fonts, or whole groups of fonts. Disabling a font does not remove the font from the system, it simply hides it so that it no longer appears within applications. Re-enabling a font will then allow it to be used. + + + + + +Font List + +The main display is a list of the installed fonts, grouped via the fonts' family name - the number in square brackets represents the number of installed styles for that family. e.g. The Times font may be listed as: + + + Times [4] + + Regular + Italic + Bold + Bold Italic + + + + + +To install a font, press the Add... button, and select the desired fonts from within the file dialog. The selected font group will control where the fonts will be installed. +To un-install fonts, select the appropriate fonts from the list, and press the Delete... button. + +Click with the &RMB; to open a context menu with some additional actions like Enable, Disable, Print, Open in Font Viewer and Reload. + + +Font Filtering +A text field on top of the font preview allows you to filter the list of fonts. You can filter fonts based upon different categories: + + Family. + Style. + Foundry. + FontConfig match. This allows you to enter a family name, and see the family that fontconfig would actually use. + Font file type. + Font file name. + Font file location. + Writing system. + + + + +Get New Fonts +New fonts may be installed from local files, or downloaded from kde-look.org. The Get New Fonts entry in the tool button (located above the group list), allows you to install fonts from kde-look.org. The fonts downloaded in this manner will be installed into your Personal Fonts group. To install system-wide, you will need to move them to the System Fonts group - this may be achieved by dragging the fonts over the System Fonts group entry and will require administrator privileges. + + + + + +Duplicate Fonts +If you have lots of fonts installed on your system it is possible that you may have duplicates. +Click on the tools icon above the group list and select the Scan For Duplicate Fonts... tool, a simple tool that will scan your system looking for fonts that have multiple files associated with them. For example, if you have times.ttf and times.TTF installed in /usr/local/share/fonts the underlying font mechanism (called FontConfig) will only see one of these. So, if you un-installed the font, it would re-appear, as only one of the files would have been removed. Running this tool will produce a dialog listing each font that has multiple files, and the corresponding list of files. To select a file for deletion, click on the column containing the trash can icon. + + + +Preview +This displays a preview text in different font sizes. +Using the context menu enables you to zoom in and out, select a preview type (Standard Preview or All Characters) and change the preview text. + + +
    diff --git a/doc/kcontrol/fonts/CMakeLists.txt b/doc/kcontrol/fonts/CMakeLists.txt new file mode 100644 index 0000000000..d09f4035a2 --- /dev/null +++ b/doc/kcontrol/fonts/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/fonts) diff --git a/doc/kcontrol/fonts/adjust-all.png b/doc/kcontrol/fonts/adjust-all.png new file mode 100644 index 0000000000000000000000000000000000000000..506a6179c871767b4442d039198304aa11738de4 GIT binary patch literal 32155 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/fonts/anti-aliasing.png b/doc/kcontrol/fonts/anti-aliasing.png new file mode 100644 index 0000000000000000000000000000000000000000..d88cacaed1afcfc947291b3b0616b48014ff7900 GIT binary patch literal 21340 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/fonts/index.docbook b/doc/kcontrol/fonts/index.docbook new file mode 100644 index 0000000000..b57c5f0199 --- /dev/null +++ b/doc/kcontrol/fonts/index.docbook @@ -0,0 +1,169 @@ + + + +]> + +
    + +Fonts + +&Mike.McBride; &Mike.McBride.mail; +&Anne-Marie.Mahfouf; &Anne-Marie.Mahfouf.mail; + + + +2013-12-05 +&kde; 4.12 + + +KDE +KControl +fonts + + + + + +Fonts + +This module is designed to allow you to easily select different +fonts for different parts of the &kde; Desktop. + + + +Here's a screenshot of the fonts settings module + + + + + + The fonts settings module + + + + + +The panel consists of different font groups to give you a lot of +flexibility in configuring your fonts: + + +General: Used everywhere when the other font +groups do not apply + +Fixed width: Anywhere a +non-proportional font is specified + +Small: When small fonts are used + +Toolbar: Font used in &kde; application +toolbars + +Menu: Font used in &kde; application +menus + +Window title: Font used in the window +title + +Taskbar: Font used in the taskbar +panel applet + +Desktop: Font used on the desktop +to label icons + + + +Each font has a corresponding Choose... +button. By clicking on this button, a dialog box appears. You can +use this dialog box to choose a new font, a font style and size. +Then press Ok. + +An example of the font you have chosen will be displayed in the space +between the font group name and the Choose... +button. + +When you are done, simply click OK and +all the necessary components of &kde; will be restarted so your changes +can take affect immediately. + +The Adjust All Fonts... button allows you to +quickly set properties for all the fonts selected +above. A font selection dialog similar to the standard one will +appear, but you will notice checkboxes that allow you to change the +Font, Font style or +Size independently of each other. You can +choose any one, two, or three of these options, and they will be +applied to all the font groups. + + + +Adjusting all fonts + + + + + + The Adjust All Fonts... dialog + + + + + +For example, if you have selected several different font faces +above, and realize they are all a size too big (this often happens +when you change screen resolution, for instance), you can apply a new +font size to all the fonts, without affecting your customized font +faces and styles. + + +Anti-aliasing text + +Default anti-aliasing settings are those used system wide by your distribution and labelled System Settings. You can disable all anti-aliasing by choosing Disabled in the drop down box. + +To use and set up anti-aliasing, simply choose Enabled from the box on the right of Use anti-aliasing:. The Configure... button will then get enabled and clicking on it will bring you a dialog to configure anti-aliasing. + + + +Anti-aliasing properties + + + + + + The anti-aliasing properties dialog + + + + + +Placing a mark in the Exclude range: checkbox will allow you to specify which range of fonts will not be anti-aliased. This range is specified +with the two combo boxes on the same line. + +You can also choose the method that &kde; uses to create an anti-alias +look to your fonts, and how strongly it should be applied. If you are not +familiar with the individual methods, you should leave this option +alone. + + + + +The ability to use anti-aliased fonts and icons requires that you have +support in both X and the &Qt; toolkit, that you have suitable fonts +installed, and that you are using the built-in font serving capabilities +of the X server. If you still are having problems, please contact the +appropriate &kde; mailing list, or check the +FAQ. + + + + +Fonts DPI + +Force fonts DPI: proposes you an alternate DPI other than your system one which is used as default when this setting is on Disabled. You can check what DPI your X server is set to by running xdpyinfo | grep resolution in a terminal window and then change the DPI using the drop down box. This will be applied to newly started applications only. + + + + +
    diff --git a/doc/kcontrol/fonts/main.png b/doc/kcontrol/fonts/main.png new file mode 100644 index 0000000000000000000000000000000000000000..2c0346c4a41c28d81f0334029ab5211846a0eeac GIT binary patch literal 33765 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�fGUb)VQ;B7 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/joystick/CMakeLists.txt b/doc/kcontrol/joystick/CMakeLists.txt new file mode 100644 index 0000000000..5c2d007e3d --- /dev/null +++ b/doc/kcontrol/joystick/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/joystick) diff --git a/doc/kcontrol/joystick/index.docbook b/doc/kcontrol/joystick/index.docbook new file mode 100644 index 0000000000..1b89d72f09 --- /dev/null +++ b/doc/kcontrol/joystick/index.docbook @@ -0,0 +1,137 @@ + + + +]> +
    + +Joystick + + +Michael +Anderson + +
    nosrednaekim@gmail.com
    +
    +
    + +
    + +2013-12-05 +4.12 + + +KDE +System Settings +joystick +calibrate + +
    + + +Joystick configuration module + +This module provides an interface to calibrate your joystick device as well as +see which functions on your joystick are mapped to which logical button or +axis. + + + +Here's a screenshot of the joystick module + + + + + + The joystick module + + + + + + +Device + + +Here you can see the logical location of the device. If you have more +than one joystick device, you can also select which one to configure. + + + + +Position + + +The plotted location of the X and Y axes of the joystick. Enable Show trace +to plot the path of the joystick from one point to another. + + +If the joystick cannot reach every point on this graph, or if it does not center correctly, you need to calibrate your device. + + + + +Buttons + + +A place to see the pressed state of buttons on your joystick and if the buttons +are mapped correctly. When a joystick button is pressed, PRESSED will appear +next to the logical number (as the computer sees it) of the button which was +pressed. + + + + +Axes + + +This displays the numerical values of the axis positions. 0 is centered and the +maximum and minimum values depend on the joystick and the particular axis. + + + + +Calibrate + + +Clicking on Calibrate will open a dialog to calibrate every axis on your joystick. + + + + +Calibrating your joystick + + + + + + Calibrating your joystick + + + + + + +Each axis will have to be moved to the minimum position, then the center, and finally the +maximum position. A meter in the bottom left corner of the dialog will help +determine which way increases and which way decreases the values. + + + + + +
    + + diff --git a/doc/kcontrol/joystick/joystick-calibration.png b/doc/kcontrol/joystick/joystick-calibration.png new file mode 100644 index 0000000000000000000000000000000000000000..5ff3bda13cccc337ec98efe2c69648734ab88251 GIT binary patch literal 25142 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 z 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 LG!(zen+E+K08s;U literal 0 HcmV?d00001 diff --git a/doc/kcontrol/kcmaccess/CMakeLists.txt b/doc/kcontrol/kcmaccess/CMakeLists.txt new file mode 100644 index 0000000000..22beb92d21 --- /dev/null +++ b/doc/kcontrol/kcmaccess/CMakeLists.txt @@ -0,0 +1,4 @@ +########### install files ############### +# +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/kcmaccess) diff --git a/doc/kcontrol/kcmaccess/index.docbook b/doc/kcontrol/kcmaccess/index.docbook new file mode 100644 index 0000000000..27d5188099 --- /dev/null +++ b/doc/kcontrol/kcmaccess/index.docbook @@ -0,0 +1,264 @@ + + + +]> + +
    +Accessibility + + +&Mike.McBride; &Mike.McBride.mail; + + + +2013-12-05 +&kde; 4.12 + + +KDE +Systemsettings +accessibility +keys +bell + + + + +Accessibility + + +Introduction + +This module is designed to help users who have difficulty hearing +audible cues, or who have difficulty using a keyboard. + + +The module is divided into four tabs: Bell, Modifier keys, Keyboard Filters and Activation Gestures. + + + +<guilabel>Bell</guilabel> + + +This panel is divided into an Audible Bell section +and a Visible Bell section. + + + +The top check box labeled Use System Bell, determines +whether the normal System bell rings. If this option is disabled, the +System bell will be silenced. + + + +The next check box down can be used to play a different sound whenever +the system bell is triggered. To activate, place a mark in the check +box labeled Use customized bell, and enter the +complete pathname to the sound file in the text box labeled +Sound to play. If you want, you can select the +Browse button to navigate through your filesystem +to find the exact file. + + + +For those users who have difficulty hearing the System bell, or those +users who have a silent computer, &kde; offers the visible bell. This +provides a visual signal (inverting the screen or flashing a color +across it) when the system bell would normally sound. + + + +To use the visible bell, first place a mark in the check box labeled +Use visible bell. + + + +You can then select between Invert screen, or +Flash screen. If you select Invert +screen, all colors on the screen will be reversed. If you +choose Flash screen, you can choose the color by +clicking the button to the right of the Flash +screen selection. + + + +The slider bar can be used to adjust the duration of the visible +bell. The default value is 500ms, or half a second. + + + + + +<guilabel>Modifier keys</guilabel> + +There are the two sections Sticky Keys +and Locking Keys to this panel. + + + +Use Sticky Keys + + +If this option is enabled, you can press and release the &Shift;, +&Alt; or &Ctrl; keys, and then press another key to get a key combo +(example: &Ctrl; &Alt; +Del could be done with &Ctrl; then &Alt; +then Del). + + + +Also in this section is a check box labeled Lock Sticky +Keys. If this check box is enabled, the &Alt;, &Ctrl; +and &Shift; keys stay selected until you +de-selected them. + + + +As an example: + + + +With Lock Sticky Keys disabled: + +If you press the &Shift; key then press the +F key, the computer interprets this as &Shift;F. Now if you +type a P, the computer interprets this as the letter p +(no shift). + + + + + +With Lock Sticky Keys enabled: + + +If you press the &Shift; key twice then press the F key, +the computer interprets this as &Shift;F. Now if you +type a P, the computer interprets this as the letter P +(&Shift;P). To +de-select the &Shift; key, press it again. + + + + + + + + + + + + + +<guilabel>Keyboard Filters</guilabel> + +There are two sections to this panel. + + + +Use slow keys + + +If this option is enabled, you must hold the key down for a +specified length of time (adjustable with the slider) before the +keystroke will be accepted. This helps prevent accidental key strokes. + + + + + +Use bounce keys + + +If this option is enabled, you must wait for a specified length of time +(configurable with the slider) before the next key press can be +accepted. This prevents accidental multiple key strokes. + + + + + + + + + + +<guilabel>Activation Gestures</guilabel> + +There are two sections to this panel. + + + +Activation Gestures with these options: + + + +Use gestures for activating sticky keys and slow keys +Here you can activate keyboard gestures that turn on the following features: +Mouse Keys: Press &Shift;+NumLock +Sticky keys: Press &Shift; key 5 consecutive times +Slow keys: Hold down &Shift; for 8 seconds +Turn sticky keys and slow keys off after a certain period of inactivity + + + + + + +Notification with these options: + + + +Use the system bell whenever a gesture is used to turn an accessibility +feature on or off + +Show a confirmation dialog whenever a keyboard accessibility feature is +turned on or off +If this option is checked, &kde; will show a confirmation dialog whenever a +keyboard accessibility feature is turned on or off. +Ensure you know what you are doing if you uncheck it, as the keyboard +accessibility settings will then always be applied without confirmation. + +Use &kde;'s system notification mechanism whenever a keyboard accessibility +feature is turned on or off + + + + + +Click the Configure Notifications button to open a dialog +which allows you to edit the notifications for status changes of all keys. + + + + + + +
    diff --git a/doc/kcontrol/kcmsmserver/CMakeLists.txt b/doc/kcontrol/kcmsmserver/CMakeLists.txt new file mode 100644 index 0000000000..68189ccdbc --- /dev/null +++ b/doc/kcontrol/kcmsmserver/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +#KDE_LANG = en +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/kcmsmserver) diff --git a/doc/kcontrol/kcmsmserver/index.docbook b/doc/kcontrol/kcmsmserver/index.docbook new file mode 100644 index 0000000000..fe580c36af --- /dev/null +++ b/doc/kcontrol/kcmsmserver/index.docbook @@ -0,0 +1,122 @@ + + + +]> + +
    + +Session Management + +&Jost.Schenck; &Jost.Schenck.mail; + + + +2013-12-05 +&kde; 4.12 + + +KDE +KControl +session +System Settings + + + + +Session Management + + +Use + +In this &systemsettings; module you can configure &kde;'s session +manager and logout settings. + +Session management refers to &kde;'s ability to save the state +of applications and windows when you log out of &kde; and restore them +when you log back in. + + +General + + +Confirm logout + +If this option is checked, when logging out, &kde; will display a +dialog asking for confirmation. In this dialog you can also choose +whether you want to restore your current session when you login the next +time. + + + +Offer shutdown options + +If this option is checked, &kde; will offer a choice of actions during +logout. These include simply ending the current session (the +action performed if shutdown options are not enabled) turning off the +computer, or restarting the computer. + + + + + + +Default Leave Option +You can configure what should happen by default when you log out of +&kde;. These options are not possible on all operating systems, and some of +them may not appear unless you are using &kdm; as your login manager. + +The options available are self explanatory, if you are in doubt, +leave the default settings. They are: + + +End current session (this is the default) +Turn off computer +Restart computer + + + + +On Login +You may choose one of three options on what should happen when +you log into &kde;: + + + +Restore previous session +If this option is checked, &kde; will save your current +session's state when you logout. &kde; will restore your session on the +next login, so you can continue to work with a desktop just like you +left it. + + + +Restore manually saved session +Instead of restoring &kde; to the state it was when +you logged out last, it will be restored to a specific state that you +have saved manually. +If this option is checked, the start menu offers an additional item +LeaveSave Session. + + + +Start with an empty session + +If you choose this option, &kde; will never restore sessions that it has saved. + + + +Finally, you can enter a colon (:) or comma (,) +separated list of applications that should not be saved in sessions, +and therefore will not be started when restoring a session. For example +xterm:konsole or xterm,konsole. + + + + + + + +
    + diff --git a/doc/kcontrol/kcmstyle/CMakeLists.txt b/doc/kcontrol/kcmstyle/CMakeLists.txt new file mode 100644 index 0000000000..47ab4e8b0c --- /dev/null +++ b/doc/kcontrol/kcmstyle/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/kcmstyle) diff --git a/doc/kcontrol/kcmstyle/index.docbook b/doc/kcontrol/kcmstyle/index.docbook new file mode 100644 index 0000000000..a0b456b5ac --- /dev/null +++ b/doc/kcontrol/kcmstyle/index.docbook @@ -0,0 +1,238 @@ + + + +]> + +
    + + +Style + +&Mike.McBride; &Mike.McBride.mail; + + + +2013-06-02 +&kde; 4.11 + + +KDE +System Settings +style + + + +Style + + +Introduction + +This module is used to configure how the individual widgets are +drawn by &kde;. + +A Widget is a commonly-used +programmer's term for referring to User Interface elements such as +buttons, menus, and scroll bars. You can think of them as the +fundamental pieces that are assembled to make your +application. + +You can configure how the widgets are drawn with this module, +but to change the color of the widgets, you should refer to the +section entitled Colors. + +This panel is divided into two tabs: Applications +and Fine Tuning. + + +<guilabel>Applications</guilabel> tab + +The top drop down box, labeled Widget Style +contains a list of the pre-defined styles. +Each style has a name, and a brief description. + +To change styles, simply click on the style name, and a preview +of the style will be displayed in the preview box below the style list. + + If a style is configurable, the Configure... button +at the right side of the drop down box is enabled and can be used to open +a dialog to select further settings. + + + + + + +<guilabel>Fine Tuning</guilabel> tab + + + + +Graphical effects + +&kde; applications will run internal animations with the selected display resolution and CPU usage. + + + + +Show icons on buttons + +If this option is selected, action buttons (like OK and +Apply) will have a small icon located within them to act +as a visual reference. If this option is not selected, then only text +will appear on the button. + + + + +Show icons in menus + +If this option is selected, &kde; applications will show small icons alongside +most menu items. If this option is not selected, then only text +will appear in the menus. Changes to the visibility of menu icons will only affect newly started +applications. + + + + +Main toolbar text, Secondary toolbar text + +These drop down boxes lets you determine where on the button in both toolbars the +text name of the button will appear as the default. +If No Text is selected, then there is no text on the toolbar buttons. +If Text Only is selected, then the button's icon is replaced with a text name of +the button. If Text Beside Icons is selected, then the name of the button +will be placed to the right of the icon. +If Text Below Icons is selected, the default will be to have the text +of the button below the icon. + +This option only specifies the default location. +Each application can override the setting used in this panel. + + + + +Menubar style + +In application: The classic menubar at the top of the application window. +Title bar button: The window has an additional menu button top left. +All changes will take effect only for newly started applications. +Top screen menubar: This will turn on a menubar at the top of the screen that +is hidden by default and revealed on mouse over or a menu button on the window decoration. +This menubar will reflect the menu options of the active application. +Only export: for use by plasma runners + applets. +To use this feature you need a KRunner plugin like Appmenu action launcher. +Select an application, press &Alt;F2 +and type the menu action you want to perform. + + + + + + + + + + + +
    diff --git a/doc/kcontrol/keyboard/CMakeLists.txt b/doc/kcontrol/keyboard/CMakeLists.txt new file mode 100644 index 0000000000..deb161aec2 --- /dev/null +++ b/doc/kcontrol/keyboard/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/keyboard) diff --git a/doc/kcontrol/keyboard/index.docbook b/doc/kcontrol/keyboard/index.docbook new file mode 100644 index 0000000000..d737994415 --- /dev/null +++ b/doc/kcontrol/keyboard/index.docbook @@ -0,0 +1,218 @@ + + + +]> + +
    +Keyboard + + + +&Mike.McBride; &Mike.McBride.mail; +&Anne-Marie.Mahfouf; &Anne-Marie.Mahfouf.mail; + + + +2013-12-05 +&kde; 4.12 + + +KDE +System Settings +keyboard + + + +This module allows you to choose how your keyboard works. + +There are three tabs in this module. + + +The Hardware tab +The actual effect of setting these options depends upon the +features provided by your keyboard hardware and the X server on which +&kde; is running. As an example, you may find that changing the key +click volume has no effect because that feature is not available on your +system. + + + +Keyboard model: + + +Here you can set your keyboard model. This setting is independent of your +keyboard layout and refers to the "hardware" model, i.e. the way your +keyboard is manufactured. Modern keyboards that come with your computer usually +have two extra keys and are referred to as "104-key" models, which is +probably what you want if you do not know what kind of keyboard you have. + + + + + +NumLock on KDE Startup + +You can choose to either always Turn on or +Turn off the NumLock when &kde; starts, or you can +choose to have &kde; leave NumLock at whatever it was set to before &kde; +started up. + + + + +Keyboard Repeat + +When this option is turned on, pressing and holding down a key +emits the same character repeatedly until the key is released. Pressing +and holding the key will have the same effect as pressing it multiple +times in succession. + Almost all users will want to have this option enabled, because it +makes navigating through documents with the arrow keys significantly +easier. + + + +Delay + +This option allows you to set the delay after which a pressed +key will start generating keycodes. + + + +Rate + +This option allows you to set the rate at which keycodes are +generated while a key is pressed. + + + +Key click volume + +If supported, this option allows you to hear audible clicks from +your computer's speakers when you press the keys on your keyboard. In +essence, this simulates the click of a mechanical +type-writer. You can change the loudness of the key click feedback by +dragging the slider button. Setting the volume to 0% by moving the slider +to the left turns off the key click. +Type some characters into the Test area text box to +verify the volume you selected. +Many computers won't support this function. +Very few people would choose to enable this option, since it +generally annoys everyone else in the room. However, if your heart +yearns for the pre-soft-key era, this may help you to re-experience the +warm sentimentality of days-gone-by. + + + + + + + + + + + +The Layouts tab +This tab lets you choose what keyboard layouts you want to use, what +indicator you want in the system tray, how you want to switch and which +shortcuts you will use. + + + +Layout Indicator + +You can choose to Show layout indicator +which will show the language iso name in the system tray. You can choose to +show the indicator even if you have a single layout enabled +and you can show the language flag instead of only the ISO code by checking +Show flag. + + + + +Switching Policy + +If you select Application or +Window switching policy, changing the keyboard layout will +only affect the current application or window. Global will +change the keyboard layout globally and Desktop will change +it only for the current virtual desktop. + + + + + +Shortcuts for Switching Layout + +Main shortcuts is a shortcut for switching +layouts which is handled by X.org. 3rd level shortcuts is a +shortcut for switching to a third level of the active layout (if it has one) +which is handled by X.org. It allows modifier-only shortcuts. +Alternative shortcut is a shortcut for switching layouts +which is handled by &kde;. It does not support modifier-only shortcuts and also +may not work in some situations (⪚ if popup is active or from screensaver). + + + + + +Configure layouts + +If you check Configure layouts you will be able to +add and remove keyboard layouts in order to switch between them when you need. + +Clicking on Add will open a dialog where you +will be able to choose the new keyboard layout you want to add as well as its +variant, label and shortcut. + + +The list of layouts right to the Layout label in the +Add Layout dialog can be narrowed down using +Limit selection by language drop-down list. You +can click on Preview button to preview chosen layout +in a separate window. + +You can order the layouts with the up and down buttons, the top one being +the default one. + + + + +Spare layouts + +This option can be enabled only if you have more than two layouts. +Spare layouts allow to toggle between small number of layouts easily +while keeping more layouts handy close by. For example you might use 3 +languages: English, Ukrainian and German but first two are used often +and third one just occasionally. In this case you can configure first +two as main layouts (setting Main layout count: 2) +and German one as spare one - when you toggle with +keyboard and left mouse button the switch will happen between main +layouts only but you can always choose 3rd layout with context menu. +When spare layout is chosen it replaces the last main layout (this is +done for technical reasons, usually global shortcuts work based on the +1st active layout so it's more reliable to preserve the 1st layout when +allowing to activate spare layouts). + +As X.org only allows to have 4 layouts to switch spare layouts feature +also allows to overcome this limitation: user can have up to 4 main +layouts (managed by X.org) but 4 more spare layouts allowed (managed by +layout switcher). Thus user can conveniently work with up to total of 8 +layouts (although the 4 spare layouts limit can be raised in the future). + + + + + + + + +The Advanced tab +In this tab, if you check Configure keyboard options +you will then be able to set a few options regarding some keys settings. You can +expand these options by clicking on the > symbol on the left of the option +then you choose your setting in the expanded list. + +
    diff --git a/doc/kcontrol/keys/CMakeLists.txt b/doc/kcontrol/keys/CMakeLists.txt new file mode 100644 index 0000000000..2efb379dce --- /dev/null +++ b/doc/kcontrol/keys/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/keys) diff --git a/doc/kcontrol/keys/index.docbook b/doc/kcontrol/keys/index.docbook new file mode 100644 index 0000000000..f634c939b8 --- /dev/null +++ b/doc/kcontrol/keys/index.docbook @@ -0,0 +1,202 @@ + + + +]> + +
    +Shortcuts + + +&Mike.McBride; &Mike.McBride.mail; +&Jost.Schenck; &Jost.Schenck.mail; + + + +2013-12-05 +&kde; 4.12 + + +KDE +KControl +key bindings +bindings +shortcuts + + + + +Shortcuts + + +Introduction + +While most of the functionality offered by &kde; can be accessed +using a simple point and click interface, many people +prefer using the keyboard for some tasks. Pressing something like + &Ctrl;F is often +just faster than moving your hands off the keyboard to the mouse, +opening the Edit menu and selecting +Find. + + As different people have different preferences about keyboard +shortcuts, &kde; offers full customization of key +bindings. A key binding or shortcut is a combination of an +action with a key or a combination of keys. + + + + +Standard Shortcuts and Global Shortcuts + +Standard shortcuts and Global shortcuts work just the same. +Actually, in a certain way standard or application shortcuts are +global as well. The only +difference is: + + +Standard keyboard shortcuts refer to actions +that are often available in applications, such as Save, Print, Copy +&etc; +Global keyboard shortcuts are shortcuts for +actions that make sense even when no application is opened. These +shortcuts usually refer to actions like switching desktops, manipulating +windows &etc; + + +Please note, that the application shortcuts configured here are +only the standard actions often found in +applications. Most applications will define their own actions as well, +for which you have to customize key bindings using the application's +key bindings dialog. + + +Standard Keyboard Shortcuts page +At the top of this dialog you see an input box, where you can +search interactively for shortcut names (⪚ Copy) or combination of keys +(⪚ Ctrl+C) by typing them literally here. +Below the search box you can see a list of key bindings, &ie; associations between actions +(⪚ Copy) shown in the Actions column and keys or combination of keys +(⪚ &Ctrl;C ) shown in the +Shortcut or Alternate column. + + + + + +Global Keyboard Shortcuts page +At the top of this page is a drop down box which allows you +to select a KDE component like KWin, Plasma Desktop &etc; +The defined shortcuts for the selected component are displayed in the +Action and Global column in the list view. +Click the File drop down box at the right to import/export a +Scheme, set all shortcuts to none and remove a component. +This page has the same search box as the Standard Keyboard +Shortcuts tab. + + + + +Configuring Key Bindings + +Configuring key bindings is pretty easy. In the middle of +these &systemsettings; modules you will find a list of available +actions. If there's a key binding configured for that action you will +find it in the columns right to it. Just select the action you want to +configure. + +After you have selected an action in the list you will notice that +this item is highlighted and you see two additional check boxes below +this item in the list view. There you can configure a +combination of keys or maybe no key binding at all for the selected +action. + + + +Default: the selected action +will be associated with &kde;'s default value. This is a good choice +for most actions, as &kde; comes with reasonable key bindings we have +thought about. + +Custom: if this option is +enabled, you can create a key combination for the selected +action. Click on the button labeled either None +or labeled with the previously selected custom shortcut. Now the button label +changes to Input. Then press any modifier key +(&ie; &Shift;, &Ctrl;, or &Alt;) and then normal key or a function key (⪚ F11) +you want to assign to this key combination. +Clicking on the Alternate column of a row in the list +allows to edit the second shortcut for the action. + + + + + + + + +
    diff --git a/doc/kcontrol/khotkeys/CMakeLists.txt b/doc/kcontrol/khotkeys/CMakeLists.txt new file mode 100644 index 0000000000..3873b3657e --- /dev/null +++ b/doc/kcontrol/khotkeys/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/khotkeys) diff --git a/doc/kcontrol/khotkeys/groups-comment.png b/doc/kcontrol/khotkeys/groups-comment.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef80c3ad0e376366627d1c98c3894cf9e93ef70 GIT binary patch literal 63546 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

    ~3nkyjaUcHH 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ⅆ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 + + +]> +

    +Custom Shortcuts + + + +Subhashish Pradhan +&TC.Hollingsworth; &TC.Hollingsworth.mail; + + + + +2011 +Subhashish Pradhan + + +2012 +&TC.Hollingsworth; + +&FDLNotice; + +2013-12-05 +&kde; 4.12 + + +KDE +Systemsettings +shortcuts +hotkeys +Custom Shortcuts +khotkeys + + + + +Introduction + +The Custom Shortcuts &systemsettings; module +allows you to configure custom keyboard shortcuts and mouse gestures. You can +use them to control applications, run specific commands, and more. + + + + + +Managing Shortcuts and Groups + + +Adding Groups + +The module allows to you to sort related shortcuts into Groups. For +instance, if you have some shortcuts that relate to your music player, you +could create a group for them called Music Player. + + +To add a new group, click on the Edit button below +the left pane and select the New Group option. + + + + +Adding Shortcuts + +To add a new shortcut, click on the Edit button +below the left pane and select the New option. + +The first menu that appears allows you to select the type of trigger. The +following options are available: + + + + +Global Shortcut +These are standard keyboard shortcuts that will be recognized +anywhere, as long as a &kde; &plasma; Workspace is running. + + + +Window Action +Window Actions are triggers that occur when something happens +to a particular window, like when it appears, gains focus, or is closed. + + + + +Mouse Gesture Action +A mouse gesture action is triggered when a particular movement +of the mouse (or touchpad or touchscreen) is performed. + + + + +Once you've selected the type of trigger, another submenu appears that allows +you to select an action type. The following types are available: + + + + +Command/&URL; +This action will launch a command or open a &URL; when the +shortcut is triggered. + + + +&DBus; Command +This action will call a &DBus; method in a running application or +system daemon. For more information on &DBus;, see the +&DBus; +Introduction on &kde; TechBase. + + + +Send Keyboard Input +This action will send keyboard input to the currently +running application, just as if you had typed it in yourself. + + + + +Once you've selected the action type, you can then edit the shortcut to +your liking. See for more information. + + + + +Deleting Shortcuts and Groups + +To delete a shortcut or group, select it, then click on the +Edit button below the left pane, and select the +Delete option. + + + + +Exporting Groups + +You can export a group, so you can save the shortcuts contained within and +use them on another computer or maintain a backup. + +To export a group, select the group to be exported, then click on the +Edit button below the left pane and select the +Export Group... option, which opens a new window that +lets you define some options about the exported group. The following options +are available: + + + + +Export Actions +This allows you to select the state the shortcuts will be in +when they are imported later. Select Actual State to +maintain their current state, Enabled to ensure they are +all enabled, or Disabled to ensure they are all disabled. + + + + +Id +Here you may enter text to identify the group. If the group is +included by default, this text may be filled in by default. + + + +Allow Merging +This defines what happens if the group already exists on the +system the exported group is imported to. When enabled, any new actions will +be added to the group on the target system, while actions that have the same +name but a different configuration will updated with the configuration from the +imported file. When disabled, the module will refuse to import the file. + + + + +Filename +Here you may enter the filename you wish to export the +shortcut to. You may also select the Browse button to +the right of the text box to open the File dialog and select a file from there. + + +Exported files use the extension .khotkeys by +default. + + + + + + +Exporting a Group + + +The Export Group dialog. +Exporting a group of shortcuts. + + + + + + +Importing Groups + +To import a group, click the Edit button below the +left pane and select Import.... A file selection dialog +opens that permits you to locate a file previously created using the Export +function. + + + + + + + +Modifying Groups + +In the left section of the window, the default shortcuts are categorized +into groups. These groups can be expanded by clicking the arrow beside them to +reveal the shortcuts. + +When you click on a group, you are presented with two tabs to configure +the group itself. The Comment allows you to store notes +about the group, and are not actually used by the system for anything. The +Conditions tab allows you to restrict which windows a group +of shortcuts works with. + + +The Comment Tab + + +The Comment tab in a group. +Modifying a group's comment. + + + +Conditions are displayed in a tree, the top level of which is +And. All conditions beneath And must +be satisfied for shortcuts in the group to be triggered. + +You may add additional groups of conditions by clicking the +New drop down box to the right of the tree of conditions. Types +of groups include the aforementioned And, +Or, in which only one member of the group must be +satisfied, or Not, in which the inverse of all +members will trigger the shortcuts in the group. + +To add a window definition to the list, press the New +button. You may select Active Window... if you want +the shortcut to be triggered only if the specified window currently has focus, +or you may select Existing Window... if you want the +shortcut to be triggered as long as that window is open , regardless of +whether or not you are using it. Selecting either of these options opens a +window where you can edit the window definitions. + +Click the Edit... button to edit an existing set +of window definitions. A window opens with the window definition editor. For +more information, see . + +To remove a window definition from the conditions list, click the +Delete button. + + + + + +Modifying Shortcuts + +In the left section of the window, the default shortcuts are categorized +into groups. These groups can be expanded by clicking the arrow beside them to +reveal the shortcuts. + +The Preset Actions group, when expanded, reveals a +shortcut configuration named PrintScreen which, when +selected, reveals section on the right side, with three tabs: + + +The Comment Tab + +The Comment tab allows you to describe how to use the +shortcut, what it does, or anything else you might want to include. + + + + +The Trigger Tab +The Trigger tab contains the trigger configuration, +which depends on the type of trigger specified: + + + + +Global (Keyboard) Shortcut + + +To modify a keyboard shortcut, click on the button that contains a wrench, +and then enter the desired keyboard shortcut. To erase the shortcut, click on +the button with the icon to the right of the +change shortcut button. + + +Modifying a Keyboard Trigger + + +The Trigger tab for a keyboard shortcut. +Modifying a trigger for a keyboard shortcut. + + + + + + + +Window Action + + +Window actions contain several options: + + + + +Trigger When + + +This configures the particular window action that must occur for the +shortcut to be triggered. The following options are available: + + + +Window appears - +Triggered when a window is opened. + +Window disappears - +Triggered when a window is closed. + +Window gets focus - +Triggered when you switch to a window. + +Window loses focus - +Triggered when you switch away from a window. + + + + + + + +Window +This is where you define the actual window or windows the trigger applies +to. For more information, see + + + + + + + + +Mouse Gesture + + +A mouse gesture can be changed by clicking the Edit +button below the area that displays the mouse gesture, which will open a window. +Hold down the &LMB; and draw the desired mouse gesture in the area provided. +The gesture will be saved when you release the &LMB;. + + +Modifying a Mouse Gesture Trigger + + +The Trigger tab for a mouse gesture shortcut. +Modifying a trigger for a mouse gesture. + + + + + + + + + + + +The Action Tab + +The Action tab is where you configure the action that +will be performed when the shortcut is triggered. There are several types of +actions that have different configuration options: + + + + +Command/&URL; + + +When using a Command or &URL; is a trigger, a text box is provided where +you may enter the command to run or &URL; to open when the shortcut is triggered. +You may also click the Browse button to the right of the +text box to open a file selection dialog in which you can select a file on your +local or a remote system. + + +Modifying a Command Action + + +The Action tab for a command. +Modifying a command action. + + + + + + + +&DBus; Command + + +The following options are provided that allow you to specify a &DBus; +method to be performed: + + + + +Remote application +The service name of the remote application the method is to +be performed on, for instance org.kde.kate if you wanted +to perform it on the &kate; Advanced Text Editor. + + + +Remote object +The path to the remote object the method is to be performed on, +for instance /Document/1, if you wanted to perform it on +the first document opened in &kate;. + + + +Function +The name of the &DBus; method to be called, for instance +print if you wanted to print the document. + + + + +For more information on &DBus;, see the +&DBus; +Introduction on &kde; TechBase. + + + + + +Send Keyboard Input + + +At the top of the Action tab, there is a large text +entry where you may enter the keystrokes you wish to be sent when the shortcut +is triggered. + +Most keys contain a single character, and to enter them here you just +enter that character. For instance, to type an A, just enter +A. Some keys have longer names, and you can also use +those names. For instance, to press the &Alt; key, simply enter +Alt. + + +Individual keystrokes should be separated by a colon +(:). For instance, to type foo, enter +F:O:O. + +Keys that need to pressed at the same time should be separated by a plus +sign. For instance, to press +&Ctrl;C, enter +Ctrl+C. + + +Remember, you must enter keystrokes here exactly as you would on a keyboard. +To capitalize letters, you must enter the &Shift; key. For instance, to type +Hello, enter Shift+H:E:L:L:O. + +This also applies to special characters. For instance, to type the +at-sign on the U.S. English keyboard layout, enter Shift+2. + + + + +The action that is performed is dependent on the currently selected +keyboard layout. If you change keyboard layouts and trigger a shortcut, it +may have undesired consequences. + + +Beneath the keystroke entry text box, you may select which window the +keystrokes will be directed to. You may choose from the following options: + + + +Active window - +The window that is currently open. + +Specific window - +The window that you describe using the form below. For more information on +describing windows, see . + +Action window - +When using the Window Actions trigger type, enter the keystrokes in the window +that triggered the shortcut. + + + + +Modifying a Keyboard Input Action + + +The Action tab for keyboard input. +Modifying the keyboard input action for a shortcut. + + + + + + + + + + + + + + +Defining Windows + +Several areas of the module allow you to define a list of windows. They +all use the same interface, which contains the following options: + + + + +Comment +This is merely an informational text box you can use to explain +what the trigger applies to or save other useful information. It is not +actually used by the system for anything. + + + +Window List +Beneath the Comment box on the left is the +list of all window definitions currently present in the trigger. Simply click +on one to perform an operation on it. + + + +Edit... + + +Press this button to modify the currently selected window definition. A +new window is opened that allows you to edit it. This window contains the +following options: + + + + +Window Data + + +This is where you describe the window the trigger should apply to. + +At the top, there is a Comment field, which is +informational just like the one in the main Trigger tab. + +Three window characteristics are available: + + + +Window title - +The title that appears at the top of the window. + +Window class - +Usually the name of the application. + +Window role - +Usually the name of the &Qt; class that makes up the window. + + + +Each window characteristic provides a drop-down box, and a text box below +it. Enter the value you wish to test windows for in the text box. From the +drop-down box, select which kind of test you wish to apply. You can use +Is to require an exact match, Contains +to require that the text entered be somewhere inside the full value, or +Matches Regular Expression to use a regular expression to +define the match. You may also perform the inverse of all these operations. +Select Is Not Important if you do not wish for that +particular characteristic to be examined. + +The easiest way to fill in this information is to open the desired window, +then click the Autodetect button at the bottom of this +section, and finally click on the desired trigger window. All three window +characteristics will be populated with the information from that window, and +you can then adjust the settings as necessary. + + + + + +Window Types + + +This lets you restrict the match to a particular type of window. The +following options are available: + + + +Normal - +A regular application window. + +Desktop - +The main desktop is actually a special window all its own. + +Dialog - +A small window that is part of a normal application, such as a message box or +a configuration screen. + +Dock - +A small window that can be attached or detached from a main application window. + + + + + + + + + + + + + +New... +Create a new window definition. This opens the edit dialog +described above. + + + +Duplicate... +This creates a new window definition with the exact same +specifications as the currently selected window definition. It will open the +edit dialog described above so you may make further changes. + + + +Delete +Removes the currently selected window definition. + + + + + + + + +Settings + +When you first enter the module, or when you click the +Settings button below the left pane, there will be +several configuration options in the right pane: + + + + +Start the Input Actions daemon on login +This configures whether or not to activate the background +application that monitors for keyboard shortcuts and triggers configured +actions. It is enabled by default. + + + +Gestures + +Select this check box to enable mouse gestures. + +There are two options specific to mouse gestures: + + + + +Timeout +This specifies the maximum time interval during which the mouse +gesture will be monitored and recognized by the system, in milliseconds. + + + + +Mouse Button +This specifies the mouse button to be used for mouse gestures. +Usually, 1 is the &LMB;, 2 is the +&RMB;, and 3 is the middle or wheel button. If your +mouse has more buttons, you can also use those instead. + + +Button 1 is unavailable, so mouse gestures do not interfere with the +normal operation of your system. + + + + + + + + + + + +Settings + + +The Settings screen. +Editing Custom Shortcuts settings. + + + + + + + +Credits and License + +Special thanks to Google Code-In 2011 participant Subhashish Pradhan for +writing much of this article. + + + +&underFDL; +&underGPL; + + + +
    + + diff --git a/doc/kcontrol/khotkeys/manage-export.png b/doc/kcontrol/khotkeys/manage-export.png new file mode 100644 index 0000000000000000000000000000000000000000..20a6fd89aad911af0e95f8db42578df9945f8446 GIT binary patch literal 68149 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

    XSqFK3(IQ8 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/mouse/CMakeLists.txt b/doc/kcontrol/mouse/CMakeLists.txt new file mode 100644 index 0000000000..582e99f55c --- /dev/null +++ b/doc/kcontrol/mouse/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/mouse) diff --git a/doc/kcontrol/mouse/index.docbook b/doc/kcontrol/mouse/index.docbook new file mode 100644 index 0000000000..ba8b0d8fce --- /dev/null +++ b/doc/kcontrol/mouse/index.docbook @@ -0,0 +1,472 @@ + + + +]> + +

    + +Mouse + +&Mike.McBride; &Mike.McBride.mail; +&Brad.Hards; &Brad.Hards.mail; + + + +2013-12-05 +&kde; 4.12 + + +This is the documentation for the &kde; &systemsettings; module that configures mice and other pointing devices. + + + + +KDE +Systemsettings +mouse + + + + +Mouse + +This module allows you to configure your pointing device. Your +pointing device may be a mouse, a track ball, a touch-pad, or another piece +of hardware that performs a similar function. + +This module is divided into several tabs: +General, +Advanced and +Mouse Navigation. +There may also be one or more additional tabs if you have a Logitech mouse +or trackball, providing access to special features. + + + +General + + + +Button Order + +If you are left-handed, you may +prefer to swap the functions of the left and +right buttons on your pointing device by choosing the +Left handed option. If your pointing device has more than two +buttons, only those that function as the left and +right buttons are affected. For example, if you have +a three-button mouse, the middle button is +unaffected. + + + + +Reverse scroll direction + +With this check box selected, the scroll wheel (if any) will work in the opposite direction (so that if rolling the top of the scroll wheel towards you previously causes a scroll down, then it will now cause a scroll up). This may be useful to handle a unusual setup of the X server. + + + + + +Double-click to open files and folders (select icons on first click) + + If this option is not checked, icons/files will be opened with a +single click of the left mouse-button. This +default behavior is consistent with what you would expect when you click +links in most web browsers. If checked however, icons/files will be +opened with a double click, while a single click will only select the +icon or file. This is the behavior you may know from other desktops or +operating systems. + +This option can be changed in the configuration dialogs of &dolphin; and &konqueror; +on the Navigation tab as well. + + + + + +Single-click to open files and folders + +This is the default setting for &kde;. Clicking once on an icon +will open it. To select you can drag around the icon(s) or &Ctrl;Right click, +or simply click and hold to drag it. You can also enable automatic selection of icons using the Automatically select icons check box, discussed below. + + + + +Change pointer shape over icons + +When this option is checked, the shape of the mouse pointer +changes whenever it is over an icon. + +This option should be checked in most situations. It gives +more visual feedback and says, in essence, if you click here, something +will happen. + + + + + +Automatically select icons + + +As noted above, if you have Single-click to open files and folders selected, you can select icons by dragging around them, or by using &Ctrl;Right click. If you routinely need to select icons, you may want to enable this check box, which will allow icons to be selected automatically by pausing over the icon. The Delay: slider determines how long is required before the automatic selection takes effect. + + + + + + + + +Advanced + + + + +Pointer acceleration + +This option allows you to change the relationship +between the distance that the mouse pointer moves on the +screen and the relative movement of the physical device +itself (which may be a mouse, track-ball, or some other +pointing device.) + +A high value for the acceleration multiplier will lead to large +movements of the mouse pointer on the screen, even when +you only make a small movement with the physical device. + +A multiplier between 1x and +3x will works well for many systems. With a multiplier +over 3x the mouse pointer may become difficult to +control. + + + + +Pointer threshold + +The threshold is the smallest distance that the mouse pointer must +move on the screen before acceleration has any effect. If the movement +is within the threshold, the mouse pointer moves as if the acceleration +were set to 1x. + +Thus, when you make small movements with the physical device (⪚ +mouse), you still have fine control of the mouse pointer on the screen, +whereas larger movements of the physical device will move the mouse +pointer rapidly to different areas on the screen. + +You can set the threshold by entering a value into the edit box or +by clicking the up/down arrows to the right of the box. + +In general, the higher you set the Pointer +acceleration value, the higher you will want to set the +Pointer threshold value. For example, a +Pointer threshold of 4 pixels may +be appropriate for a Pointer Acceleration of +2x, but 10 pixels might be +better for 3x. + + + + +Double click interval + +This is the maximum amount of time between clicks for &kde; to +register a double click. If you click twice, and the time between those +two clicks is less than this number, &kde; recognizes that as a double +click. If the time between these two clicks is greater than this +number, &kde; recognizes those as two separate +single clicks. + + + + +Drag start time and Drag start +distance + + +If you + +click with the mouse +drag within the time specified in Drag start +time, and +move a distance equal to or greater than the number (of +pixels) specified in Drag start distance + + + +&kde; will drag the selected item. + + + + +Mouse wheel scrolls by + +If you have a wheel mouse, use the spin box to determine how many +lines of text one step of the mouse wheel will +scroll. + + + + + + + + +Mouse Navigation + + +This tab allows you to configure the keyboard number pad keys as a mouse-type device. This may be useful when you are working on a device without another pointing device, or where you have no other use for the number pad. + + + + + +Move pointer with keyboard (using the num pad) + + +To enable keyboard mouse mode, you need to select the check box labeled Move pointer with keyboard (using the num pad). When you do this, the other settings will become enabled, and you can customize the keyboard pointer behavior further, if required. + + +The various keys on the number pad move in the direction you would expect. Note that you can move diagonally as well as up, down, left and right. The 5 key emulates a click to a pointer button, typically &LMB;. You change which button is emulated by using the / key (which makes it &LMB;), * key (which makes it &MMB;) and - (which makes it &RMB;). Using the + emulates a double click to the selected pointer button. You can use the 0 key to emulate holding down the selected pointer button (for easy dragging), and then use the . to emulate releasing the selected pointer button. + + + + + +Acceleration delay + + +This is the time (in milliseconds) between the initial key press and the first repeated motion event for mouse key acceleration. + + + + + +Repeat interval + + +This is the time in milliseconds between repeated motion events for mouse key acceleration. + + + + + +Acceleration time + + +This is the time in milliseconds before the pointer reaches a maximum speed for mouse key acceleration. + + + + + +Maximum speed + + +This is the maximum speed in pixels per second the pointer can reach for mouse key acceleration. + + + + + +Acceleration profile + + +This is the slope of the acceleration curve for mouse key acceleration. + + + + + + + + + +Logitech Support + + +Some Logitech USB mice support special features, such as switching to a higher resolution, or +providing cordless status. If &kde; was built with libusb support, then you will get an additional +tab for each supported mouse that is plugged in. + + + +The supported devices are: + + +Wheel Mouse Optical +MouseMan Traveler +MouseMan Dual Optical +MX310 Optical Mouse +MX510 Optical Mouse +MX300 Optical Mouse +MX500 Optical Mouse +iFeel Mouse +Mouse Receiver +Dual Receiver +Cordless Freedom Optical +Cordless Elite Duo +MX700 Optical Mouse +Cordless Optical Trackman +Cordless MX Duo Receiver +MX100 Laser Mouse +Receiver for Cordless Presenter + + + +Not all devices support all capabilities (typically cordless devices do not +provide resolution switching, and of course only cordless devices support +cordless status reporting), so some parts of the tab will not be enabled for +some mouse types. + + + +If the mouse supports resolution switching, the Sensor Resolution +radio button group will be enabled, and you can switch from 400 counts per +inch to 800 counts per inch and back. If you use +800 counts per inch, the same physical movement of the mouse +will cause a greater (roughly double) amount of motion of the cursor. This tends +to be popular amongst gamers. + + + +If the mouse supports cordless reporting, the Battery Level +and RF Channel widgets will be enabled. You can only change +the RF Channel if your mouse has two channel support. + + + + + + +
    diff --git a/doc/kcontrol/paths/CMakeLists.txt b/doc/kcontrol/paths/CMakeLists.txt new file mode 100644 index 0000000000..526a61bc25 --- /dev/null +++ b/doc/kcontrol/paths/CMakeLists.txt @@ -0,0 +1,2 @@ +########### install files ############### +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/paths) diff --git a/doc/kcontrol/paths/index.docbook b/doc/kcontrol/paths/index.docbook new file mode 100644 index 0000000000..eecb4c76ab --- /dev/null +++ b/doc/kcontrol/paths/index.docbook @@ -0,0 +1,91 @@ + + + +]> + +
    +Paths + + + + +Michael +Anderson + +
    nosrednaekim@gmail.com
    +
    +
    +Anne-Marie +Mahfouf + +
    annma@kde.org
    +
    + +
    + +2009-11-17 +&kde; 4.4 + + +KDE +KControl +desktop +paths + +
    + +This is a module to configure essential paths for the &kde; desktop. + + + +Configure some &kde; paths + + + + + + Configure some &kde; paths + + + + + + + +Desktop path: +The Desktop folder contains all the files which you see on your desktop. The default path is usually ~/Desktop but you can change here the location of this folder. + + + +Autostart path: + +The Autostart folder contains applications or links to applications or scripts you want to start whenever &kde; starts. You can change the location of this folder if you want to. + + + +Documents path: +This folder will be used by default to load or save documents from or to. + + +Download path: +This folder will be used by default to save your downloaded items. + + +Movies path: +This folder will be used by default to load or save movies from or to. + + +Pictures path: +This folder will be used by default to load or save pictures from or to. + + +Music path: +This folder will be used by default to load or save music from or to. + + +If you change a path and click Apply a dialog appears where you can choose to move the content to the +new folder or use the new folder without moving the files. + +
    diff --git a/doc/kcontrol/paths/paths.png b/doc/kcontrol/paths/paths.png new file mode 100644 index 0000000000000000000000000000000000000000..eff8756d5c691363570166e2ec611d24f4dafa82 GIT binary patch literal 11152 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
    2O>&r* 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/powerdevil/energy.png b/doc/kcontrol/powerdevil/energy.png new file mode 100644 index 0000000000000000000000000000000000000000..1998a57f36ee4964459dd1b5f924a353cb7d09f6 GIT binary patch literal 68729 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/powerdevil/index.docbook b/doc/kcontrol/powerdevil/index.docbook new file mode 100644 index 0000000000..a99dc9bf0c --- /dev/null +++ b/doc/kcontrol/powerdevil/index.docbook @@ -0,0 +1,317 @@ + + + +]> +
    + +Power Management + +&Dario.Freddi;&Dario.Freddi.mail; + + + +2013-08-18 +&kde; 4.11 + + +KDE +System Settings +powerdevil +power management +laptop power + + + + +PowerDevil, a Power Management Daemon + +This module is a configuration tool for managing Power Management in &kde;. It is a configurator for the PowerDevil daemon, that you can start or stop from the Service Manager module. + +Through this module, you can define your computer's behavior in various situations, allowing you to save as much energy as possible. + + +Powerdevil works with Solid only and it's integrated in your desktop. You won't even notice it is running, apart from notifications. Moreover, Powerdevil checks your system capabilities first, so you'll see only options available for your system in this module. + + +Note that PowerDevil does not poll your system. This means that it will not waste energy while trying to save it, as some other power managers do. + +Energy Saving Settings + +This page shows the actual energy saving settings. If a battery is detected you have three tabs with different settings for On AC Power, On Battery and On Low Battery profiles. + + + +Energy Saving Settings + + + + + + Energy Saving Settings + + + Energy Saving Settings + + + + + +There are a lot of options you can configure for each profile: + + + +Screen Brightness + +Sets the screen's brightness using a slider. + + + +Dim Screen + +If checked, the display will be progressively dimmed, until reaching +brightness 0, in the amount of time you specify in the spin box. + + + + +Screen Energy Saving + +Here you can define power saving for your monitor. +The check box defines if DPMS support should be enabled or disabled. +If you choose to activate it, set the timeouts in the spin boxes below. + + + + +Suspend Session + +Suspends the session after the selected time to the status +Sleep, Hibernate, +Shutdown or Lock screen. + + + +Button events handling + +Select actions to perform whenever the laptop lid is closed or a button is pressed. + + +Run Script + +Activate this option to run a custom script when a profile is loaded, unloaded +or after a given amount of time. + + + + + + + + +Activity Settings +Here you can configure the Power Management settings per activity. The settings for each activity can be configured on its own tab. + + +Activity Settings + + + + + + Activity Settings + + + Activity Settings + + + + + + +Don't use special settings + + +Use the settings defined on Energy Saving page. + + + + +Act like + + +Here you can choose a predefined profile from the drop-down box: PC running on AC power, PC running on battery power or PC running on low battery. + + + + +Define a special behavior + + +If this option is chosen, a special behavior for activity can be chosen. If this is a presentation activity, you can check the Never shutdown the screen and Never suspend or shutdown the computer boxes. It is also possible to define the time interval for the computer to switch to a suspension mode for the power saving activities. + + + + +Use separate settings (advanced users only) + + +This option allows users to choose the detail power saving settings for a separate activity. The settings are similar to the settings from the Energy Saving page. + + + + + + + +Advanced Settings + + +Advanced Settings + + + + + + Advanced Settings + + + Advanced Settings + + + + + +Battery levels + +These items are only displayed if a battery is detected. + + +Battery is at low level at + + +Here you can set the percentage after which the battery will be considered low. + + + +Battery is at critical level at + + +Here you can set the percentage after which the battery will be considered at critical level. + + + +When battery is at critical level + + +Defines the action that will be done when battery reaches the critical level. + + + + + + +Events + + +Lock screen on resume + + +When this box is checked, every time the PC gets suspended, the screen will be locked when resuming. You will be asked for a password when resuming from sleep state. + + +Never prevent an action on lid close + + +When this option is selected, applications will not be allowed to inhibit sleep when the lid is closed. + + + +Configure Notifications + + +If you want a deeper control over your notifications, you can refine them by clicking this button. + + + + + + + + + + + + +PowerDevil Runner + +PowerDevil can be manually controlled through &krunner; (&Alt;F2). This makes changing profile, brightness, governor and more much easier and faster. The runner has various keywords you can enter to access its functions + + +Runner Keywords + +Here comes a list of keywords you can enter in &krunner; to perform PowerDevil related actions. + + +Power Profile + + +You can manually choose a profile using this keyword. All available profiles will be shown in form of &krunner; matches. + + + + +Screen Brightness + + +You can control screen brightness through this keyword. In this form, some &krunner; matches that let you do some common actions will be shown. If you enter a value after the keyword (⪚: Screen Brightness 50), the brightness will be set to that value. + + + +Suspend + + +You can suspend your pc through this keyword. Available suspend methods will be shown as &krunner; matches. + + + + + + +
    + + + diff --git a/doc/kcontrol/solid-actions/CMakeLists.txt b/doc/kcontrol/solid-actions/CMakeLists.txt new file mode 100644 index 0000000000..44950ff5cf --- /dev/null +++ b/doc/kcontrol/solid-actions/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/solid-actions) diff --git a/doc/kcontrol/solid-actions/add-action.png b/doc/kcontrol/solid-actions/add-action.png new file mode 100644 index 0000000000000000000000000000000000000000..67b4ea98b0511585db4740a35d190866ba3bfa5a GIT binary patch literal 13822 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 Z*@~#gjUGm10TBNV1sPT8dP&pZ{|}-j+u;BJ literal 0 HcmV?d00001 diff --git a/doc/kcontrol/solid-actions/edit-action.png b/doc/kcontrol/solid-actions/edit-action.png new file mode 100644 index 0000000000000000000000000000000000000000..aa2731b2c77aaaf69e23f6b0667fc7499f12fc06 GIT binary patch literal 49373 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 Hr=b52o600- literal 0 HcmV?d00001 diff --git a/doc/kcontrol/solid-actions/index.docbook b/doc/kcontrol/solid-actions/index.docbook new file mode 100644 index 0000000000..54da3eed85 --- /dev/null +++ b/doc/kcontrol/solid-actions/index.docbook @@ -0,0 +1,222 @@ + + + +]> +

    + +Device Actions + +BenCooksley +&Anne-Marie.Mahfouf; + + + +2013-12-05 +&kde; 4.12 + + +KDE +System Settings +Solid +actions +devices +hardware + + + + +Actions for new devices + +Introduction + +This module allows you to set up the actions you want to associate when +you plug new devices. + + +Screenshot of the Device Actions Manager + + + + + + Screenshot of the Device Actions Manager + + + + + +You will see listed all of the possible actions that are available when +devices are plugged in. +Please note that they will only be available under certain conditions. + + +Add + This will ask you to supply a name for your new action, then will open that +action for editing. + If you do not supply all the required details in that dialog, then your +action will be deleted. + + +Edit + This will allow you to change the Name, Icon, command to execute + and the conditions the action must match to be shown. + + +Discard / Cannot be deleted / Remove + This will do different actions, depending on if it was supplied with your +system or created by you. + You can only discard changes to system wide actions, if there are no changes +then these actions cannot be deleted. + User created actions are completely removed, including all changes. + + + + + + +Add Action + + +The Add button brings you a dialog to enter the +new action name. + + + +Screenshot of the Add Action dialog + + + + + + Screenshot of the Add Action dialog + + + + + +The action name should correctly describe the action. After entering a name and +clicking OK, the Edit Action dialog will show to allow +you to set up the action properties. + + + + +Edit Action + +This dialog allows you to change the settings of the action you +selected. + + +Screenshot of the Edit Action dialog + + + + + + Screenshot of the Edit Action dialog + + + + + +This includes the icon, the action name, the action command and the various +parameters. +You can change the icon by clicking on it. +The parameters are displayed in a +tree, the top item having to be true in order for the action to be shown. + + +Edit parameter + + +Parameter type + +This controls what can be contained inside it, or +what matching is performed to check if it is true. + + +Property Match + +Compares the specified property of the Device (using +Device type and Value name) and using the evaluator, compares it against the +text provided. + + + +Content Conjunction + +All sub-properties of this must be true for +it to be true itself. + + + +Content Disjunction + +Any sub-property of this may be true for it +to be true itself. + + + +Device interface match + +Checks to see if the Device can be +classed as the selected Device type. + + + + + + + + +Device type + +These are the possible device types supported by &kde; on +your system. +They are used in both Property and Device interface matches. + + + + +Value name + +This is a list of all possible property names for the +selected device type. +It also provides the selection of the value evaluator (which is either +Equals or Contains), and allows +entry of the text to be compared with. + + + +Reset Parameter + +Reverts any unsaved changes you have made to this parameter. + + + +Save Parameter changes + +Saves the changes you have made to the parameter. + + + + + + + +
    + + diff --git a/doc/kcontrol/solid-actions/main.png b/doc/kcontrol/solid-actions/main.png new file mode 100644 index 0000000000000000000000000000000000000000..19c91c6abbf90dc399328e8b94929fb64ac3a54b GIT binary patch literal 65245 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 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/solid-hardware/CMakeLists.txt b/doc/kcontrol/solid-hardware/CMakeLists.txt new file mode 100644 index 0000000000..cf7a9a2323 --- /dev/null +++ b/doc/kcontrol/solid-hardware/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/solid-hardware) diff --git a/doc/kcontrol/solid-hardware/index.docbook b/doc/kcontrol/solid-hardware/index.docbook new file mode 100644 index 0000000000..58ed17d11c --- /dev/null +++ b/doc/kcontrol/solid-hardware/index.docbook @@ -0,0 +1,62 @@ + + + +]> +

    +Information Sources + + +BenCooksley + + + +2012-11-17 +&kde; 4.10 + + +KDE +Systemsettings +hardware +backend + + + + +This &systemsettings; module allows you to change the order of the backends used by Solid to +retrieve information about your hardware, and manage its network connection, +bluetooth and infrared devices if present. None of these backends can be used directly by the user. + +To use ⪚ a different network management backend, select it, and move +it up to the first position using the arrow buttons next to the list. Then the +Apply button will be available. + + + +Network Management Backend + +This is used by &kde; applications to determine the status of your computers +connection to the Internet and other networks. It also allows them to retrieve +information such as the current configuration of your network cards, and to change +their configuration if permitted. + + + +Remote Control Management Backend + +Used by &kde; applications to handle input from devices such as infrared remote controls. + + + +Modem Management Backend + +A &DBus; interface to communicate with mobile broadband (GSM, CDMA, UMTS, &etc;) cards. + + + + + + + +
    diff --git a/doc/kcontrol/splashscreen/CMakeLists.txt b/doc/kcontrol/splashscreen/CMakeLists.txt new file mode 100644 index 0000000000..81b5f77a7e --- /dev/null +++ b/doc/kcontrol/splashscreen/CMakeLists.txt @@ -0,0 +1,3 @@ +########### install files ############### +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR kcontrol/splashscreen) diff --git a/doc/kcontrol/splashscreen/get-new-theme.png b/doc/kcontrol/splashscreen/get-new-theme.png new file mode 100644 index 0000000000000000000000000000000000000000..dc631ed73b6f8a17a0e1aef6f0d9bdbbd8031559 GIT binary patch literal 67741 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 z%0D%|{{*h1GkiYqq4f_3#BTrTauV$oa(*Z)LBO~8g#J6E8v_9h$E2{q&GE?bi+D{G)DBj@g|Ah*5Am9iK7+8Ylm`etG23U)c|b1q zOL}xmZ{U8S@Nq#QH(j}RX_BKgFfPg7`RCm+XP;C56BsWoQP<}86vN7D@UzerQFH-6 z0ygN-u;XPoC_==wn;qLf@}jR438&;GY*VkfCR=0dz7Afsla1UHKu0-W=R6Fx{p7YN0+C0VW%g!XP1t-{i5)zeG#aa`hvYLm3#A4(#Ag+_VL<0O*e`XL5o z_ot3+R5BiXzkFDPjbeB=J9L*@m`VtDGn}flZ=sqoRyOW!-0tr#^B6kVB?KtvPx5@d z;{Iz@ca>_Bi@#e6qUwHwi~{c+Tom;3Z`$+oV+gV5V*uvcnPbpD6#8iTVe3!Vt)ZIA zvT77dBW}AbxR=TJNrk`2>t`fsy8=foHlM>4EN;4DMMAsz9tul8cWJr^615@kcK^^!a+ z*`Bh%=jK>)TmFxNnLrj2R|3yBMk)SoR9vrvYlHKlNJLAT!LGL$%1fQfUi@gx9|X}O zP1cTv!cvYX60(w@+CWKZNv@Q1Pg*)Q&?rYchnbt@!a-2YeBt2NAhN;8n20?haH>>( ztQY_eRyhBNFM|)I$lXQDR{!O!FW~Nv2-G&GyZ&ePX2(*MW`plGzt7@o{8Y|9ltKTK z=r4@8t;_6`fPWId11)~{u8n9QnM>#whX1ahUY~zY=^+0J1OIO^rvk|veixP&`nPDo z{!@7T-!h~0Z=0b1?)Kjei2u8^$>#=v+6@1FZupeKcn;qAQUj#vPV(Q6M+LO6IrURR zo(~2E1c3kVHN)io2knUd{(czHpn&D5;fX4`Kl>jA|F#%q%nGt!F6e&T=+V;FCzFbZ zr0CW3R?}MJy%Zq&_YL5qI}+{hvub29aiyiD^eOOC@+;39YPx~>9vi+g|9%QKPHN(p zfShL#xj30t&yxavA)^T@e3fkKF2C^>xoiEb{r9t&SsCHkJbff3>vkwIQ~Ik8Pn=6u k{`Ux(ZPcpjh>uK)l5 literal 0 HcmV?d00001 diff --git a/doc/kcontrol/splashscreen/index.docbook b/doc/kcontrol/splashscreen/index.docbook new file mode 100644 index 0000000000..0136bd969d --- /dev/null +++ b/doc/kcontrol/splashscreen/index.docbook @@ -0,0 +1,117 @@ + + + +]> +
    +Splash Screen + + + +Anne-Marie +Mahfouf + +
    &Anne-Marie.Mahfouf.mail;
    +
    +
    + +
    + +2010-09-25 +&kde; 4.5 + + +KDE +System Settings +splash screen +theme + +
    + + +This module provides an interface to install and view splash screen themes. + + + +Here's a screenshot of the splash screen manager + + + + + + The splash screen manager module + + + + + +On the left you can see the list of already installed splash screens. The current splash screen name is highlighted. +On the right is displayed a preview of the current splash screen with some information about it below the preview. + + +Get New Themes... + + +You need to be connected to the Internet to use this action. A dialog will display a list of themes from the http://www.kde-look.org website. Clicking the Install button associated with a theme will install this theme locally. + + + +Installing a new theme + + + + + + Installing a new theme + + + + + +This new theme is immediately available after you close the System Settings Add-On Installer dialog and is highlighted. The preview displays the picture. You need to click the Apply biutton to make this theme your current splash-screen theme. + + + + +Install Theme File... + + +Instead of installing a theme directly as above you might have a tarball of a theme locally that you want to install. Clicking on this button will open a file dialog and you choose the tarball of the theme you want to install. The installer then unpacks the theme locally and makes it immediately available in the themes list. + + + + +Remove Theme + + +Removing a theme means removing the theme files from your disk. A message box warns you before doing anything and indicates to you what it will remove. Clicking on Delete in this message box will remove the splash screen theme from your disk. Clicking Cancel will abort the remove action. If you choose Delete, the theme is then no longer available in the list. + + + + +Test Theme + + +This shows you the theme and the associated icons as they will be displayed as splash screen when &kde; starts. Clicking on the splash screen hides it. + + + + + +
    + + diff --git a/doc/kcontrol/splashscreen/splash-main.png b/doc/kcontrol/splashscreen/splash-main.png new file mode 100644 index 0000000000000000000000000000000000000000..375455e9c17f6ca021968339ddfc50813297bcd5 GIT binary patch literal 66684 zcmaI-19)6*7Y2+@nx?TEH@0mzc4ON%CrM*BY|_|fn>4m<+qRwjyYF|-b?{@Z%-)&V zkC*SYCj6Vc1R@+R90&wLl#&!x0)alf0&icK55PB7epKwh4c0+Y(-{Op>iPGENTfx= z13`RbkP;PE@mM;^fY*sOC+xT9$Dk>pEI?n1rBYMmHYrm<3Qqh|?HwXbZ^LM2ybx)$ z)OjaeT)SwY6gBmQr6MrmOJQc$&#}YoOcyU6K8*92=hf@G+~$6*W81g&@z+M(aUcDA z*9ZNW{ipl)_p0MFWgV3sl#jx|U(3eJ#0I~&`;z`)J)0U-YJ40hSyb#jiJqSxrwK=l)*Oz~nALNl9v7zZ!{&^-}rx z2#bGGN!j;mxPpfZLBcQ1&gL@c0I4SW4=1(RnwY?Z&S!mDuQAx{D(7{Nb+~uXZ?$3v zJMKqkp!So*{{GE`3I6FJ9xA`>pt~tLfT=w;ela-d0<;jaNxB8p& z2M3DE-Pz)UTbD895>L&k6q>@UQg$8%zg3YZu*3mJC&aMi)NEC=nuO}8?pYM7p$vP-LD#s?y;$;fJUqNl zFPRnD*&QogUCYn-ROl1)cjxPb1O%OHM#C`tSKSAbpUlk6c6WER1=dK=*d6$0SLpN( zw-ek*6+4v?ugcjxIym_It4L+k*!1Agla23-3Kk56cr7;D+z=JUL1+5PfyTryD7 zg@)(psz4?ZlRn-=qrsrF$@QGnYH)20>8-k@g-=AJJ36z;-|;VU~!Jvd0K zUSTpU)%eqilNS)vy95O{YGiB!CbJvCH83L|-%7tZ`7teo+uhw;^Gk}k&|tm&s_1MU z0>WI?J4hW34Sj>rTSxKR@4BS9(`ETctY$bNucklYu2X-Z?2uqClMnjbmnRx+y&{PfU7y8yAZWn|0*0)!P%D?{oUZ9__z@?II4> z0FF4z5 zV(_JW$mM=UmrfBMnfnQK8p-EXkxOPT2J=tyHucC) zuHoTfkwamlhcMK5gaYz{6Fz?TvoC{U-a(mc-VY9U+oI0!;ygpr!w!8Wum#YtQm_T4 z1$|LcMFpLQZggANr6G#M3=Bv<{;wTFOID@3Djb28(F|!5las+~&hKwN`2}&yL9pl> zhkRJ*HLlBQci@eqChSX|c$;lGS28?wP zy)a#|J8|cc$4Z?^pWKnncz?zwq;>0szER0pnvZ98#%>5RxgO2HWBK;=JZ=crl0lB} z*%-*VxnV9dQj>#XC>ZRPTF4m%6=E3{YL64TLy?J}M0W+J1<8np|J0JZU;q6}I1C40 zQe9KC*<-l>d{>Ixv{Ley+s+Z;34T&hp`cVNiBd|YDI_ko5QSkA9WcqO$iAU}@{oNW zA@4tVRcc&rh9FaR-S+4f^END>o|g!zPzM+w7?3^aqnMDTq*R}q>9=|% zZVE*dQE18b+(7E~I0x?sU2Z2RE0NVxD5OTUuWmNLBEfn2939)n5E!Mrw#LU_6xhSu8&pW*?fiYWWZf6_*=DgixPQ5{s!C8u69?(D1#+^)q=8h(w%{8K zzX(;iXdts>&HhN7(g!A_$LDhvcKoU#_0jQB(;t|AaTCFN!mj}Z&`bG6MWKnc>_&Ss zXNf^UK}=}*u^jV4F03o6?yV@v{r?k{Eyk4|O^x8+Dj6{xb{DH>Sf4*X9Y@WBc!rOkAAgR8ZZ%+AN*dMx;&YOwn1sYR zB232?Yq3#t`@$&yt@Juy7&8}@M`u7V)kV?4!9xR=Ew*4LbSOY>SK5CY{%1nHkO8kt z|5Fm#dW-9^-PkItxdJUUweQPilES>2wWZD(csfr?WqP*OSS&brKaNS1C?Qv1zI-+kS0n~A9&Or)pnn8}1$&QpxrxqF9?|=StSUdA?ub)YYh6%0t zJ7k`XZDRnt1?-m4KXX%z8X2vAbM7;_sP)=>=H^WQgvS^xymOv+Z_vNi(4b$LU-&hr z`g3V`p`F=T%fuivhtg@v$_dKkLWJ=FEFg z$Y8cF&CwD0GMtff$dZjj`2gXSGwOePy7}Vj>I!2b@UU8+!pUk~cFbY3KvY^Ku|WRS zcQJ922}&2%cXg~#NmyG>&(p*8GO>Kw{%G_GtrWR6CgZ;i>4~_?A$Do~ZiaKCqoZcf ztuaGXt5{xM7CDTw>5DAZZ*4TZlq!{T{W{s2R@#(@&?mkt)?_S^g;jh1nd!eZpzuS~ zX$}q#E66Aq6EJ(^pwy*faB>K2#@pRahiM!eJxAz)1A@L6o~oo`a6m-sv#6Mn~2CRrbF zzCdlK!u~J#I5R!*0CTP>hhv;9D7)X;NF;kFBl#T#y3-6aiT4JL&MPyP&E0XZd=c?w z_+O77tMoq2!S>vHj(}$!J2|ZhwEh4y%qxtv$g+IdIyaDb5w)VfzJ?)G2 z?F)saTu2-3&qb$R%gh`H93v(#iXkkY5b~7c+DSh`h=egxd?JiOMgIY7c0opQm5oXW z^HuampT$jQHn9PWavmfUF~TGq>L=P7J0`=w*3ECt_nFRot(@8v2xze3t5>goc^?ak z_Rj=vHq+L*u|SQ`Kt%a}zHWTagBSky_n-7DA%^b~@l=SKN_!uydhZI^`S}-6`HdPqv6aVY$YkP2a zV$Q^BZ365@(i9}*)jW&+*-CXa3lRBYyFTm0N#?sjRANT51mzFNMm#=*id=q~F{QW0A`#T?S=i486oZ<$UzaJn#1|vHJ z49pbp#KpDUPbVsR$|Wqt44HeLwkh`gaXR37IZk!G+S;FDK4Ba;``57 z(JPQ3kTJzQS7Tr^IaZg^iqYpE*9!7Wr6ie_HyL560RtCQ3Ya-p6Z<&9Q_^^bb?jrzexq> zwVmeo`7FWk=ih6ytp*pjfX)L8^DdkKR!q zxln^Hp&ZoHLt(?QUHKJjXsR37ZW{NV_&RtWT|jSULF41VClbB(v-P&wTR&ADYIam6 zFlOHKE^`oZdCbUeH!5n_=pxJ4n?x6DN^5*~iAOHLsH^cSaM;GX-U`J2pCh`ml#wHf zY`H)2<?LNLEw%7T?P|suI@T%W=Cfl5U68;dwrV%m6-cB+fhI@I=o!h&?3NM_{x!O zV6W=}hO$wT?Qf}N#Cf=;I8`w-gEZgJE*V~`(=)$3G2C|hGr!%1lO1Ru909+N3jqQ} zC0_IEIKhRlEY%v6o@<4;_E&TTWsg2rA?|SNnlF^XLfCHSR##N~xiD3R(eiBn^FYwf zYs#Dx?_k|tITXjsEve%Uc_s2CkDlcNvI_*L!=jLPS%$2C^Oazqv=U`nrJz(rn}hWC zmB9Atxp7pDMN}~3E+?PT)7#|R8y#nhbhqwRi*vLi+SqVwfP|__aIRwlvzf>2F6#>> z`k9J()}qF?ZH(FH;JFc8&V}>1V<^Itd$OAHCKa*vqJ;)2mjg~#68{P&5Qqxt>q^r) z>k0SW?5*%)U2>TD0%7Z;92m@7nY`nXcYE{{+Gnq?et2JOnUK}?lNVFUSy6*QrMLB~ zdz8;wrib%rPZ=bg^`(P?omuU8#?ygCOMz$C7$vQ;r*A&1i0h|)*|whFcn??eJ2H_p zYV*)zueNPZw-^CiL=*ncp{=|>!jB@hK)xEmsc0DxrnJ1ICBYPGwx%UL91K*2G|5}g ziDIR;^ko*-xQTecotLvGljm{vmvUOrifG@ObI>tGhjdRUQ>xK ze|Y=en9|~z;_iIDLw@dX)(FUxY}QlerfK0gYnqgf`ufCSK;1Od4d)+Df+?!O_P@@g z7;^ZKIhJy4Cr4HI`6ylmaUqF(2bb*&B20q_h8gf6P~oI6!%sBGD}E5@qU&V8Yt9iH zl4cZ;^3)!FFCHz(Kqr3N9COe($G5=a>1XI2*1wktqaYAd@HT<)q8j%YeW^`N?7@M> zX6Gj>grQI^9%waQ9CZFKZMHLAAq*f;GTFyT?{TF2MO;zMcJ}+>xN``0uIX-JoKfgFyV)20<;C2vSmG^jEM@Qja(oiW_YH%<_Jfuvma$smEml;3<7nYZ;EiEV8 ziHL}@+j0~al+gF!yJ7JWt;+h&( zGO`83%#oofqwXhHcJ^7(&$wt#-0bZ9{I-)_!RA|AVN?tpZkM^iNtjh534?bh(b(A7 zL{OCd^Kfu*k~x3=#9edZk)ig z(ENtS!ipgE1$k$uuy+XbVara%a=krzT=Vl3f$%PNV&)&P-|#u7JLWKuB^0F*3I?rzcw^1WM>=ThIWU>ym%iceed8PBqa1A7#bRi zmJr*0*XRg5KRzxiFDHUpuh4dJakc-9Ihw*63O$%ZK)thL^8HsLc_QxBrMNxg?4Xmp z%;~S}5!ct);{mffdL7v-1^JfMgviCDt4)EL-z;5-|Xlczt~xBZmJ= zk}Mr%sg^dkwpP{lHYPL_8k&CyG%!BiUi>>Yv-8n;--HEh`b^9iL$O5;AgL&4Ypv6> zvjs&(`v(W2qF=f(FflW^9ODBCc8Tce=%oy=_vnYRC2XpV_9YnhvqO=S81*Norlw|Q zME{XK_=^8UXMcVXP0GiI-<+|9qrAwllrBoOsi?Q@a7UoMEhi|d66!5T!+sRSt{QwX#Ix->&HP0Fsuwc^M+}!_w zhJc_)0dHuj0LUHjGlVLd=0iP{j&$qE-dw}V5zbjXaNE_N!nGw_I-IZnQBuhEU3vy!>Vg*y0GvGnjzBd721 z_6{VPp^Z(sTQvp-2I)Q^j-bLP9;|*&r^fU$!=d3}()-hA8s^K3xV)F&``+PYW!4%R z#Vn9Lv=WPpi!V}MTK4wm6B8)klLHB&WyIg3qoZ!On5-E1@)h4%Na zw5w#JbJ8dK)z#3%Ub5*f*QzQ6Q$u&B1;hf0{7+AUwiFM#bRxPLS)r49{A1IQ$vHtz@Q&?B%a zfS9K`m*iD8f=CaLKr-ZNT`Nn%QGSf z8uFjv(6Uw73=6Tph(d>VWX`%wX7}OC@?O1@+b(hXWaUw`Itlu$14h8_pKB&`2JH1B zcO@Y!3kw&`hTmPD57WHO^I)O~SUl719)Hz=OA=QMxNM+vp&zPT)kP&^{Z;EAe zt)yilB8_e)OKWFr7}|ZnLMyU`QK!rGC7N+whO#O4HH$rRw|~^t?3l=U%HYOV(sxTO zbb(=7DDN%w=X^D^o2}=^n%&Qb@*>o#uI8=2Ki+aaD+tECa4Xdn%JPk6@|P`*jc3)* z+N@~&u{#ZF#_rb9y7#IYE7mMY(yE~cr40%Ud1_oF-IJCI(@`8H1)uZ!scdjpLWv=&`JQ?yu zlNP0A);bKow1k0GW-|WZONohziC};9^du)Q*vgrTQY*_4@M&roO=jNi>`a-QBw?}D z%5HdkelFXeoQwm2{8Cr7oxQNotgLlH_cK6>{qA=N$l2NHSy`R;qffU`F)=xKcuLJU za&mG=oVLZ+0|T!<0<1)HpDr+6xF-ah`Nrt|`J&CAFM_@;RaFWr2%kihl;TaDPg}wF zA)%r58gw*xjiLN8ScHUGnVEX3xBd~*B)RgIwzjR`-`jv?duX3c9vjd7OhiONis-NZ zA)(@(!U~>S$?y5amRg02yHkSO_C}$BWizCaU%Bt)Bdm2Dj&AjV4Cp%kE2d_C63~+K z$Hv=w=o>gUF7DhJV+{>lDfw+}ZKb8s!0?l1;>T6I;KLH2!-+G%JhGOl;qBpGFc&ry zd^^k!3=p7}1L#OkWWY#g{r_;;f8p9omGgLYfu;m5-fsBYE09S9F>>6yxVY@>?;qxw ziwA|0Q;wHu)T^z~(5$6p#ghOHl=EVA6GQg)D>Pb62K#?i0SHmCxKi0HjorD4IWR-V z&y@R@GcyKG2~p99$H(5jzSPmZ!8BzG<-Rwc=e5x>Uv?T6Qe#DPb8}^7<*Sy)qtmC` zbAYn%*MCN9YiT4~U+1cW;iqjm(qviK*i%34hn#Kgj7vzVVh-`wi1SG!sZ2?@!{Mh)JCtlDA4%!-K#3k#FP zC)ITrF!6l}{~X$#b2sUBUNU{?g8QSesi|+*sbm@oH3(q;9l^UXcIru75OodFL_Kc(ZqPlfLf-;hnMGZBiY} z55Bvyc5wLJ)Z_&gep|V?0K5QP8VyWYd9?7KjuRsCXeB)Y7L>x0lEpII`872OIvRAC zf`aYrW$JN$So1b&v;d=l9vIG0;bC9^i_51`XlwH#76uj{F=2`CuwW^fh20^cql?NgWmUf=1-SbpYIZ1mKFvQ{zdcpUj*&gaJP-NE&g(0JU!hWr&HcM{xKF0 z+`Rqy*(pb79)LcNvF3KK?T^el2Fe_5WpZ(3#FW*&VqBT>@4veU#VEw5WgyI)Z+HQ`6E|S*A#L zuFZn^@$vBTJgsTDE!phb|2hyq{@geGH-g9Iqt1)$MAQxYi%?~ZuSM*j38&pkgU2Na zcR_w(e3d7`C!m!d);`$ReP}hE*Ltp;TDeeETzqeDFG4-|p;Oyb%T~+kh}GGQQMV}{ zNQwcN3dbJQo3*g;8vu|Ks)F6m^`Z^p^}y`J!n*3}5+v?tE7Wu=0)krPSy*jev(kaW z=XThnM@=siIl+vrT#Vj!f2C`mGjv}(JpYlbhrjZ{^YDww$y#gk-i;-a@E0WLMnzRs z&y8+m-kT68c+8eRzOUnguPX1S?!S)OTeGJ#N=k_R<=x)~`m@sc-QPO=As6v#>{gq^ zM0V}gW>#l!Uy%_{@t=YtF)M~gye~HVJ+Mhny)t#)cGdOM?2;LE8XOL%3a+k1fD;F4 z>^rerPUW+%dpkc|Yz9IPd(fCZ-5f60?Y1|%(uSLu?~6)EI2)cW)l!z0u7TfQOO%Uf zK1Y}i>oq#gh`3 z@iwW%LsoxpZzE2hL$kcJwAW`4knBq7t_lb^{kVarmR3=79V3{*XZNR-5~1ehxf z>-=+_2rTdF>`q}&b+It2<{t0kxlZoQiTSVuZJJ-g8|uMZ1=D&{=e1;JHr2$8sW`lzFbf2gWhbl zW(7eA^GKz&m6b4)kXcLuB5dF^X!p9MS@-ogU1EQW1`tPurH&52QM2QNgN-s}BO@bi z?dR)pewm9Z$8kU>0eNa#_3|jCk_Qssry1(JNo*`UiM-yD2}?^_56uYp|38H^`Swb9 zVe?I2U*E^)^=fz6mg9IEVSB9=oW3#g!+E0Hb9$v#6io=Ub|;~(uApEqA_Donc?*=G z!1n=!&04N@JeWXveRah}%AtfRjGieNE?MBOtEHfc! z8K6J`J9Bx-=NvIiV5o{UPMxQ2=8H;~uK zvjx^*Y-MddU!^S}v{Q6$VQ+086FZ!zGPwikJ>DpuC#5h>gw435r5z=npoAkuVrps{ z930FRmrUOd#KEbfX21YtT*IMNpfa$#w;8Wh@}JusFiUw1mBgR-H?ABFJPtYY~mq==C|cSYDa zA_jdM6pBToogyL;t@(?f*b=N!bJo^A)<#hGWy~^7eCW~lx12|2c)9O>`+Jn@vd^*j9u%1cPTv3UyN7nVya{lLB85a?ZwWv$?Q0@u#K6bt`SJ;oGl<_m4_7`s zfd}|INFMH&-A9}u3^J`XH8zvOjs5hapE1tn4vx4DotYc;0BNwwDVR`V*sWcHWbyu8aJP0h`>WJ{xbK*~G0*rjFc;h`b=O7(AbBPG(2 zB4*#j!~_5$d~XO}jK=4^*=Thcfp zH%35SYz>o6P*9MQQ@wxO=ky#OrnHB2Qmy{d=f_>)i zzO>VppT9FzAoIxpCwFa|1oWZZ|7#2!2l(!!(c{vH=_W`iXZQAaK0;U;4^9ZEBCCUv z0cv*2%Ughj-rW2RF8UB7%?rd8)qb4zYyZ63-Q5bk)+JCZKuFLFFOVb#Y9<);+g>(0 zA+Loc+R9qRSxr+ntAiES0NbGK>|7(3k5dl}>;*kU38)r4YI^$7|Mm9faXU#ajAaum zfQxv%dwF!$1q`kQd^VgiP@c9FPU24Wj+Ro<=PFW-u4~j^cXskCFE20mHtR6uWM#2IPROtPpdR!53E2cSr+kCwbHT6dG6|YXP2avNHvb(hz?xEGIjy!J7#tkjA@ExfX@%|>pUCtF z%6TS&epxXANM2mgR5Ss9lke-()00>2`GSI_jZM^#AM7#P{V~=GU2}74^ojK-TCD{t z`9IJD(aoFPPL(3Z%han7K#id*kW8r~zc|#?Zm8+#UM@Dffl9ho?UUk$t-G82!ontH z6)n}ZsVO6ZrrC@aINM9b>_3eJ{9Y!`7+6@xcAe~|%XPNAE(a4pSmy->kDi>ZHZN5a zH8nL=R>~X7@XstAUEG~6TQRYKb}~)V!C(4sdSf8l#NIMC-7WRHW3{|1b(`JxMsUPX z+zXn1ep;Z*7%#~1U0PnYtxN~OUjlVNxw#~1MXF_Lw(D)Lz()%I6t33#hzPh|d^vD$ zPmcxI;`GTFlyvHsC#d)^UbqJNLZBs7nHycNM?zCzac_d*+UEUeWJYuJGcnQA-sk9w!*Knw`Y%iyS=)^vPPyj>Q-W>Vq#ykXWQ4LoYuyP60(fnET5v3KRRg$%A z!|}&_Y;(k8o}{!`NpUjf_1z|Bd|{cwwtj4V+Y)XZ6ZQ1;v=SKMCq#u>#U^>!5@GK`@qV#LcP}mh@e5`pI+W|KxG$*8{q>0Jnw+p2)(hW zr0T5(y6{Ft-TOB_5#W$Bh(3ImVs3{9O+tel3c7%<8%iI3FC7SGa2|~bU7jz*fkArG zqCpTQ9qIAE(D~=`Sjq976r{%8G#nE`{v9#)iMQ9z>XI0N{vF;g?s8Tz#rTNmNc7^; z3jEm9Pk4%LKwTAR>&eu4cB^sQznbn$vYJrqo)NqgYvIx-GVDO+k{tC!kc9UoJiacr z67JuBw<26skvm&A^hI_;?sykgbrgm`SZm=j*^XFlm)@Rlt>Rlg;x_+fU|l(UwAj>G z%k#VBrJBA9*2cV~rDI3_z&JshsOV{DK}2Ll@%S6HYgpv2>r|FP>P$&7*P!hbReZe0 zbni^T=lZo5w!XS!vrzX+!G=pY&R4|o##k^A56uz=P;olGqt`$Cn=9;OFoc>@{gN&n z7L8XpxcZ5wHX7SzgOEf`N20);&asdbeAqM3w#iK;`^`lfg!%o>eUwoPG$@esz4`B3 z-=KAtW9zPN-^ge&Yz|2wnXc@00-p<7UeC`SIBS(bMrJ6EHRvlF{$&Ku>OQyV@D|%> zeAHcA>|UJWCSpNN`nj-JGpQM_xcpqVuknMXXbD%8#r$^o8?Yt|l+cSBd8WQuc&mlT=SvG7RBNPQQ3BBbFyQwwZjaj(sTQihSjFxM4 zWo;Kz=IX|le)4$|21tIxlpCsZUyCeNS2M#vqmY(8>5X*mA-@W<;l_>R9;-W& z@C5TLr3jnVbRQl|)d1=D>4mm)e1f6FPv_LOMhNb8$Djyo0s1LmD~Gg^mg)2yoTMfuJ3lQVe!j6o^=jV z8ysJGr}8eASbJ*n-^lnLty5|Igd6DL)adAKmo+)_)tlcwOx8s;+o7S96&V}(BqRRp zPFDhnj>QKFJ3)0Y-x86O;d>O7Eo%w(Dp;GI4ZR)sM|?Y5%mA%0a^9JarU6@O*LIKk z%gcP<8;L*3^U5Hmw)YBFJzhoCRaF(so$?u+@Vffrb@g)0p>6l5YS>ecHJhwzT zxLdo~#uP_#kW^GfeXYrQbh}=}r=(7@az?}W_Jm7-$BJ-l2|6a)ewDY$_5R`x-?~V` zwto=*Rz!K}9haRmQctf*mO+)J5kUWPB3XBHH>Uf;dEpVvW&?)|X}Ve6m|Ux^%joeLGR1l-RuQhZ+PpI3Ny2@2tsa73ey!MSJQqDF0$d-f#e z+?uBT=YQ0WZ`kQ6y@} zhm)1r?A_bu5u(UmShE(CNI@GlTAV7Ot86SX5*0euGGm$xFIVBOmRc5s zA3Br&}f(X@GOn&3p7?& zHIw*`BBJH2VTbw6!m$_*9E9sS-XMlSUEt7|7XB+o@6UL;>mpmnrq?YDXI^Pm)|7eZPf(I+^UOhh z9~q`pxDV->W626=4*JjaP15yf=)KH^NsaZligV={=w zEN3683=L-4;XmwW3H)06oQQzVX1HEwn-gYnl0U~D*#V6hmwXP8Mu`lKyC&{~Yygen z=7?E}oZw$0J9~B0!px8@H57iTuLt-_kzsP76U5myYs5AXWEvJo*SP8q*-#=AY5{dD z@|-5s3`D(;C!U`0qWE*suF{fUPR>z8ky)EijR{OlLJFT8>vUKM*Z&^0_21Kn z3bXr_E7n8MM72#zqEnqkSU^h~IY=R^4u7LJPOG1dcb0|?*so_aXZ(VIQL#Owy(GyW z1KvogO^kyDKWK2UCH;`A{-pU0JH310gjD!R!x3qF$#gY_kCjUx;{$|dK<*v|+PhR_ z6D1nA9Ffsafw%#1wYT0!IL_LXskM-jT1yI(CAjWmi&<4sNzk{hr&I(u9v& z6DnRaFEO3NeEG{>9Md4J$lIpaQ}gi93J-^nR0!Tmi25!n?DC0U@m`eV&lpB{da$7I zl;~>qx0hSknmemBwFa~Vlw6ox;SWUqEAc#GYnPas-{?s+gy-R{`tJ}^2t(9ddxHiY z_e<;JwJc2n#OM*2_2;%>F&I?keVl*%{@f+EI}@*`!#Do>C;jy#kYr`^u^PWQ5XH@p zsVPTn-d8zo+no83L(GINs*r%*ZVW7B6+OJ?dVw^K^?V7M1d3=>tbfidXAvr)q=`*dugwBB_qfdg+MI zs5i!%ljaZ| zx&7}%nAg$6(`^Njlt4-_l_O?zOLto27)+Q@6AkonLUhl+%;uXH?q zVino3>Le>liq4ZE1$-NbU(rWa*%HK)j>%lEkBq;`FEv^3RsS&kI*Bs}1KDVNz_qUZ zjRAeydmMcl@e@)7wb#N|^9m(tG}Pg_fT|8CPjWdxp&eyPlI;OnrRJ(D@!&j+>d3?f zCqGYXkOc)YphNE|mZNh*6x3SHv_l}-rpf5n!BbX@fm$X0jklFHSc={_aw6pihMfk4 zfnV-iVq_}Id@q19A^jIWz9d#W zJ)dLKpsz!eZwZ*L3S?;EqGOplg>04>LL9sKN>*h*S&zkH#7K$!KBq?dy9a!8a=)7H zLBqV)Xopyc6`u+@d+QV9`w^90AcV1^HYHncNL6={y*_(4TJWf=lI|c6D$mGD+S7%+ z7vyjKuAvc@Qd@)2WkCO1%Qm1XWU%^s9C5}^^SrgKs-|VwImduRyKFSA~{%fj^WO;%cJwzY&kY-{^{KF|B5=c4Q&3e@osG z_35kq6OTB_9UCluG_pXvD9 zhuqjNd{MDxpHTiJXNXxf#yMSnb3tNAH5aHUxeBp9^$?Lnh)Pypzayx<=hGa=E-0wm zz2>*5&>C8>5_Q(#WNu)<;EN=A>m$_Ye&Kw@->mq>;95wY;=$x=kKAgKN!)^S2PGYH)}!JHRSUX z(@gP^Q9ggf3-!PY8?l#Y!o`N5v9_L7`5qh5d$oBrvIMBmM*tG(to*3_cuZv;@Bt zocNm`CyBLOQM-JjwOlH#ZCQsi(%VN99y!*T_i-9)xzo83y5^Q~%>1-O2qu)bdUOVBVD&BWXG5JjN@8gnuS+sz;kDLC8 zDWe_5`~mw&XKVi6fr<mxOawY5RkGSkLab|{{S?J%%B^mrsE~ER87!m*cPBRuq zHG@}^Xk3}h-jVSxkDcZZL2OiyT+oUKACItkZ^ZsHb0o~)opAw)3?Pg^y?h^4jy;DE zwHH2*Anx{a%{pfe)4KtMW23QIXoiK&QVLD^Is2U+1@AF3&IflDhYjSO?UZF@TzAy4 zHWQ>3b1n@3+*2Q4Kc?P~0QJE1`w@WpYj#TQor_rnyFvI4ab!G55FE)a$bt^11^#z_kLmEX%?@2qgCE$|MFzp8Swx zxacGFC6GDAQg6PF)GahCx3ZCZSyR5OQg|Lh-EMeZ8 zlptJf|1Owrd2@SfyVztpJCq3EI3oFhfzaPykM)rWxt*46>$|}bl1eo9_3q_*wRbP7 z)^ntjN3%YwtF=ypCxT2Qeu>g7UgZMJwJr|_NAt+O4T=hseW7=4H%7g$8(+VetjG=_u8A0RrK%DoPrjOmKzpa<6V;Ew#lobTEiHE zfeIfG3_!ub$jw(7nnFPFfix%2>?ioA5zLM<>9y;0z^AqME6(EqQ1A?`H&Z|!+ut9; z40Dp=H68M?Y!+7_eTg8qQ~>;d6HVg)ex;}htD~9o!4n+ zfZDqri&5|8)c(8m>k~477hxw5ZFO{TWBHsICp|VDS2pjZTC-mf>=KmP)>hEY>oj;? z4+%D(1%!t`)hL__^0E24cucVn5@g!gSINq;BO%HKi8ao`jb$v?I$n3A{y5G88;$$( zD-=$*gOWoAqyk3UA9wha5O7prI+t}`K1SSpQ>>3)Z%OriS@{?_q^z?K;btX{xNG8>#+`1J(dxMgY zkRX#pH#tC!1xHftdOW9X*C_UiXWw!e&3pcmcJ93ofVk)0^+4rG+u>ds!$OOuex##2 z`WqvKv9wf4YwI?8)9)MY<5jjZjbbCVUR`azK1;;Njm#)(XBE%m zx!JV%nz(#IEjH=$oD%((WqIOrxv}!-%+Pq%BJT70{eAzjs{P5r$BXkTsovX$$+1qS zFd2&kQQtxnMi%dm~Y=DU*<)L zhB^iYowv?$eteHb*;6jVetLdR(G-IvK>}c9L`43_orFTDtKz`SEl#Zpwdrgc0-rFr zRJBRt3Vx4^>@!V_cySfHl47|20C$L4tM&J{``HpsT$;{0UAIN&ae-z4ymxC}zLxg`K$Qyd?iNH}CnSN?`>-}+s_@FSAo8sAOB+m)w z0CIt+`gW~~HsB{-@K_8pC(+{hP^(4KB&$MvCzHmlcqQjRivE1bwf|T93;8G?`;UReho9fH0waG;5Cu@9LANak4B&iJKRxb-f z`(_PMRF+r+9Mq_bYSq{4XTeuOcbBm*&p69ImrKx;0)eaA4xee$e6AJY45Sl?WzhRD9mM}ao_*i-&pX*7 zo^l$AEwJUu-bu@mK#5&sC%HGKdk>0D3Z@qgJBtp!8dMF|s`70i zMRH*J-Gp$}y_#pU>j4#t{Rw9{BPM3;r3#$2z&hv)_WO{&8gM|JoXF8-tbEt(j$f&b zv}iPmx8sRzAKZ$5x32@2nffBeUX4O_^GRo)@NusvVZpeK63sJ9ul^f(WF7J=mZ~QJvN87I}IkddzH-Q{|}nJK{1eR zi!!!t+qP||W3yx1wr$(CZQHid@#Mal`G#F*W2p+^&nc#mQNqp?pyCmUfIebaZr*dl zE$PlOlCS2Qr=D-WujYF8xlr(R`xhFtK48-PQ zohXLIH6a`Zneun~g1yuO$PvQca{jlY96qjziX2DM$^UUKKqaDu!8FoDmEUjOIG#+k zlry)pQ;$;T|5` zOXKPw0?K@+D%47tm2K2OYV299N9gc9Zlm2lo!1Y~$jax3v0ZEIt=1z0cXMlN>fM_C z-#atS)E;Orv)30lZYH~DcXvbX=-%c>V=w3Rn*byGI(}nb?-{eVxPP|U0>g^h=s2YI z{T`RVB5rx@B<^)aW~gU4p8g>(5Y$5vs6J5O9_0>04G!1P`F#`nLb$*;7YI=?% zZ+Y#USNr+2Lph)4$F8l?`7lZhDz1ViF`E7?Tk}z#GeJk!kT`fzqp#&)JaA_da+n5+9Dww>B5GMx9#` zcb!B~G!;q%CL}Z_F;Xp7dUP9goYB3k=K9!q+>R9(XGUFk+xcp|?XbM{9PzBQ`O+vf z?s&dhPnMW2czZs`ELS1x}*Xk(ZHW*g!6f6 z#Mydyf=MqS%8sdPC}ahZAQAL&BG5h-1}?U=+n_Iz@O+Ve`Us3kSqdV4)%1^`SMioZ zF3m$&@%%o~SfA&uvD6vcXgHn>X7=w~8%ZYmU6*vGZrHIt&!c1LOJ1aBU+@#i8GJFF% zK_vT0b~xk>_v(~&U7_$K0DWXfKij+C)@EvIbkr{yQ_Vkz8?`%j!bIs_r-G@Y_`Y8C z>Jmf9LLX%5@(2*;h&M)KS?(w4dhZWES?smAh{YYVuRR~#&~$A8fbenkX5R&lXmlCW zBROsZs7A5q2!Qn5hAj#!8nWSC;_U_J*t9E4Wc1y4>PsCxjM)++@>)Gb-n!C1=KTyT z%Oe(+$a&4Pc1H=AgP3|x@%3J=uXQfYRH$0L_2djE$EmJ8Ej^{x-K2`1SdAgT04=!m z;Z;nWG8Ey22VBWlq1QzKi zQ;3xP6VrJCGIr+yASS?nxZuoiRk0OA^?2Fas_AWQkumF&O2(SzCqv$WS9X2(}68bAOdrK!gE6NTKf~Tj^AY$vI z@_Tx8Ke?ra#tIO^R&_nEpI7zJ#nTu7BsI{%6-1)$t_hdD3#LIjU@S?w^7@$QI_?H? zzb|`Vo?oOSCdq5sKI_HtE32zL$sq*~9=M;Elo!e~N)Q@866LEwf(A$;*s4AjbKjiI z%uY$s^$e*oB%$GQeDaj6(e=DE*>2ta72#gs!mzyF6H9Tro0`v*XYB~JU|{UIST&5! z%8DBg&ez6Ar^TZiO_!&0cbSryGdsj`H|O{j85&JjXm89l8=dC}3JP)6&eIk*xi_|# zcNdxIf^(89A?*mvU;laFJH{)L3}QqpHfl6B*4mrNt1r5Se0V8EcHmp3PED;D5}| zD`r;H1_SO&V!<(sM+(JS9VwXLh2uyC1Q{O-oPvbg$iFV;ev0s@tm^q@Zz*bRZfV(e zKacdb*LPN0Ug#Pf903Krhlm+?h0<#L8#9XKf8BzHeReiHWE=tUM+8no7}{t0Rnv$} zoa<})$7QgdCTaJh@IJsG0&-mh5udUwk%}?rOuM@@rMPk>!i&7Z>e;Oz;`~`kL^V{e z%QKm5=}9?BVx(F6t9)t>5EWzU$s&8ck%8%`#T$z_oS%YI(yz{xO1f&3iz#1yxc}*lNim)v`)en!W25++U^B^%_Xea-H zre25Y!pEw+9`AmaywA^_4_Pv#YSv`6leoE|MNywx_Sh*z5Qfy`B}|-7KmaD_q~V9A z?E_6UrLTRhta!|;s$xGTa3+V+MZ*^51(7aQ^9KRMa7{r<_Dl4|MHMy}6CyI=PXX+Z z;Zu#M7jeOw*-h7@xPzsd-WMei-`CS(@7r`{&BsG3IM{nBM+^uvB=P6UtBsBIUk=0b zghYA1{c&=%OwCP1q~l$wYvS}YTceRDRN+X=n=ESL_(7Q{;$P;sDl8~RnU+h zn11t>rX`DzuuB3a<+mJTK2G7Z?IRkiX!>+a{s!LdI0pie68%3_n2@g#E+G=Wr%6|4 z@-KLs@foW~xf5-b_wTV&-wX6yjX9L4>`miWh=Rg29%4j&6L3Z?EHM;WgiH}tPsbX% zBg<_kRR4`~VX|E5F1Z2QBHJ<)vJ?(Hktc7xfYjpKpfeo93+2scZ)@6mg!zskFv;#* zWO*J%DdK@nh)s=m?A?E(>^p9Uox5K#mmQI9)qhrIZ`DgGm>TbDgkKS{Oj~7IjXZ&2`^VE1aj0%S-*_v zj0J_8;0`n1eL+mgE^o8<&L**r1^u0l`6AWum?KmM&ktOLp+1mRCsWs!K46 zV0(?>U_m1xkg*Zdt&+#QXiDWv?hbm<%OnS9KI~FN|ziM_HF#B z9>2kO75Te^RRK={g*pd{IXP4^T&ErO?>6U2kw$pF{^8tf{FeM&`s_gY1qW_@enQO*qTx#wB})?rctCBY08uw znNgVHiU;PbRStq!q`IL51j2FrCYi*$Zj)Lk?91M-oNS(lPQ5amO642#QgNy2lVI zDYbH3PI-Cka`VcsXiErs$eaX30;oV3UXdZV`_%8m{cF_svvce4_k*(zcjLMH%CzY? zf7$$bdpphbMSe!4o>}dAX;zlwR84xt^R)7|-kvB`qt*NF+1befg+{;G*_IqK+#8oM zZr}`0pQ+Jow%Fcq#sDh8tj|aM`n;HV#o=zvXH2e2QS8Jl!p$3X<3 zs>WpzJv?S^rwN2w&x9HEchZ|RcWo`T-0&+@p$8&@AT40#<(Hv}9n15dh&O|Pi8cL9 z>A+BL8F0JtL`u!otW9!gg1r`ZqjrMzOi2?F0jEt@gwXaN*Qcu6hDWiwoZfA;xJxvf z@?)a%Hbs=vQ6koD3Dw0l(g&%VrUn8wYA0Z@Vy6#B!ll}6Tb|>)f&f)J%&7ctU4x51 z(T+KUphOIv2}aj7r~df0KS)>cwWOOnb?{$EN9acUsiGT2d|}|=pzvQp34M|H^(baIhvqVb8p0eT^3jWBI@T0aCF?sb@;H-dyLF-Qp$6 zX=$-PaY4GC8&r3`#^gHTFaQ_A$dKW#Drz=#8)7LwKSkTDv#zP2+m4gEJevVWaZxjL zjD-M7uAoffOwOPNAuaB0WCW=_MUu_ks|!1h{!_pzsa569^y?DhGuU7R**F_oEX6xfdO!gi8uZhO&O{Ps30uW&n++;W(F&sTs5(f7Y3-BW^Jb@ z98>*iZb|?1GQ5wBwnAqqFEdZCjF-#hJ#upM`SM-hTq#MRzQR29f-KPayUvxxUxyAT zj}PXwTHKcZ?}0tNtAw2ocN9c1PSN;K*x#?o6?{D8NaSve|7P}WTgB2WjoMI}p`2>E zy1ojY8@tbLyZ#pRG4=Jc!RVVO{Wq6tuNeR1vAMPeQHNrWwsngLP~dgjb@w+oueSR| zvs{vv@{-&2%G}0Ej`TrkP$A0T;56a+*Fh>PV_Z(i+37mP^35QFt`fxv$CV;gQOUpXG{=nG z`5s9Cp^sE{wRjXajWRK3BWk4}>d^)e1{yPPjlF|`nGQfC(1gd7U8QEDIh+6>RUbP{ zXlqFSPRsz?ccwHE<%f{uP5n6R2gAD50W~;%m4@UQ;-&JELj5pQHBFIJh7vi{TDvn` z2B?u-bJ-H=VcY4UJ1|TM5mve10YBSwlbS7j=u;wL41w4Wre)x62?i63(fmkd&x2`F z5VFkk@_#2+rF<}J_gbxp{knvDECV5TbrPD3g_aYTpnj)~hWEt^>;O3l>`qDTW(S|c zPT;U-lG1FIrt>{%>X!GaPC^zb$;s~!3ptDBdk-t}ketr>g)v`mJbegXpRO8bCz3yM z$i?zLZhLdXNII<_Po~2#Q0w^eqKma#B{>S#4s|s<&3N#SV96~GbiC7nQnRq3?vJOt z#p%pnfGn)#qPG=T#M&JPMWosEJ8D*n}VtB?>FgE07Eu_6Nk8CeU{BCVDh ziq7UKRjtvxg$R_J0xyD%Mh`F0`seoAaW=6Ue?M&P?UZIWb4yp1GL@hY`hI|w*(LGF zCMFt^ZEkOKr`&I;@KS}QC9RbsNsir2$2|YzyjGxNXFLK2NleClEw$zoPSOe{1wdq^ z&^I28%0mG_?p$4c|s|Df`vDM5ERW8p{C_e0j#hiEZ{?>(2KE-)hwY|h`1b$ zh4tG1{BsgfUG>M{A$|Ky*HJ7|C9I`Z0cCVbJKl#ZZ~{AStW24bQSFJX`lb9Iu^o+G zRS%|Wm!r%V^PsBdtj`^u0pUy9L3Bdbfj6f7al|Jk8Igemo9L z5LiYcm>AR*TWpM!Hkc4n+-c47nQ!}I)pk`Nir}iXJRxylW~#bzPIJhR0zVcC{bO@+ zM*(K6#OyCjl|*i+Vp=emw2Tq#Cnn%ve^{FWpFCTk*-NUE^n(wK!OO z1Irr#wC;roq~&?Vjd&Ye9ZzVCTt((hg9D8BoiQ6zzRZNjxIM;ipwMpUFG8A7@_b6E z&nUx)U2~Do@{Y17>W}k7J4uo_O&5@Y%y)>ziOh!M4i@TpCO6{Tj^Se z1TngJ;mH)*NH=&Ko;6FY-tT5;KBs=$pT}16Y^Q@uY&Kn|`QY8&;}vULE1;nH{rXz% zpI%*$^J4CsHetHXf%NAZq4J^6myy&JCsJj)zo4KauhFhkHLgZ-oH^jt=rYJ=Kn{m+n-0EMvVK8fU=#v&0B#QEup#z#1#PYb&{oEh zmZR`M#mEfNbCQ3aMPqZevplYrgJqlj**i2w6Xd$Y$SqX5#-XV)_6*lQkdq@Q$%DBC z^DQ@P!u#=(aUU9ukPng1ismE>955{iRSU!0aAve;7R1o5db>wGd}*E$0T8K4fYK=y zrS^NHP!JOP@&u@#Q*QQxB3UKL)firU;^QaX4KbGUgizy)TY)ye%Th=JsJ8dBV_|Xm zxaZXiIW}TU<}xAXPG_w(c9S>fwMfWd^rE?p7_^e5og&JbJULpiWvp)r3o5!t2PiQ| zD{RG4Z*i1=rWn+OGk=aqUe3&w?Elpb!u_IX>YT|zG>~72HXt7YZm}Zo6Z2`9!Xi)r zYYt%vYouMHc+)L)eu2?C+^)a)!|6@ipW;}l>mzvhp%#mlZ?3n3_v)9VxSeIlo`|FTQo`CR_GWKYNf#VVbEn~ z13pJXNwY3vBO?iQ8RLVRs7MLvwTmYLB5n``Lbr^rpse-kA3rSBbMdAu_*~k7ULGd5 zLDA~?(F@uxovE0ST0Ne}ja(NKXl>JEFpLS4>~g1Arr?P$My2~$uH*FmA9e<{>)&hk zUTS1}7@8jy%{0XV`J&6B(H-s$TR>K$O;$ajaQ-s15gExzY%o;9W zAkbB4_W3pqOgnuZOQTm;Zh7=%bo%Y%thU2G{aoH%*uLt)RE9#}6zkcDjU?H6bOaOu zbx05h3G5Rt8LwDXc9yO#6B~1^U`a6zCw75GX1{;MWI` zwqSbPR-|zHedC{>55zrf11svi>QC-0GFQ%pDox1_=?4W7LHzC3It~l|rugD`h4Qkv z6G)0GEdn0K(N#504!S~TB;cg1yxEz{r{#C5>w7m!0 z?mlJ1XW74RIA6y6PKu7zA;^}Ka^GHiFzcR!ch6NfOg!tJK2@O?2fCMRei+5r=xW!s9$#%O&;cY6+Srjo|%)MA0AHq14F_@adplfpLmxb5WQSdfERkOr z(#OK%#A`MdzQj8hMiKJEp-WdEAr7GWc}vJN)BjC=RZ$$ySL-D|AZkG_J))L`pJ{D; zT{G1h@Fd|97s~YBO${?O5K`(=Kky+M2r^Oec?~C?!sE0s00f73C|Alqt z??iRnJbk&j?mo$=^nGc}&2@T^1R!Ykr2Ci)2)4fOmf!aH$^~8By@rw5>;IQWUc_Zc zH3buK@YnkNrJ&{gIwQ|}6gHp6~af5la&S|^m?shxmWAp8}< zkaGaoByM3Njlq{1*Huq@b6q`kCdSmGGxUTu6Igd;65KeX^vx_4MoZJEP*LB(R4whd z_Ipa2uaQ13MC=?45gYc2e~*XKAQdBPpn(s)xw{lm0}XxLABsjEKL=I@plwld*0X;4SsSlHJr)v3 z>K?q(RWw^gAV~|pNJ<6fM*~9hBe2?=N&))e|8c`dZ8@k$77FwwkK{<&E#-VQ{!|+% zySlsz)T5vb7rPXjND~UFbhpFQto*+Vr>QJ z_0`@)u6?auXH0@T+jva1!5o8J6|80g3}nnp9;mAYt_Oe+5sn8iZyYii6C%*MOL!@n z-UJH_;NRlMJL0KUXsb#JMQcT$pL^o^SYzaBv;%{*LkSHK>H1a+Y)+C|J6<77bQ}XdO$Ss$-o0cyagm)*kl#+CRCxxfw^F6orEHlWk)KPN7vV z=*HA;epPY*#jbIf?s+vWrR_zaGUI#S*$h1Oc9heXS+Rhq7+BBmd1jq;?h6?mMR}h4 z`={A=y>{GBt+(3lZNFbe(wVhF$+XH}f33@(5tFrX7gN6X=xTg+j{}EtnuQ2Xf7o9- z=Ky@YgWrY|A;9~o*^_4Bo}QMRao8Mb@Q)zcK11zzZeOF11oGwU>dg-DZ#L~N5>l=Q z-!PvK#Qv`FX6$a|PJa{*JjQvXl`#+7trG_55#3i71H%ECcRdhQb?G_v3)&G{|P^B+CY&{$eSDaDA3!|udSrRw=E|b5x6B)d=5hg8|4{{LoC2NgihDUmt zFH2A5gxO;?T@MqEv%IhSq4?k1!ql2(GjTD0_G2l-%d|s~n=KR@N6ahsWCMpBjGUplEM=$BD2a6eF;AZ&D zAMn^<3j6vawUhs@kbps& zL9&50q&>rc;`-CVMmt-N^^WC1)v+UvlxlB1u@e)0r znhjNI+XsYH-+2SP_dvJU#XLjGe4|t`RHs2wIyQC}R>YpCCoOKhcs_KD-INOK?hYgiheq>le#{aw>d9`>(&*83*Ivc~;sUi`N6wzWQp zdx@Pz(i1Gy$LmzS$l?*+_n$ERqVE(A-bJ7(xFPZ$#T+x|A83@o*zDQRS@zxUW)FL0 zFu*P?24tg7Y}1}m2GmHOcmrK=$C$iMer8Kkof&3icRkDDuqwM#g_>qYOji^OR0L{R z`?*`|N?S{*>TAqh?mrl_o(K$<0@%^m8EP>%=5A-fasVP4MzQ4i04keT9oCmScir7n zrd+q9^#9)MwLsT^?C^M{k$dPJJGQU!Bg%A}Y>?x!Y^m zKfCxo>h8iv-Fq7$NR{9Mg()2wOD0JIXi=41!Aua&=d&eu|3|_82dMH{nU04)wfcEmq{^Ul0AF)CKXXtyc43ClF`0Q|{T> zS=@-$>*vLd6W8)8H93A9)xytb;3lca`6>U;+b_n7c&PVX+P*LT5|ysJl%Zn7-OYcEX7N-J`s}i(E}>$pC8%^0~2)|512+M@K@6Q264LA!yy!` zu407H+JxeaDEQYk`qcn_2C%lxt^-;tWUtlkj5X+WOV(X z|NW2=_=YHXOc|i6h!6+M696|1NO)68+)Z6|omm=2S_DgZ9lD(h1FrFb@B1}D=-W#k ztLXC&&2-%tkEH$CDAc+@`8_qY;fG)nN9;lwfM9S);s%Hir%fdp;Lk@w2DVT3G&%y| zML!)DjM+VMt1LqPHj;ELMJ2%+b$EopCh7OT@|%QpO|%5Ye+O^n*tgR)TYJQ(J7>R! zN!j+YSf%{zhzS!QV}d|HLo%@gq|~M=2*~!P=xepWpVV$!*p#b^87<3eN4ee`%Nrh6 z<_y8xP(&mTVu%((6JkyZI7SsH!@6<=Wu7Z3&@7c>@MM8_po4*uGL;HD2^k~_L*pP5 z$b1P2zdizzX$hgic(H{o%)dL#uU}_;X1C1^9=A6-r8hi9>7H7o6*H@yYPH+m9kZO< zulLWbE4tL6VkmsLzXy55t4dd?P_QZh^RC?>tcyuQphNr`jgU2F#&%UgESvQl>&^t+ znvury@)^ydr^hD3J2PbFwjGy!#$8>(r*UP5!a8F2m zkK^gCdFnIrD7otS_`=no?>~cT&7xP!o)@j12Q;H7C>`JDp(kYV80`+{^Al?H*44bf zd3<0={(Wu9t@OBWo3Xng=r)^obCaoOFM+1~Q+5ac2Ik-7yp1VN<4TAdAG1Y6R?Gt} zyj~AOZQAsw8_73%TTF~~s3$?g{3XKT5kUNlxD_PAXF^OjW^mEj#awHhEecPrspCW^A|IcnkV2_S>`)XYoMtd^BSLi&$h4s!+1m$H$Gp;hmvw zlyDLWNpr|q>O;=TkwAuukh`PVD&TzZm=&e|jm+Z}g5H5jVbie&gvFSVu_(N;W*06+tNF_J!S@D_kTj#PnkMUc?_%z2tHZBWR zn&O{tR=#3YDAl@o6#Zg)r2)(XZIL3)c~NwoBIq97hp=BZ_knT5oGxCe!2eqV=ELLX zW49LP(o*kZuvGu=f(hBg^Sr9B6QZqJQ2VpQcw!cc#qVZtUpkBX z;pFk@1wdk616tKx>1bHaHzQ!D#bvKwa(^{tN*V@S%op~n^Xk0ayWjs4h!hZ)c$J1r zPlq~__P5jS{H^e?nnjvI7NLFh$`2xL81SW#-fOZYo~PBlf573nWJQm+%eLh@EgIqj zMPJMr1H$cMXlvhlbjN9&2B7xlbg;$ldf4akIcG{4AVR5NkR0tKH7+BGkbuzLrs&Kh zl|d*MI7pg=kI0~rqp0buLc4ga-LZ<77EjR-=?`|_0R|-s8ybke!U>iL!a8RGNl!>A zA1_d=OW60`b#odFdigA>*7WI)+D~I=WMQL#AJR{=sr90~l0(mOK-Qu%>4>TS7#LEKsB z>RZ;&VMu8u0#f_T_{^d_f40f`ukI|F;b6Y&ipj?Pw0Pn1K!12G%HuQGw^0uIt zEv4}i$qDg57tk|p1o8Jo)9paSLrZ-E`F)P>mY~BO3eS$+2yf}7j`%HkCNj)npt<-w zt+cE!eKYst?@7oSn#S1ds3-jwCx~gp+4ly@fo_fu+h{(>BFC9@fBU2?)3*^ z)iaI!2bFE;OW&#pmKD0Uh$>zRFXO_Z{#B5H#<0+Hoj#`ouM4BVYg~XM#d$Bg;caLY zjKiBgdD{c$FB^Sx^>tl^_x+4}z>qcg^TNi<`gktyt0{lu>oM7kZVBu;Rg44}jexg6$^EZuOpAYD4)~0B>Ao$<<+(!sj@?EY>Gs-k?pDhTL z)|Y@vgv@cBQbq!%h?AGtcDp=kZ(4Yt#EWGhvcaGM(I_#X$T@^6OE*|kC`X@`6JPiG zzSt>p*j-`961(^TgbRXe1~wSLS84DQ69xX8H<=70_`blo9L;BiM1%~eBCa1yBGA7Y zzkwwJsl~Z~8vKB=og+yi5dic141^(sT$PEWsgf~BuG3OMrY3@Nq6Om(gBYAQ(uce7 zcPm}BP1^C{?6#MdhaeQq(~3~rcl18->1Llr5NNld&KB^q-r}> z8edQvb%r11t+F1^fOfmY_zC5f?H?fcPQ(1DnuGs=uDf*FS|JbXH$VI#fw1(fdyjW zN%=J)G*SsP;)O|g4-EE%`~{A2qw46N!cGf;gZII-%4#*Ag%5kdbTy|il0e*w ze!W!he2U970!Ji(=n!4oW2m*G0TiEpxVR}c0x(Jl;x9mNA7p8zt{8JB68eE#jl>U= zHl$2pyq^OzgfkXYJTlqoJ2GWb{$S-MU-ft@(1wHcl0j~du2a=PPm;JG~M*@`8p4-8}2eLWx#=b+LW|RCd zFBZy+9qKp=C_hK@L-do{-x`sh$lf`10XlbnqT<|}`DL@io+@cU27 zuAE2DltkcVw*?l}=i~Rw+Sq0&;w;C~BLS+lBv&2Xk>VF)PO3lRFw|ozEDKG9#VA-P z(6wC`Qn5L!YCR9hz~FFR7s|OAnYrcc7vgZ10Wb6E=jpHAx850tp99eJ=JZOc9s?a; z%s9f;CE5m#@#wd{n@?|QLJ9ptUk&#gKbu=#(q=EM;-j~<+XptR;H$ATU$x}5GL0L1 zWw9;5`ER9cwVtQnZ^KqrYnVpSx9J%GoN}Ub_pvWB+aAjyUyG6LORfKgg}9Ug(PQT3 zMSXlWVphtwPdr`mnQ9$U?>{XHlC zx>6BH@K8vQmC!QZl=jye2=aV(k(Hzve`DE?#^urL{dJ7#&~5x8*~UC=f`YS3P7N#o zO;bhqH=l{SY}BJTomoQ@?5O)WM&sYR4y9htf;id42mWM1Z}SY0T2a?WIF<>a_)L!n zN$6qtzl)6jv7b0VRP~YnuZya)?ld}dix0!d4k^+V5LWQa%2U21m6lFg(kbVf0~g?z zqU*X50+jg`IVhIJhlN#2csOBhi1WYC&xr}YKL7eP8MwKbd3l+6S*yEOnr-q!_Iuu@ zZ6hSc&N-O_Nr-r7LSL-^ntsY>Hg47ioOqADnw^-aul8fgrIa$)W#s#BfnD z0H|9gKU|d7VqU%*mE<-gsEM$wGYCg>s{Ld=corasbX;W-8-p0wuR$*naxfTUDhj2- zK(<=ET~t>baEyWg#y3^AIKUa7=mkvG9R9BSmF5wAE<_w=sUpCZytDf zi4$!j-T?dC_I7;f`D&-?_QYuR@6{Qhv$+=NpN3<+IYLvf7#TCBIG0rL|KEYeajTK9 zgp^a`p9Al;2W-IWC1D0BVmt?atF2}|*Iip9F*B9PX8pc4%2)EXy8CbB7kK-dFQnSo za~Di+?sdIkS^M>Gl;0+5K3GS}I|)P78A>iz;g33dkL9cBYzcJU&fAr7skP2V1u&v1BpDb2 z{FGBqr{_h5Y_+ubrFhD39`P2Sv@1@QB|YsC%|gAvNlHM7M$iOs_eIz37SYowge__W1N}t;#2}AP{%VlhCkHoo z@ZP}dviPMs^{QlE;$5`1 zy;nrGV>4u6+F+E%PXK7^;pDnOf2^Q`;*FAzT1ZZgPb7+GJpp;8luxs5B@=IR1RSRxTSguK4^Kb{C(uHPggX z4}8BLb6saB@s+}*m6KH9-IDdh!X-d~qjR=i3)UU4)_Uv3>Dxg=TKlE>1Dw@vuy%S{ zm_1Dj+fN5FBTSh*-Oi7D-;S|ABjKS6iOIR3;lJ-#eH;AJ@ln2K&(yL{Uk}f_x$i2j zKXb4jor(F>U9eb>cgPd)ZzoJsJj&<&?v8q_X7is~EKh2Eg}E0pCA{%AGq>9d`)d$f z@*eGkW~7yPElxoW4C#Ec{Px&ogAHe5@2IOzg@&YV%iZLIp=u+2t`71w$Hss1n-iun zN$^cqnl%-K{xMba9HLH=+;|+;Nau7ErL%r44A+qvR1w|IqdU#;e*Zg^vShIr_nsD0 zx;|~$v{}4Mk;8Y}^B2c+C&}5Z8yr030Z5{$HDTcm%btPsl09HidL z{T%(_vz6sA{fmAA-f01U`?n651PC!`N0E6C`D5zE`2@d*QrwTp5Nulr?v+OuStF-< zd*(hyJOqDNtMhAm(K2Hzl&3)r8iTExS{tBo_TfJC0)${fphgcDfbfZH(Ha*zVTem? zzy|?9<+7b>M>&5$UvhTh@|9wNWw{|}5^te{`QGS)cZscK%;c7z4^^~v*Y6cJJIp5C#dAOb(X z&G*P&d*0{H%IJP@`#~(y3pj4qTa~46=8G{IZCk1|7U|v=HGho{gr9#oMlx$nO#uNN!ZtQbf|I*DIQ$hRvb^N+Hh%BBF|(|zTu);^ z6WMDPpr-_pqCo#M^6f<$*U&0Mj;IcK3kg2!v%?y8w1#OcIMU}KfDz|3g5&6!g-pa2 zGS7Kq!TE&#N|NiAy4jJEoa*&czCTP98SD;32@-xJ|AKod8d>M%vCzp=ixf`~(pjgn z3=RrN9<%!W_=Wx5Z^F#3!vH+M?^|!bdPsW-wbCC`4fpIxQ@ZL)T!;C>BT=WPkTLv| zBAF1Ja(l%;{Qtjt(4wH^t^m{SvVV#xUP(6;)otnvUfvv2quZU#Nio z(lzoGjrJzs&3iOtTt1!|YG=p1Im;{J^P}9bLuOW`9`)k6F=bj<(F~wO<~=MOK#YW+A>p7T~J!Hf-Tw zO2_Aq@4w&QPhS}e*au3>;y?*m1%jz1lv|My`SXO0-W0c%N=OyVk zCDsxCO!3*M_P-VrDD+v{gES%_l5viNRxJL#^h8m~O-TDRHFx1_R+)_u?`Q)mOC+By zSnhN&ZR^vR(DL7|mmp0yuYK~HSn!{DAcp&9?onw$ScG~@n&N`F7eddMq~d^Pv6x^k%Ed@`M)`hhZr7DPN_mgcw&&T)b{kgCfc2hJTH7Ev?`PU@!3%lZk8= zmjQvx3GGTLWo`ahH020Pg2Tw(PsSqu{pTqntePKG9VG+;0P1qg5}zW95MC@yv<)5N z5)K><@r!L=RKGs@ItxipOgxH&NWiMY5s0#pElYzb1A}E@kLf%-Vm4A738L>VhzVQ> zY_w(43Qp!gdQ|z+K~25VRbw|iyPAE53(dEzUMXIPRzJ>90mQj;$++~YS9jU6=6@a8 zwOiaj%zwRW#5a@Z7P2x@&GOcO@b16k3*P%oShG!ZF$#ID=zO(X%nGb)(;pwSBDKC zr9lEABF11y&=At;5NMmWlO3T|I(v@s3^evlj2ZdCcA3?=fQx>@QXC|gvV>-YKx_rR=l{S7j$6T@ zr#xhK2|I;P^|dmQ=H6PR%cj+_F2IUXfW0bI8daO{NAk4VNDs6!PKE z=D-IRMLS}G-Xja}5Q-%Y!=g}f{^`@uE(tHEHvM=1!DPKxWz`ZG&XMo2f)mwn?FxyQ zIAk0={>m=5ImJaLw@FxCK3_TuIQ1oNRgh5YhV9?|P9 zKm0KeXPpJ+v#BZ+hBS)Uhyw`p`Fp_uy%;9z9vd)$hzb{}BX_Q83Pc3~k`S^{Acx}< z^~W2DnP@_uQ*aSEnSxMM@I{o*%1i?T}b=|v95`RpG zxo7A4&YCi_VGZFgICMAEohdkV!^ zMqS12;{``l|5RD3zMDXhd_Wd8igYU`pJp;Jz`sDE&y>iMBvizRjI*7}SBQtqB8jg# zTsxDUmPS8)pV zp8kdJ4^rlHAR!1QSxb}4_}0YtcnQbJOl7!Zd1kAd@4dOfOHf4-h1iBP4lcNuQptoU zXqM`i=w!r0G3-bT_GbVH0_LDI z{I8s_9Q-PlPSj8|fEQ*EXKmIrv}{=bgQ`z?kJcn|t(pCv+j)Y+{-Kzn$wg^8{2#X7 zG0d`_X%ueTwx?}tw{5#;+MdR=ZQHi(p0;h){YlnY(rTcxemn_ptM$A(W`zxP7>NW++|-GmGA(O=x}8h{5JtPWYE{$6%gJ{608 z%4gKLI3m`>sG0E*8F>v-0o>D%B~YjzFC?dk=(zZ3@zZwwyI1o*e#n77$Eq+ur0hpp zV39hsLZ%&#k7GQ0;MA;&BD}AHK}e5UnP7!(4bLFUXm+e5#Pg!`wP_V$pyUyzy02rE z$-$@QTAfk7vWlWrQXG?RH?fHZW57rqMHZ+lD-Q-m4JsG^2*X;0v6PV{XC-G8B`mrd zh(US)uC+JFvy)ANomnYv4)JRjh0_r%sJGS*7QHK36Y~!NNFBV?{Qwvlg6!3E#$7W^ zuQuS6LICRQ!L0Y$cTtu3k}XS}U3o+}A;b(tEPVZY&;%~)IW+~u#^!4=ibd2AJ+xp3ZArym{@qL&V2Y5>4yrz&)EKM%o4pC-|JrEk_5@Q5) z2Pl91&+*Nls~OBS6%x8bRJw6!{4_D#qdMhP39)^%VR9EeLGeEHIO-Yb`GY?@A`=xe zJdps0Xm#!=H^o-A%^yA&(|@cjavv!MpB7urU0Mw#b%&%9@trxLstVh_QIby@;8u&8 z_<>3ZpcN5OfPlxrE%h$WEi#v@>Tp>yj3vFAmghKFq0p!mzz4gpY3pK4A2ZHmTZ+zM zF@wNt{*Cgmq@xCpnI-k0`aW~~kg6#ejgpF;-Z$E#8Pk*o;UXlxZ96l=gwU*mcFx`S zCE$=8~Ue&V*jX%j= z8OMGy5j&z(MjB_?vQ&eIPVL*|b=CKa5@VEvRENQp(u0CJ@f=rP_c=@Kt4U>A3o((1 z#yn~qf6w$bqCk?L0BG?)W8XiIF)b0hJpl9xm%s>3j!BM10!Jq9U^ViBMk`(NLX=do zzcb`9CGwyI&_huWg#GI@%y)Cv7em^NU#lNL0Lh!-L@m z>d!bDavBaBy@dIgRy;cqWsp1idF#ZIXwkaN(m$n4IiApEuz3klP?HW{V<)T}ickMN z5ni$Lt+}Ty?S*ZikNl_@@1%-L`}Ig`o41krlrx%}as~jtbLUe`PaXF}(qFek%QyqZM5GB)wwHq7}yTeof-qs-fjv^B#qsmdiTPRcj2BCJ3l*WU5Zm$S2}+w%F1g z3*Y7ZRr-R0Ne+2snc}F7I+p(iDtWYH7x|1CVKqef@Y6>5{Q$bU4~SZ=zlsKSx{ z(>T^zUNBYe6YQe-)jWUR^Is*jR_G(=mxx@|8TP7NRksWg6%~lKb)kvMvS zZNzA?F{*CLl)5S=V2OHPoVsFaA>ax9T2I8oSmgBStzcH}ix_*G8HH%4!$8Qv% zfUFz2Ql^W^$zD zrspO-3IB&vCl!eqDyF-z&~$reB6f+;V6x;#RkOG0T?Kn8ZlPP*!rDQ zO6|6Ybod3$?{nLt@_Gg$!jyPY3wD+X6c~8uV9a8^#s}_3gX5G*qY)>19tkW6t#9+- zMWVAHW(Ma%h%AWA@(SlkCPpeO5(vUfq!6QJ@F5hWpkyMTLY!%T;wdc9Sb@%AsAwoS zq_z1ElrMHzPv^k8;K;|%PXSU=Q1THa&tGdD?b}if8{-4IO9^H!E2FyiXgHt5Z_w^j zits3hJ%^-H+kp__58y`NA?O1!u4e4#H4}-tCi?p&#d9L(%LWLGsF?#+OJxE&e9q5t zsf(<#;8+jBcU8;8D}j@VduvcVv%{#F8DbbhkonBc+vIB|>0l2(-62_p^#~VkzKVU` zF?~O|-uJM{=6%4u0e{q#D7{@hA4J>eDvDo!(4IS_YwXZ(JN&r!-XYk|{m%UsWKJr5 z=G)LSK@U#0mAN)QDce`z?fCbgsmevq1T{W%=i}n$>*L1xZGeBq7_hV5V}1hQbMZnf zy1s9h7$bjbJL9H1azCDpJwqj!VW0{*v|K5!F;Z-PU15vG`9#AiBY%e#&7VtOwq&V% zdwncb%Ae!CKYdHnSS@l%yXeUL^P&H-*I_1q*0)7?tPRnCqfva)_`WJN1O5IPd*my4 zIzsuDr6Hh37p*ytf~rf}NC3gLsC&xbebt`V8!xVg0w+Hxg#&pAjI731PvU5y6lTSi zB9g6*M6X`aS0N?Nrtz(i=oqg^Qiv3TTE$EbT3FQofvDU>xsjIu{yyPJ^D>vNLpagZ z?5A>(YNg#Tj&Zs;j-T=P`vZ1Yf?qA4Z$FZI-mTNANc%=hj*>|n)&I~Yu7I9&QU$CE zWl^3HZT!`M46dV%^y~Y)dfoH=yt)y1KPQ$MXvz;RG-{tYS$Cg_A>6U`R&=4C^zA!| zF?X9``x-uS%{5^Lnf^r8v#-!lO&H5QYc$baMe%Mu}s5wk0P9ELuD z9-cfZ{xj!%E5EzP8n=ey_tO^N=C)ym@NR3>S@qxLx|0JLkI!53&sSwZFWMJm54}1y z7C0tzgv-j@0>ONO4A7~WIJ7HxVJsH*LQ9100-d3TI>I4GUx5~?NP+2F$ zJE<&Vh*clJo}lirW<4%q7J{R;gc)zvxWc-##kp-9{Za)9;F>L<)WRZ&?X;7bk({yj z){<7NylE5MZ_U#vSKji%oJW^tOcy&gOTwl0dk$@vX2a7`S1T5(!0EKk(GC`xd`c=_ zw`7@lWoQ~w&trbR)0dI!l_La;eh!ijva0AV1HgHb`D5IevED{{tcov@KKxk_eZYJ!_15C{!?dROh-MN zBxT!h)2l$N_rDYH!clqzD;Rawfs^)vp2Yo__~345Dw~F1cK#^H;-Z!RB{eK}lOnf3 zT&$pFF=+TWjZmp+V3MN9w?4pwx-+}lv~_z&=K$d9%D-umz9@D9J5pHsTVR}6ur5A_ zSkO@34zR0cTFxFaYL8i8S_etZfTEBDYn@kAh7vW>R<4#@fC_X#LB)fIVFX65f3xRM zj$GRA!dR7DWt4d?3iVg|Tvd#+!7n2Eo8F>VhPNr<evY%c)nqW4AKIlNk*-N1?aarL{X>gX#Zl1M##sviB&&rf=M zH*56=WS!+6{4Te$wH4-9u`^2ivCuUL6knZYkcsQ>b7I$}WGX^&6g?$?_SMRP>*q z7gk0vL@1U_as`zw6#U^3T>B*mT}V;Hd_F1?5+e0w29|2ne30FVa#L2!2^0X)VBT*B&@39)(>@+^)5b|}O@n9B`sqi&G zKClfQxodhKWy!iHn=4{fD z)V<7m5N8%3j6!QxV#DP8J%enI=Ttz|+?eWkHCNhWlS1I)8E;y6o{?;gycKMCwDM=w zWmHo(sPXGJp&HoFMLR+m|9FtJ;=3d*@pvx_jF1=pm1$3x%hwWjMW<)kbSj$BQP1Jc zWwt1Dh@5_7f7)1_R=s=oZa9I8PIobttpT|wftEF_4EE>7Us0s z3K0nP)--yvQjRgxk)ab*daTB@0$rwRqsoIlGn5E;=7LH@xMgv%zGx$CO@pJkU7IK++HX?_ozSUNb?~|T6XiS9{WO8tza7qvbeel!=dUbB5D25Qm z?AOG-nJn3R8`&lCl;yYecz=VstlZyD;|Tv9@s+z|1@;=>(Qz&^K=~6lJba{A!bZ%q zB;~Y5nx#bR=s?`lm-lD^?OJ|WNJ|~6sRKF_Hm+P3i`5(8rP3fg40@BvInZyf>A4xh zj!fGHO3T}nx&TJ%Bs%{|VR*c&&rOv+W~pEhjlYf3Hud6fAaJtPa5mC4!Td|nFZ4@4 z*D_We5NUOL;kZzZ=i`sXXg*FcI*I}vnQ{{t#-wIvGj$};qG*fYUHMs`-70(K7GW_dys< zc*dYd6 ziULOd3TQHE)Ww{q9b3{Glec;)sQ4F{W|-u#5Hn9z zn3AS01en&(Y?q!KfD2aR%~bp`v7M0nb+_CsRNzWdVrT5!hp8oPKOv)R^odqgkTn>z zgayE2*TQ(g5xvpYh_r;XiE#ja3aG_^^?M@j0c}q>!Fv zfS=IEd4_J_U7s8>Z)p7WrexY=Lreqkd{8k_q{~6f)foqHvE9&;A@=eob3rLzW zQUn=`t`j*|#b>EV$90*XopeIjPv78LJMWVtpxf}_b5gn{ zE7DDm@Dxv$ustc1ys-L~KKxbLHf|T@5uy@DJ!M994iwqK-l45%Q|s)h{rr~Eybz22 z{Y1{#gu^{pP63_KE9D~nC}rmx8U}oZg+SKU`N^%p&ga7DrKdw&;p4f}!r z4yRf`?8p85FPW$6f?Wv;_^sT|!v{^6^OHs(^gR0dRa9Rg1KD zvpDxnJ3Gp64NH-8&J7G(|Sf8v*lbT2C4xVJRcU%+FJS%Y)+Tn@UGj9#v}Lvhr!^JGg68Npktm1i0=?L zxQ>P~C(<*xH|0ndqq(;(iz7B-a$}>Qadb)%)D@!+05%xQNW$3V2A!Acypuk?v%5_V zI7B;esFl&RM2c17ZH!j&GkL?C6VbYeaQp)V%cwL`W#-u(G&CY1>OL2tUUE*R5)p9H zatysm&!{Z}bv0^Um9D4<-I-BbQcsCGnbayUqgJu;0OQuU~czr4@? z%AwD7NFdlv056>zY5r+LfM&;mn+nRlAGeVke5ZHiZ?%In93)j<&{EB3-P zoh4J6QscLGrOd+zpdSg`b+m4lFh&DEpGeU&P-++s5Z*qxy#057X4~;ePH&Rj&uh!3 z)t0G|za*+gbH@cm64K}hv5S>JrE^cFzd?dWHa#atCZ9yVZ0>l@i<*-&j_ATF)D*JO zu9hhOaj;`7bnts&g372-n)bEZD^Y0f*%Y$JL${nO?~oj=9N3 zI^z@%d|K+YQKbwy!royshPkTs{|GGGSlCES0mdf$h;vRo?i57Hul#IjWHX29<2h_y z=2aF*UWDB^)#;5G(z5XlA<8HNWe_p$48kL3Q8w| zV@3URwtZA(Usf2?`+Mdp>L2}9RjYms%AWBo#bfV5wP3#NSzov&UDUw3I``j&$F8}? zy{g3l;znBM)}-Z=YC&sCP;iS3vt%UOv-`7J7UAmqy>IjfeWq@!O0IZnMeNzakpldNju&Cw42F;$Z#J765jM#2@6w6RV_@?LP|Hq ze?#1z(T1nRN4at=rEud_xb&b%@pcq(nA6 z(Ma}%T0ERhx{^OAE$<_)+| zY;uCKH!R3$;@Dk~*#j8=i06G?>_tWo*1?!^B;IE6%Qg83Yy6ThN+Lr9R>*eaNAhYl zcyDugW_WLxI62YIrT!Jfc!VJ#M%(bCR@AQ6jGVQ`7Cv}_l~N}N`K}pAQ1^w1uEhL+ z=7b>1UWA_ZN~ITswx)d1pW#v&FR*fDQ0Y`Lpl#x8n|YE538g!1U)=XT&z7V_G}7O~ zUUP|G+-#b#nu;4RFad{kuE+TzP~;jr1OQ;l_QjVW@Zlm)pNG- zu&az+)5vwPE6&lM0N4lVe{yR1dOQen*5y8AIBvkl4!^@tleB$?j5iE1C&)y9%-~6V zPyaKUr<_o*O4JC6P=m6wawQ#=-!$+h|4O~T>ZTZ%P61x;S*lq82cJzU`OH+g7Ot_y zxa0|A`vhQDgcZLa;uh5fY(edwnaXY!L{Etkl~Oeh7k?)RA|C!Q5h%YZ?i>M7qx|*} zNp>kR~;#KTY31%(LQL0C-D8LkD+BH#H>?J%t#hB#hT!c+_8 zMpQ1{=0(Q8ymzDDChg6O^u__=fYe=oTa-0$#F2J7B*6!BzHmU!k`#Ah+(-j=O!BV~ zb4-T0A^~%nk%mcZdIKGUaj1dyD!6ido`7E_b68XYt*9bC`I@w1wMOO(U1aH9T|do4 z5I9LCC`r2;=J^mB2c71qV_(#)@QWy7JroP;B5y9PA5~-!(bFlLNj(~(ZX5Re{`l9rX<^z$<{pYJ4;{QWZF)CtS&tC=*#ui0^R-gX@(W@a=KbtM z^>2=9WZ#5B`y4dx4nB=YRM0UOr2-GZJrf;_)I2pUewlih#^p@Asoe8W0Y1i2__?j5 z8+t>lx{ZKtFGJR5-;RfHtW&dNEFrx%)j6gbzLc6T8@K^3K^*1k+8aJc6zrkTiDW@+X4cWrk zMNFZ?4^q>Xg)H<#Cnwghe0cjM&AlU6fvQbrbxB2NP_(4&o*TQ?`(*p53LB%?&RfMG z_RYe1ta$#rO5pE{LilQ2_|uosFRj4*~Tjvnz4+g2DYG z!5jOok>r)Yy;bljTo@_m*lI>dcGXG^@p3CX#X7?yjWEFV)R~?ZXOrwa^Dng5iP*C+ zH8p*ad(!Cgq)t5DiYWt3C^Z&~Q$W$i+s^^5od?y+5eCYzBe8l13eO+wh&|G^`+z<# z-sT1wU4$@od-upczWkeE5cM9?@Xw+r>}p(~^{|?7c)#A-pFGIw&GMwHct>2SNwTn) zv; z?OZG&pqW07L^4AEL-TU%b*#XQcRS-Tiw1yk7P+LES_(>Xzy@jq0n*?e%SYCIj_IuI zk76|rsA`(!EUTOL^vdk>ERZ0lZ|R_Bxt(=`M8O031)@o?g0fi zM}++%7RIE2Z{EJ=0VSIAbDJa4=Ix=vdXM?FuX-K}^iNRqdwqIw0rS3rpm2Ofy5Nc}Y1Acc=_EYRC?NR+mds1xXntqDV zT(#LY&@vTkjAyc$<~<1tw;zT(sb=_% zqjo$x9*Eqmn2&Y6=*Xn|Nj1@U#-C?LhCP} zKV^!SR)f_!B*8jSpt1Ws@Z}bQ==TmC)EVySbc2U3fYTOx1rf+FYWTD;%iSwKz+V2l zsTcjAm%8$jru`u7o$$h+e$t+GcWCC^>Fh8wy5W)alx!3(nFJYg_kPe)l$Yp<$M81z zT3F*Lorn=2l)cmVI43jYF&xo_W$yYnu zEEBkOi|<{a*=wt?odfK|JaW4AW6ZhXq`AoiQoU3z>T6(~509HMs`#-3nPW*|{T__p>)vdgs+#L<+?iW5(TpIUZHM&*T-+0`r{Df`OzDau0f@F7`6Df4-Y z^|A8BWq&@)xYWUgk)?t52UEVlrT1$8TwcQd7F439;#7I6O}#ogqfsM93EJ=-qZw4J zwou2!cpyZ9*|q*Z(|5snDpvKzJQ;BIW6(~8#{Is7JkhO#LNiBnxICiXnBVqw#L1Zc zPMS4|FU>dmOx^sh`M4nwLR$X^a~f?Nj$rX2K-(tc2U)B%vgCANJwW04rGw~ftobdZ zl_F3mQU5_ako@(1W749`ynz4QgqjIrz#kFqUC7ui?9Wm(99~vFwfsRZ7&?ZQvM?$G znK%e1{BptvTAmnYzA6s3jhJ-#FS1IwLxP-H3=TP;O*AK2BT^jmI+$cE3VJb7B{h&p zGk`4%dv*J7-UvXZqJX4vgsApa_rrfqBz!Nk{cR7p5yW`pu0OwAYwNjJ5?DzWp;`bG z!!C9?>f$nlL-G+$GAf6$VK>^vGiM5nAT!Y|W@uwpf$lY@+K@7e>0bI7k31t*m;>if8p1rFOqux_3ee>jFu|`6Ct9|QA0-G<}r2Lrc?LrSQR@ZoIg*4J~4Bfw$Q!^|w6pcsCZS9;o)W8B8-_FFZQM~iFwki!+{u|EM~5H5c@=$JllT($&=K@cjr z#fjvpj(B=fRH?ABs5E^{f15me-gk%`cqy!6&bqzNS?+}DmkZ$Y^cu2Tdm_K+f(*(z z@>CYOuSrm~@s=Ud|%M9V3WV(F@9?o{@-kmX9Ewnfg@mNmhf zE5lerVfw>P5i`3spLAa-sEtXsMBTgAyI2k*b1vrRPwuw%BF`W=~~^^6?w3tPC)zoD77=IGi(51yqDja zv5Qufz>6+t?zbK738>$Of5$D)@>yVO^s9=k6%)jU4N7jcBYnygf}LVfm{tIPgi!a5 z(g=?!T|)iyK(CGpz6ovFL*?*AfW-gQLJ)f%V8dCHc`RZa)4*?Tm7-Z>Hr)73m?pXg zK7>aoxmSuO`Iq^Rx4>p(#>0d)4sXpUg+1dZgJ4eC7nnP-Bow)@op6JowKQJn?SvqJ zNVGK+7>~lF*%VAIqG4;ByKG|Ga9Rbqu2Bhjs$=xh(IVgLvfIhfm2+boHy?e5p5k>D zbe6uOQ~7eyKxS*{TYRo;yJXnJ0|z{5jem2G7k#sFSJUv^(_lNz5Zg?8qF=q!45E56 zK&!oUOL3W7h|AHDUZH83a*b@Gv$7a%*E7Br%Ty@SmbchwI$*eT)yo>>O^Q z{{BVk1;!!xdTt~FWu;$VI0$l*Gw|j(3(|n0LPnI(I-k3DQW;Zfq$=53I414B*dKR` z9)#<`z!b}KEEC{Q)x zu3e;qC#>jfSl;0E zW_1ZuynWy6O*ouYI6e91?t;rd|;5K03P5Frq>pK8IDiXsA}?VWGM2;+aM0q51f&!Fy>{1*jE!#}8i_(g!( zYpOS287N6mKJ{vjun>##*L|F@A1-QU>JN<~6s zWDC3<8kpQ<8cPuab6|-RvfB!R-!-TwGO&fy|Cs=r|EJ}rF*Fd<4bX2juqH6!`v<*k zA}+`&k^KqS|0;a}0PjJ7XsL=_r+^g%>MOu{M`T`lk=yzFrn`_gj;*7>-8V9ns_mL)KUWD)wLT9pLc!0_m zaWq&v^fmkGi{SPSm{4H!2$Oq_=cg06eeTjP_pWUuQ|%RJ5R26taplSGmJPpa|Io04 zQ^&>}1uAuQZ{k?s$7*lCU_rj9Vh)N{WEUQtS!NpO^E`L!a}rE?HXuPZUqJrb0gyaT z5FlkhfV~CLQ3MtPsRktA{{uP;_!nrww*~%xLw(k&!9hWQKjF{iKs^l5U0~&HaFG9I zo9@W}>+=5u{Lfu)Ht?bU)8c;s|6Aezk4E%z+5ex1`H}cu2s1{2fZTwB+yeiP|0}!h zg#Ld6{-^ftG>`!QSHu5-lRRJHP#IGD9o$-5U_1NTk(=b1}~j-+B)S>ht#em=^$2)&2~a{BIQgFAe`s0{h9PLUCt@j+6rF8!CJI zqzwgfn+^Z}_!oAG__8$gS4_2iZeFe&6DURw=5(y9uM9+Cv{UqF%-nM>h}vh_r$$`x zjkDxRK|$J`xe3;dPt62~V@KLU8!KHp&P*EgwxB^y2mWqYtE-DEzxISS%0gR4v499E z8bt*PpZA!xGZP@{f`WL=6Nwg9#sf!%PumC*un&G;M$W&zzSn-;?i)FDtaU>8tn#7P zQ3L&EYu5NF7fNWXp_1p3?MJ}FSgFm93IwqTYj8l-+Q4khj)RxBBJf zk+n*qxuRkkf=sConiojSje376G5>Z>OS%0fAb3?by~?D}+8kx{d7l67Xpj3akr z$jplm;%q%BC& zdW*8kXdD5rPwXFIN7y$UTR<`w3?HDPa=*YHJT*?KKlCZi2Jh-o3 zT2kBVYjb}v)3c#RplJVa>K74}#(%-b|M+-EfJXi^g~T$6Gt!$R;=0F-5r7tkA;!V6 zP+j%sX<=$~vR_kR=uJs1ufYlE7o@k>V6B0g%k||87=Q<|<|(G#>1-U7Yt?ov92Qo2 zLKB6?X8Zk0BsZ9s_rv4)5*HQK{r&Y0pUV~n>C3inVnJ42U0p+?#rNxT_V-{2(0Q_w zSc$H7MtXXSwSE7RWGr5Jb#XYJE*i$`6H_UggoN1Y##%;t3==)|D=@sr$Gew9R7^`sV3)r0 zle|YwlUEiIW;4R^Hwrn4*Z}^ZJ_F{o?EyEcy88O$LVl^Auq`evx-CV< z{Le4Qafyk#ZNJ2|w5ZQOH0fxos^}RQs?ib??8)L|3JXE3KpzugGF!d8u%JRACMG5l zpId#u1mFmG7t?I5E>0h>xBlK2%LWBzWZ*4Eev?f(yxM{f1~ElLf=0Sj+)h(bY89lU z9G-IKlp!auNN?+KiL|>;A4fw+hp~M-UrIYY&Dzvo;wW%DVdCcFOXO@RvV(<3 z?$Oo{lzXkSZ$pARxIT`kOeF+_Seu%d(9+S&z4!MAMAOhn#uEN+slU5_Y+acJ(VdH~ z$SjnX+f^@WFK_Zv($mYz>bx6`pYP4f({RT@fC@YVMExet_TkOR$*Ehmk&*w#l-Ol_ z((e4j)6+9FC}eG8gZxBF8g_4YpA|o+L_89k{A0HdoFF$j`6shI38&?xy!6;!1f8Zq z=2~1Qs%Cgtlo%yrkYY0V-tK8!T-xc$jpF*jUk{8s5GC$_=Ltj?}WSaRdv~(Xhlf z-L*x+XZx95t~xNw9Gx7+r=|;dw}*s4sr&Ks^T!ebBAi}qxAKHYwqaKKsTf0mk-mPq zxw+xsA^CrvoE-&oQ@QQ((Jfe8T3Rotn$5VVD=CSA$^TGMX`tnW z(jn2Yy4x3mV9S3iI*L>*<>GceZ~70-rew$6s9<2UlG5Wr52C}vVY%wKtkxPfHwp0M z<=h`nN%stFY@#>_zjmF016&fU1hpzNhr>``Q&X`}aTjq9Drs?PNf@7*6)z%Ks!y9b zXxR8C0JtV*^M``sIc=6sxgAiW^h$_Rs}UhJlg+Kaa)=K>hdT+Jt~HtxrAubv`$B}K z4r)p!2Ly`N^~xqECLUZgDyhm^4@coLRHU(LG88(Geq&-n=FIui&Rd2NOC)$*TNx=w z{Y_dLUqw~b%iHVm@$vl~JdbGZ0ChNsquRU*^>z`}kc3U`+u#QZ>>%Xw%1U7lA>pMo z{%z97<1VPvg3E(tyJqe3y3kwoJ#Zz3TJXfVfl$)R`x6udF>pdQ9W(*~&Q^tVfsWSP z+_YT#RZ>@Xi)j}URfXWHR0LZyAu0-#w_oSx=jRU(+gr{7GdY$ma#0?8{cq#rGG#DW zSXg3U2<;Q8wWr%%9of|k1njqsC^SMmfy7sZu>u8|0FOt%olvR0N7qvPn;kB$Tp`n; z@#SGC|9N3ySten|xyy9?NVv5lUx z+iW6;3!!O-vonsRrQFFZY3^R%(25XoXc=Uq&@)NzvWc_7@PoQgVb}OnO`$9Be)t~d zxV6PaCuJcJIV1KA{A0#@Ruu3N2#D7O<6R>a!To_cv{(+}!H*37A<_NV1FAH(zMJa}*~ zVZhVn#gx($Y*M!-b`rD}_i zQs|*!j5_WUhb1P0q|)(tX=Mdk^<`DDUtM(>ES}CCZkcbiR5N{N-zjU?R%*@d9Ll?A zV`Y^Zc{ScR?N}(yhKNx@WLX+Jltw?Zp|V59#Kb(UL_rqZ{;wbhJ7BQ$k0=Ro+_N}0 zH%za2qB{y?n-eo51Y3tQ5DVsJCT0l=!iw(?r{qk;SVU&FhW^r`u+Y5PyzVc3ou$8R zxA2$^Kq!BZ-w60h;1kj_x;SSO;$S2tHRbERT#G{^8Te?(owZxs8Qo*~tr_Mg8h$o6 zQz_EW(k?GArz9nHM)v2?{lloC0@plo>=L9CDG8}*1$_66BqWZ3ad&>GsuB`(CS3=x z_3zBg*x%;ud_M@m9T^&qIN^-_(P%b!yEnSBs6@;+OhLnCT(%zKsP*EH%o{XH|dR%c>Tl=~es`Tp*eI9GTITB%Vz$Y9{(T;%(@2Tc&Z7b*#& zN6ktG*3F<+{!p50W^Q_Pd>nXXg(o!NRM&td?bBUk-uc8CLy(-}9APk0Fc*3x{ zzGl0Y5HphA;|pS@@#8;IB@*|;mg_{SB#^0%&g>8y59IX)-X)dV*|oHA&MFfL`dmJq zm1<~ckSR0lp>%jOS5-xIWoLWk3W$M45tx~oO;7i?udg#5PYu{J+W!Lb)Zv=GkPyd{ zDMv>~&mjvFbL)?2ODzY5cVGO^dSl@^YGx2T1r%QXF?e z{hb>;06b5aT%G>$A860`~5?j);NjGv|edR4sjypF|Ye! zjMq#fBcn|{^Fle3cCXKLy_FhlCVc_d&;A7}MZhK?E_@s{T;*fa-6{*+d!9mH(OXaHR91ZjP^71lj z@@PU6fq(puMkX`;LO<=;$Pw*X-nh z*9pJ3)t93a{cg8CK?I2rAv>DY)Yu&IHYpdX&Kz3WQPBaE6B{`N38a*ekPbHwGJn_Q zii(P1&zI*Lra{U{S|wM55eYmA!c&4$#cUBN6hL-Pz!6Z}V292?k>AC{ePh-qnVK4# zo<=LZ!;^HC&%S5j1b_dC$KvH9C&Xygx)-BG!%AC@_r2caX?H(Al)f```zelx{G%Pd z9fNZwS1@$J0XqSc8iiY=IPjSL=wM9AJ1%fF#;*G<<2swuc|7IOiK6C5Pt1H?fc=cP zxC7f=T1Ye0O)LLZFlDc7iyL}N#33TS!J!aO9i4sT5YTCJkx2G|It~;O#pc#loTV`U z-TV&T5B^)#k5~xEC+W&m)&F@Mq?U_{;+ zc3M_c*cu=%DBNrlFE1^ro&ci8^nCf{UYK)%j+B7`_TZ5{O!`{^=F^*Dqf#C+wcoo8 zKnq4x$%AknV2{OkdDnT_^Q)`DA%nY1@0EV|!dv5bp6WLH`wLrtR(qh&kMH({XuSYq zz1s>{TlKGxT2Nz=WxoI;uK!wNrSk7xT8fqu$`&sB=Is2GdQ?6Vjw60bS)HCs#81*m zO+({2FXO6ny53yb@XNY8B?W7FbkLet4u<)X9L(~tOu23*I5f16+WB}g{WPuiJDp!a z0@+*O=)^=|d|r1A($(Kn;MX1P?M0YPKGy1mK6SQM9&l7J?LnQLovjYx5IXDYVMWsN z@^?>na|;U(56Ec(-n{W3Q=q9M4P|8w4Jwavva+&dkU6Yv>Y&6}msQLPKf9;Zv3rU&b z;S_NZ5uJ-nj}HGg^+R~fPu7hcHZl{P(z{wK7O}9 z_#rtt8Hb3To<0l%sFU%z-ydR56ox@8w!}*EHxW||ro%vu4B&M~Aq&38IpM^YNo3Wa zhRexM?Mho(Sy@?F^yV$05vWFTu-0>O{Z8X@Rmc?})=ASfP}4Zua1~WSQ-kyN{!oAi zneFZo@MVmtBRZ80b0|GHIJgy3tV5L$ z<~rF@wN&IltaG|*M&JMyc?u$s+A6t1;P?53yN4`Q?`?Z@?YrZFVNze+ zvN*IebOq_hz@0?9>nzvSEZ6O>m#v4bo4>gaUE08nm0j@AOD+-v9dB=d?dGg{-uBiO zcp(h}p`5Lt`~Dy>WHTM$r{w?F)HjCL^?YroP1>k&8r!yQ8;#Azwi?^Et;V)(v$1Wx zJHP+);r(*XbG?$@iTnTK=0GQ$sYC|oA()Iy-P>n z+0@HoZpb-$C6re=QJfMMXi8P-kKuYFvh`*6L)#c8^&{$s2nxL|s4EYyK1nMCie^{(^S|}(6#-F}Z z=lHt?b8~Bd7`_Wq4XgwQ1NcY33q%~w`ZY9^uWu$f5)u+`w@rY1d*?_bJqyFk?Cj{o zgf=c}P>LEIGjgcZ61Pj&_~|w8>G{#7(L(mXf#^0s@&5%*kgn54Wb=PH=#=Ui8?CZnI23FV6*j5s#JEZv4$tH zh0pZb?pLliEeaBTMNmeyJiE={41ntEOixd*?w1Q~ynNPew5_xf2#^Bb4T%gLVBTUF zK!bt8JxJaZO-gu-%`AulEXtrjt zKtBupfkC2MvZ7Hq{cbY9k2tT8eA2PF(=oZgd2v(D0eGAd!x9U{p@o1 z>w3#k51vm8^hYo)#MS%$coxAqxxMgk2G3LP{MAJ9M}*jr&R=XcHsOBZZ%a2h96lok=|Yy%3O=OV!=0s~VDF=Nbe!3<~P^+|p7r1D*aL zwi|=e+dr=#EF=c}F}N^?n))M3Q>?yzghq@}D3~fj7Q?n%_oqRnh!_OEkmA8#XJvc{ z*E~F!g}(-aBvO}aaS8JZ&ARWepy2l!8mo930WOvnmfo%pRuKp_8XpkZSwJ1QAt-<3 zOxAaM#diFqCA3y6Ex?)3%9vSS#|}}7IZ^}$n^T$Mz>?n<(%&!4YP})EFY)etxuv7z z4TXI6eHfx2dT3V3}*(iTj3e7yhK8GJYVi5m|b0)hX!HQnCvJQ)|zWQmKk>YPakfw@R77oDs?`}D;RL8#uDHdk?NbN5*AbWUt;2~b$-K^JB*6MV60VpJ2 zGBb~tppsI)Y5%@-nu9|f5Nfg7Y^nG1T+0)UN~G4o!N4%q`|WzR(rD=^;MLLL4ZxP} z59f>~-}&>iGBa7u8Wpn|Qpmh%Feutd{ z0AfukVEyzmp=Kac(An%o&CFa~pGp*q-0qGYuXn}C-vhQ5`)3p^Ezc$!i|!W|gV+(- z3`E@2S5leH^_n1l#(8)uDmoW0^wW0#l9gSY>zi9!^LY3D1~`}SAJ7<7l$3(_q^y%; zV-_O1TUCSZTRSoyZ}oX`adHS)SXh{t&N~Az=9H3#3<6amkyz|cy+F#@uYm#2{<53H zZ9xkS=kI$##YF#GHi50QKbE%pW9Tk!x)0gLL(%woqMStq1v%mH$$7n1eQ-bk4seuV zaCtO~ZLkk0es1NYa5$Q2YipYxDzwc{Pp7cb5*e>^OosxeeJ}MG`%e1_ND|I3mSGDs zCMNz`BEXwJC3t>!x3ILZxI)Cv4Js{JSrMgXwvov3JcihatASL#5NT3X$IV6y!9K3Lc%v>RjPu>zqs=A4jV zrpTSeexIvKHeR_CLGdB(O_PkB-QxtwHhaz4*UKfgkz;8dF?cCU9YCb5p0dcWFpWR+g5N z)7?`OYu~9mRi2C?tJZx=SKEuf>-I>(h+5w)nsG9fnbZBEV^J*t>nu6-HjA4Q;yXN) ziykb-aad>=)b&jOR8t0tjK^kguV>$--lfVJ-)khiz>sW$GmRFNWri;Zp8-C^Z%|EU zbqar~pDL98zC@G?hEJQFv;Eh0 zvjdeTeGrjZT^+d}NdRJ+u8yb`9J)zwb?$Z`JkvUiks>mmiQ5u+mpWHGz@Z-EQ`C2! zWy*c1;WQ-e*#eY1HrQVdkW!5jMn_TRaH$HeixV=2Q zb5FU;X{VLGLPv$w1d^55RtlM`kCVnXelvr~mm@gZ<$6q0F>aCA3 zvo2!gF896sP)<2Hbm6$a)p(pPUJ=ZZ1L}KLJ-n`mPRN+eZ|rBxp!!I~h$) zL`7dVJKo_im@a>z-rqB7ZaNzsySlpilFP3jSc~e&Iw!{xbl~r9>MlsV3UgrFZD`X=WfeL52#LDSFd2b z*gOCaDNU?K?q$DMU;F!|5m}Ricny@G^bHg=iAt?y+BvSJ<$H}11!dV-R;TVkBwk^6 z9BG6`gB3F?D=PzoolZk}eD5Edm;1AT0O3|&ze3qYjfbnj^;Y7(`To1#20Oz@r09@G zR8-g`#93*2CWB0m_p8=}k=Pmo{oZbYYU1ce zBM}i1S16T`MAqfE+GkI@aZ!I0^Y9KpU71l@n{&7oqGP?I1E5jqZj|J4^o)KZ*dD?k z>7T7Q#*L4OZGzfwv^YW^nL|{f1qkHa68GtBF5TpJsC(A^>51$4LfjdWWE8t1a5eDq zTFCKUn;6-EvXN&OGVr1>4mY=JbW0-BoPa{TCMYg$Yb5+_Mm!Wl|Ls{8XJMY0gv8jy zBrQ3$^7)W(H*BrNv20@LZ`$kYM3(H6*Cb9(ZM1;h)IbELvv(^dWEvWz?$OjtPg`4V zZfPkZ3}EiZSm5tSh?u<9q@gW8UfZ>q-DEN|g4dnpt|!2LSe(jU#Os>d{T{D?9WfKoV$DrWxBTvKPC-MY<=2oGV9Tc}X!F3hEqaUg;wJyd|e zkz{aZN7ATqiuXbSv@B7e*rhtBI!0e=DdYpB>w+(Y3B5KYI$INHULCV-mSg_FS=RAi z>87CPAUJxa_Yq^*xY#)A)-L=Xm`Suc?_78wUX&qUKo=@CRCIK_clM>7Xi*8X7@aEt zq5$p7J>)JGHf&77{Nm!|(2%Leb6tMEVM5a4-mODj5Uin*QGek#2yqlz?eelBa8URK z8LFFkW@f6auYh8Uz+wD;rlqMxK|%4#Vx5S=r79@c>o$U1rAv9$7sqV-GuqmQS65ap44S;TcycfO{y~anaerfOYU;AViGo}=J3K9~ zto-e_G=Nd!ryT4Gxd})~{Rm;J=8tK7z_5_?d^p$AtAgPev}xIKU=k_mr2>;yiidyt zHBKVyYnUDhYoYSB!hD5kmA1js-qCh|R9Z@mjFwhZOVI#1-kKziOVH7={-vg1MLjjI zzW!IGro4`hs44=E%$&a($KYCn^#`IckWiC~uTu2@m0o*x`XH`k`KW3%&xEWy{~ zgIqZ>>l^#iSOr1ja;Q+~yHtZ*!u6qTIF}$^J_RXFUs|4QLCwU?Y5e>0X3MSWn-Ee` zcJJKmQfe;$wsb7*6Z4aJ&#Y++1R)s)?CgR(OY^ zTj@x?u7cswlkYdnP?JBycpiNaYMf1f8zsbK;**k^a7`}(jz1e)Q*#M9D=8@+9^YI7 z!sBEnDj69C9U}Q5F_`VtTImRdykBm6n=jX_*A$;AZLD9+?{xNfthtqi5e5@N!QN=C zoR}cOMyq88w_8(dYimx<){c8D&e}(Ic6R*P{!H#o?8xxf#~oR1Ip)jFFe=ri%dIN# z(Gj*Cm>=a86#)H89F?=<-R*d;L=FlX8hWup<7MOaNGv%t+mVb+U0vONe~jCihMmj9 z+skWX*)r-ueEx$!yOUP(|;l178WL+Gg*=jn!s?pMMLiUnK>$sDw*U_ zTvFh;vrlc2yxZpWinyu#MYOqDZ<}c_o6GUSk(P+L4Z~ z!eEOF&=ImdwPhx=(Iv@{B|hfe-J)V!B9~t1?MJqBs>O_9<1|Y`jgMv3YU-mto z2?;PW-h>u5$KCh+&L;&>y}ZIgCjc_FZP~F2rb8ztCSJ~|$wzus*kOHG`fJeBjDSZ< zYY=-xL=^`FRz=ZIn`p5w>6Cr#1|5G~C^`u6SH5bxWZ^(Jj+Hn^gq;->}i#$1`Q z`I5`%Dx&5Hll2h3xiN8Y1;5sNz>{cNjwR>pJmrV!92QDCc@OVMgN)|w{h)lQE_b=V+*3`%hgM~NRnk6md-5CiHt=JN8K=Hlr#PWfr`be|eotefe zqmc3_OhOPza9GIqkPvaXSUJ6thr;MiDWN|6HVR5g4OLYPG%3EirmnAZFgQ`7+FvB0 zCEF;vn3f<}qAH7vg}$Az#^WeCI68`x{!I9p54~E_;L9P!28}``w99q`2{u<$sO4W_ z8d`t%2Xwn9ExC94`#e@EM{D$#l{UX#i>3`J5)AMQsDZ{Xha4s;@vSjmk)cB*K0(2_ zlDWA#J{bM@pLAw(WFlhzz*d-BTjESg!0u79A<)*)XtwDTxXJwJpyaY8TlkeoSIf-h zB}Ik|wPzV&ZcIBaiz_KU>`=$E*LcIR;yUFe$Io91IbzF#*y^qU?s_zZVSXInjkj4 zKeSB64x{lIOg)~iiJRnsmF|3kz%5UzD3ZxEOmq^uru)mu79JKRSPem;%6YYNnV&Pu z-~e5<9?pl2y)N1pXTL7xNhn&nT@QGQ=8P1N`*ha_DsIEhMBf~nx-RKF%*-f`AWOOx zroO`;-OWyR?j9Uuak=`o1(%jml$*sNy zfvi_se-N=PH3?|CPqyqcx#FoS-_ppAn$~o-FKs7ts}#8f}^EnP&OU@9hohr{v8eh*LxqJ!WEAt>qUY8 zOa7rVJUncZ%9rIsI54!tM#;!%xJc8~8z~|jbHK;Pp?#&A=I_tu+qb?Boa46P`M`~h zjm_3}DV9C1gh@iP)YsQHHU`L(`BLN%{G|Bt6TdN1ULdc?qH<1`ZlLNE&)r9CT{jrA;o$s|u%R$Yuto-;}t40ilP<{r!CtgFhfj zo^QOyUpEp8NvjKk=WmR>s<7KQ8wu+@HKpEyFYKBY&H7h|_~;2XR%VEfH7%ybw5I|S zc@*3bro+2-3FYO32ngf}2;e3&xiJOiE-|p$peL$$KVEMvJh+e^3A)_JF{sAiaC!P@ zR$WT7g1_H4C(r)13PUyM^(`h8t-co&=WsiHJTVD>P;bX*0KS5Cj>CPt%g&9>t*`%y z6Q$m^RMAjbDT+@pjsOn2lfJXotX=j?`frMW(B(dzDp)V%SN2LYrXPM+ z&jTWXE|IjaU0(<=wzpMDUKcq~9dfhT#+@iK4}7yIX;@I6k^b}Y0#v&*R=IF`ge1;P z#s_G;xi%PQC~=fFR?nHulT!0|ZcVll zF{r5HV$<^hqQEiS+rL;u3(tIOx<7!s2^DZ{ZS%4ZBcrx#YI&w|X}|rUO)sT6f6r1(85Fh9L?J;>{V+F}pCL(~E!i^S#lV2V@hb8wBM9S6)vbi*UC#N|_C ziJrJ_;N+kE-k)#}(JLz`Feyl5uO1;n34^()f3jURQ9iW-vIOtEJN$bHjBk~R4lak1 zjJoZO)bS=0O4x`-zisdZh5#h^k*BWf~;d8o+~OM zVjSPX!QiL=z$lOdflnMjbmbSb=7Zt>xhON8cQ_(<-93T4dr!A|Mo@loD5@>8*nr<8 z_sk4>xFVAC3M!Rm-0F0uzAH$K>}Cr%?w#O{s&X5Tv4IZx8)YicL^tW_cxnv}kU8-B ztZ(hb#bi0XonyP=ag|!F_W~K8Yw$Vf4W8)vgi%X=iUq4X?*NvpDEdoscltMR|D@1?XEBvMnyE zIv1^apb8ebNO2(prhZsE`ADAJS`IbTbW_9A2pP%AQsE&XBpDXBcft}f%E~{Le;O@` zMWf)bON)~ZokxOYxr~m?5O6#ryYT_c17lohMFGaK#M?f=A3z=R_RdeG7?6;Z^fLrv zTEMxBPx=~oM46eRt=J3;3?GxcI!(GAy{Bp{EQ-msUHxIG&fYgLM+EfvdiNIKF2&y* z4egj&)1)|-o9)4k1DH;W0fZJi36}in-_DLsEkA472I^`um$fGq|E zUFh6)3;cQiA|NPuS)G%fj^)A1cxHmd^;mW#WI%+t+4>N)Igw@ZUg+#(8yU=&pPT#d zq!r<4+4=O51FtKK3mior6EjUXY;9z8lkAkhR%ScWH^amIsk_Q~P$5#SlxNdygAqiVwHv;|aU%8Jssf8rL z!31pb(ddO_!HO~=KXM^4JafBDe1fw#9zK>fxi;GE3*zbH#yQg@7Z5^4z!&s z>K6$h2E;D#gHa{b)Q-NP1Ce=wm#dvYJ9~TlQ(hYzX&0BV3DqIGvUFbO$YCEIHlq_3Uf#}00l{gsde4{MAh?upwOSK! zuJFVZIKXT#X@ZYJb zLbQPpsdkeof_XSPqwx=nTM{MW&J@P5u&@AP9jr}q#q1k?mzT4g!otGgO;7OUP46!b zgd1O~++Livf!O`7(Qaa0T^*O}KQLsWrOGK@YHAp4nRGFGJ3HU06<8>#42}xXs7&hQ z$Qn3NMa5bB9rlC{G(~L}1RE#&sR0=TKB&6V-mFAf4N8Dgn`rXbCFT@3}KJ_5fHO#FLCRAFl?p!DW1FKgzj$mua9LtS0)Ul;$f{hO?*tLrHwGBGh(K;w45LuSCAS4${WLpq!< zYfN8*=J=Adm!U~RLkOg#U=CGBcIm~(#OQGv29FNKpdTH{O-y9*Mmc>~U+1@VqE3q( z3SzWeabQD_kv~10R`S?47zo#6up#u~Z+E|$PR`84nF!5WZ*_)KmtU;ZdNT6H#ukAG z3%dV{)Ta{_DdU~~H?>DDCoeB9DQR?7{%iQKoV+rEVMi|LBR|HE+|oi6B&58;g&5X_ zg}I>@p_-b?>( z#I^|f#rD<2rL#*LtfoAWrZJ8IMoEth3q}%!!TfwwTeMhH17*D_Bgxrq*mt_7rmpUE zp-tbS2la7(AIK{<#aLrsqc`t^SN$fENvRhqQ#-vb>^O71)&2eya#3We#z;;& zm3b&9KYvoiJ2Um!z~vExP2&3xw5}aTF!&|gX9p4wCb}^y7^s^1`hb_yu_Hzxk3S3jzxkiOm~`cO`O{`4gWKKr^_>q~$VcyhPcyjs z8>B5)vb&5GP8%1kGJ!$9xBoI^ch9w*#>nW8#r%qh@tN!bZQv-uGIsa$gNBf*Bbe zx2<;O`}tlf;iR=#l$=)YN%{O+4kL9PalPD$>%J8XA4R5C!W`=$oss*h|)?x?Mmg zHQy1z_~9){t#j&r4lA);Q&b6=Sl7|c|_Ss%CZEj;3NnV1;V zQR>2(kz^;YIyw{q_FyvG%)q2T2pKf=jff{lbF*vD;Ps+k6frlqR+CUW5pSp35;Jw$ zS9D!qN)WlO#dR}rSL3X!*6+_{K#JwvtB0YG@E!54t02}SU=&qyKtP(V)>~K6d6hZP zO!w<}c+fyE>nH_m^e!l38AmggB65XFoWMrn3$;)KEVqULPP&(Ciu zg(BYxgvAcM2bjeG+Nj^jeJZ{bf`MFTF<+Vh08v3zPj<6~(#HG7m;|gsqQYkz*v=R4 zZ!#GiALivJMIUORRQ7j+sJq`&eosjkX4GHcXj%*VfimDl`MY z$y&9p47OlBSg&LK4%-;|4_%X;pbk@c6Q>^g@E4KJv%Ftu8NEB z$N%v5KAOuJfJVZf8HsrF|itXYv?AwG#4?)4^)`}-= zvfCT!0G$6>z^TadzuLj}aG9t7mu z%ms2DvPvevkpO%JaB%RTpr9ZBfr&h^?*X;*|?0#`@p zou{}c_^Ws~KE7CQRQdz1=d11S-{hL^ZJmvcjnh6~4lmfdk(e{T@;>F)wzLQl*kZAS zKOi(~y@LQ+;BRf?0XQ;GKadeAqW<54a~*h|dNFPc0$96iPoFaq5~AEaL=y0+Si@fz zxx4qyWJhujTVAWh)JCm>CcR+awmvh{(DJcG%eK`wkw&clGf@`aE0ROTQpk8r5n%Mn)vPxog7Bc6ZbOA_NP6iO|cc z{{DUd6aR|}+EB4Q4G?35n*&kZIC*9|JYQH0n1BuKi~N01SN_&l9w*7wTfMGKqqLq6ITBpn(GYBGaUMNu&fZ}WV;?vjcN?hJ@G1O$9* zBOMs@`vDVi8Gn5p>hCW!u=`y;zJF8b*7FkC-Th^6G$|=Q{$EXQE(7x&fLI_Iz3qXc zc51yEA(ImDtZeu4^5Od85wPxL6OaHi7SgDBs3Y+QeU1nW9B8uL!2r9}4VnfvHxpB< zZdhDD9`y88!HB|nw)!zZzoCOA2ztJAH&|bBOik6A;sKr^i_;z+T1v{%;$qWyw@j{O z%+|_F5?I*#BpNMb=nDivip;MN;Qz`A2?)5j*7Vi{{+8kko{EIqh_u!;Gc_SMYwi9w zFm(|TH~DGnxZ`_oW{SAHFkro0JWuR_Slgm6Qx87MoJq z+e4Td_EAFXH_Xj57xR3Iv}u-O`)$+TJ^KU5se@6tW#*ikwZDg4=|w2&~Fq~ncohm807 z%8I%OyaXT4A57NktHqwrKL7m`3UJShR($+7iQ4LTQkgSdfWjUCDexsftFpMf$zfaI zF@@1Z+%yNt%yU z-bkswag7m)#$$Df+PzU4qAjRq&4^}SuyvX>TP+GY9{&mhR6|^kDLJ*XY#Ta#_eOHG z%;h{&^Dk_{ zPLw{NP6m9>j%MAZiH8SQgif+lp=6Sm5lEbzj;^NWXK0xX(`oDu6&d zFGRU)-HH`7*?%Fm;I3!aj-3N2V1ZY+gTr&110?k)99&j2fVoH_X*a@vfZ$8}x?=*B zGG1kMyS@VN@IaLfpfym|0R)6^4HS6wX#)TJ$`o0z0>3shiVuWjwnIm zXfM%4jS&PyDyV7j;3ne9BLpKt;%6@ii7iJ4OPDZ40{nNN+ZNlX&5I9rLn8aD+W78g z%}c)N>1oE9*{ViOMIn*Ue*Mozxwey+mo_ts2KBdO2@;vcrX!wchzjhGP(WWQijOMVtL`{LPTc@5w6Dx7!_mXUaTA z22~JZV$6vQPEqs_q1gC%C57vKU?VRX44mAV)!!@=>Hh`rBDeu~PGCe_60si^L_2Q3 ze-B&}TbWz??jKcJ!vYDU?FJp0Rd7Z$nhZ0RDRC7q1$DOpwc}LPxp%?|oRr)+lhZ4C ztxo7Ov-LLz=F2-mByp+Z#yp*X=o40&>wtT>n$T4LP8GzkkV%* z4e!>4-QFz&=)@70L(5N88qNHk5=~#en`|P7Utd7FZq>8GptVyA-02+`MYRekaf;UG zZOyeEEFu{e49*Njf@yB*)vPUYp}vk^@CxQ#iAL@m-pf8+Uo#wJZ~{CPl`8FV&9=vi z2+TJxT%C%X9IuOwQXmX;jJne1IvcTBiCI!G?XrJ+lqLJ#x42y68mC0V>;3KlsHEaS zMPT{?&6GMvE%QK~3`(7%jvOBIqnW-wus^+!S(ie9m7J_yRirpF>0O`u&odG;>mMb1CFxSG9XQ*~vx`tC!4GxE#H-aFjAm$X`xZo86g>Kx3Wj z<>DyF$z6`MxjIM$oGifn_;I^@rr74sH;!=k`Di{LEDf^n7r1g;T6T1b2!)3zBcxM= zLgD^v($u!neqzB0wL9PZ0P=FAWn^Tk#z_!ESddX`y{F4f7T5W`bftdg{pzhTORA>C$Uk0xDcfp1H>l`tIZYT|&Jrm-|K z&}L6Sm0}r!P6T1aTGKL9>$Kwc=r58>Zkfzicm1}@CnGzl5l8ZNmtOQ?vVWa0l*5W~ zv7y*WglNPv%)L--MZ1K|bGzRYgzLV`qau??Ao-NLv7rsgZ8Dj0$8($@>)8x@JGnw) zno82y6$?#7lO&0=(cvjMEYL{u;mp&aNHBeQc_~MCX#F6$A01%T$hl)vR`cvhV=1!( z0RnO)vKm?9v{T1|3J8YA*F*pp(S7Tp6<++ z4i4M4gnC$2SsCNDaejWjyv$j{g|q0_ouf1&w#Z-BX+gu_T<>^7s6aF~I~ylPWVC89 z7};27k@T*39Uo8Re7frVd}{)vS{|PsOIWMwbP}&_+htWtEz5}CH-{!go8Q!Dnd*N9 z$*yz_n4OOsbVglXbJlOTu0b-IP}$&ozK(&DVas3{-^+|RZ$Jr<$xzqRs+D?q=!9Q9 zm`HyjfQMkqn23x#NKM1Nd07RlYiKB?f#=_&r)Ijke2aHlt(i-;2jX$V$Pnq8>J??R z_J+F}%?I;yyBg}rdp2saY=f}{Ps(lnJxpthL+OOd5b`urAJmFfz1y#?)HKXFXA2M(an}AkB)_o_sLD(*SQmGOY_w< z9=W_uEm(H!9}PHMWRzTo)0h|-N+>%!J5c5k_m&_a$Ehk3GzVNCd+c}45ni3KtL=JlwP^+ism8a1vt;ZB;Q{f9h<49Un%mtSFO`s`NKoKInK8G}|5wwZ0X{XDudiyR#SZ3xdmWbp3sZh9KX7MB*n1>t+&$7x;13G1gx@7%g` zJ2^fgA=4C;-sQ%Pyl7~%%;;p&()`l|}ivUcBv$&g!|&M?0jMw|ah{q=siKYnc` z4+64leI8SF!ID<7vJ*p+F>I*t1-<;&@9#Q96(dbcpddpRYjKf0*WDyKd#I0p84?w% z#lC<CoEo*7h$Hukwz)w z#^`IY-Kk$dK7!T^&_qV)O1W@~YNfuQ=T0A1q@dR}%aMVAT(drmO-^n~5~XT1jQ)6Q zt}dUMQ3#rJ_OzJ$rD?&C^1sz_(5kAeh?}y{n)0LChw0U?|E28em73D9dIkmJ{yQ~MiUb8&T0BOX;x299DX2FmHWm@e6Xdmf;st9`m+=9aFyr3kfAk zL+JB>>h>^EKSn@zr; zn4Q~FLRtEGk=_F_7$7PlEI%-q(DBYMJ_Y2)sZ)^*ux)Y{RjSou?7;Bn$V|U$d@iQ$ zpUtQYJGg|c-{$5wE_2??K_9PbozxD)Vx%T&t{0@Vs&?8Fh1q%QWSIv~or@c8EYuO* zNI}zlz~jf&ELwoLdxc|Sf8fWfjpJhJ?WH8(uZGyt67>E&jasvPgZ<4F%fP>ZLQghk zZEbC4ChGv8z@7p(Q{;yVG-$GUf_FJ8b*QV325#73G*!)4QvP^~K1c zsns#ZqQ$|HQ)^sY+!7N<#(7!QimEOYR0HbIHwT~&jlH>=FmQ80RK=P_^S(P9waGWK zItT|FqKwsS2;z&za#1i+>nto-MMXpua9~YNCNc=gn_5{JD{i=*_$=$Qzi-%D{uZY>E8PG z7T4*0)nD;)f8lL7noBk=2-TN)6lSw-JlaNicBWbsi~-PpMe4@ zPVR#`JmtXV%qTJ{$`*K0#Y4p2Pf~R$;Qkhp`=W5k< zx9$S)MOcZuZf-qAfsE)A>%c%Dfp}&L$Pu3{)MiKHB7|ys}^6e?8gK2h4n`!ZoDVt+*zqvzw5O;mkku za69bA3pd)4ap!mb)$*AK%^xX>$2oejX#ixrzw{SAO}c3D!)&wT1xTxDc3;$`n>wMc zsE|pLjL+}OC(1GaHCuL`JYR2JBq4#yRaI4D0z!qnbaWb>>Tg=DPW`+$KjvwdJ;@*1HMTn$X!Fl z>+)!0Xh_7t@!Se+=k+_GSY5}OR=8kMLZZWc((P@icl)lS1h>t*^jbDyPc*V`aPR_% z$DAxw@C20thbKA@&P)}o;N*4lX*4oyEUvN|bSgz0uO_b4J?HY}NXABp6mlmB^;bNy zTe?BcehRexH1|vfpnL|9hXfn6b5iwTz>u<#U*51h18}q^J+6nl1%o&^I1mvL*{o<_ zM1r5|S*|_y0*t_d!ot8* zEL==(AobXO(#T?^?&|i4H~o1lzF)s^1mJNd(J0SOaJx&q)}5L}eRvhkFM_$PBm*iN zgw9%1!+dm?2*%6d?Xe(9i-wfjxLZ+22PpY9F1zjF!i9s8Has-McE9=%9xDcl@4!z% zaSWbI#^6!|O*LF|bUeshmxwsds?T_Icp4rNA}*me2#nr0XYU+a)Y;iXQxormc~(}= z7As9e9vNeY-SghUcKf`eVEZjQ0V|^Is_$6jKgb+2Gc@Ch*;+!TGjJN9}9}f!QA5 zI)Ekz;00r2J4GI#gMf5>9p~nn92GGz5X_s$&}T>?U4sHm7C{y&8eMjHaZ*x3jyeRi zDm3eZYQ+MeD@Ny&6crSH^;hVF%rZ4Hv9dP$2hbFJpzt;aG1Lv77y*~#7r+(#?x(kK z=YE*9c;eWs`SAP#;F%q73;iI4Ie)t@FRO?4M#qh7v(^|{SoWP-sZpQ@`~jD7I8SWH zfrD5)_mI*2eEOI?l!1doB1_|kE=Jxo*=P-sc+?N3cz5LfirEu1VB~RoDYs&=VmMcx zG?@oSei1z}p|q5}QcdJkAh~4v +KFontview"> + + + + +]> + +
    + + +Font Viewer + +&Burkhard.Lueck; &Burkhard.Lueck.mail; + + + + +2013-06-19 +1.1 (&kde; 4.11) + + +KDE +fontview +fonts + + + + +&kfontview; is an application to view and install different types of fonts: + +TrueType (.ttf) +OpenType (otf, .ttf) +Postscript type 1 (file extension on &Windows; & OS/2 .pfb/.pfm; on &UNIX;/&Linux; .pfa/.afm) +BDF (Bitmap Distribution Format, file extension .bdf) +PCF (Portable Compiled Format, file extension .pcf) + + +You can use it as standalone program to preview and install a font +downloaded from the Internet. In the preview you can check that the font +has all characters you need. + + +Additionally &kfontview; can be launched from +the &systemsettings; module +Font Installer to use the extended preview capabilities +of &kfontview;. +To use &kfontview; in &konqueror; select Services in +the sidebar and go to the folders Fonts/Personal + or Fonts/System. +Then open the context menu with a &RMB; click on a font and start &kfontview; +by selecting it from the context menu. + + + + +&kfontview; application + + + + + + &kfontview; application + + + + + + +&kfontview;'s Standard Preview displays your font in several +different sizes using a pangram (a sentence using every letter of the alphabet at least once). +So you can get a good idea of what it will look like. +From the drop down box in the toolbar you can choose additional preview types: + +All Characters displays all characters +provided by the font in one size. +Unicode Block: The Unicode standard arranges groups of characters +together in blocks +Unicode Script: In Unicode, a script is a collection of letters +and other written signs used to represent textual information in one or more +writing systems +Change Text: Using this button opens the Preview +String dialog where you can insert a user defined text. +This feature enables you to check that a font supports the characters you need. + + +You can use the zoom buttons or the mousewheel to change the font size in all preview types. +In Unicode Block and Unicode Script +preview mode additional tooltip info's are displayed hovering a character with the +mouse pointer: +The character's Unicode Category and the value in +UCS-4, UTF-16, UTF-8 and +as XML Decimal Entity. + + +To install a font you downloaded from the Internet, click the +Install button in the lower-right corner. + + +You can install the font for personal us only available to you or system-wide available +for all users, the latter will require administrator privileges. + +Fonts are often provided in an archive format like zip. +Open these archives with &ark; which provides a simple previewer for fonts. +To make use of the extended capabilities of &kfontview; extract the fonts and open them in +&kfontview;. + +Applications need to be restarted to use of the newly installed fonts. +
    + + diff --git a/doc/kfontview/kfontview.png b/doc/kfontview/kfontview.png new file mode 100644 index 0000000000000000000000000000000000000000..fa205993ba4fd503b8b43c35182a2086c17092c6 GIT binary patch literal 66103 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

    yRh*Nm76G;;^B*1B4m%wju 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 JFP1WT@jsDHt7`xN literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/CMakeLists.txt b/doc/plasma-desktop/CMakeLists.txt new file mode 100644 index 0000000000..c5c24b907a --- /dev/null +++ b/doc/plasma-desktop/CMakeLists.txt @@ -0,0 +1,5 @@ +########### install files ############### +# +# +kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en) + diff --git a/doc/plasma-desktop/add-widgets.png b/doc/plasma-desktop/add-widgets.png new file mode 100644 index 0000000000000000000000000000000000000000..7c062760ebce7baee7892a9ca26dc1edb1a55272 GIT binary patch literal 28524 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 literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/desktop-settings.png b/doc/plasma-desktop/desktop-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..03732de504ee3de816f8c586c935f7e8d1949381 GIT binary patch literal 96709 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 z�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

    2%{UuTZF}0(9MYSJ%41UC@AGv_`RJTSP2M zbD#?$!zc`+NJ$Gu4MvC%f-!~_gRVUDIsrlnQ@-G+Jd#yOKBe&yLJ4IcMcIE+Y4Mf0 zHmF2i6}2Me1Rv68xKU|rVOjC7$mhzbrG!T$NMy+vE%}^#LMfy)_iZl|wJPOGmeWeB z?O>p#c1-%j(n!y&_oWoCs+m11c`jIgW7sgx%P}r6^rXij$FhbCxSSb2F1tNW(D7xjdzs7DD)bkn1jbo{v(-V|FU;#9Z654BN3S%XA!v5MYG*LCCp4 z1k17v!$8D{bKeVqkaRjVWtRz#WgCoU@_FBn#Q$gSU3z3WvNW;tF!NVLTFF>Yi=gu9({zVkgqV~i;YA~v48u4~(-@y%{G+-!yzGBgAbP36258Pql@!H_e2Bml>yVEM&^Sj#*$Aw<)7tYXp_~O&P$ei*LPBKk+pc5w zah^@2_8EB-oR>cYAb(a_aE2-X-2d`F{m=i+fA`h6!~gmpoXes< z`lAc*ABS{)2CDy=;b;3%U&P0!r{Ww}3MUegV~2>chO1WFp!NRMOkMRBCn86#ZCYjq zAkRK8l?gfjLk9N@76?tD)~QT)TBBrZJF2yc7cM1k4GP=EF&D0Fv&;Yq)+g2#MS1-? zaOLD&H%C{mwz8nCU3Kx*tH0M;El}EU05voPvDK3M1#2)fWp9y9=QC2*IDUP5CyF2T zBNN{5x>q-YZ`ssRlCJe_+r;BICq1TUr!hrQv!QEmZ#Vb1yI=qHm%se#&G+x0m>|W3 zj<uIu`?ZQH)@?rv|seDgZRI1Izk_2+rIyWM){x0{V;u6|*VBmrR8 zG-kkzUDv9rcP=GKNlvGCFMvhm(o5C%iVz(y+n0+++w}xo8BP|XY&X4{O%n);*Ug~VhUkW(448Dnd)qo-O{sK zDKBUUP;>f1#-E9>oLm+{yt}($=ZHuNK`Ae4^6EybX4x)K5|t4i43Wq=-}dchW1=aB zOz^BLB`VOiL9ymo#r(bO35a062D{g4yDqNJJ`4vD7`aPulhs>Rk81&uu!^7uwylU)_Tw~yKLmU|bzSQkpHW}u9fFxj z-!)(PP2*uakLUAg=Z4MD0W>NWV-&H&@q9QQLx@QX(7baGPyOTV>8meafA!|>U;c|P zPvd+zjED2|xIc#&w^P3v`pu?SRc6|3+U>SPaWE0PMMVQS@<>%v@`&ghn^_1+)XbEL zm>H3iSW3w;A!16=44re^t=nuj1_p-X9Kb*nC74=hThD|lqN)fKVmhA25aW58AD)ii zz5Dp^a2V$)&GR(PITa_x6k;Gm=a{+a+P3ezwsk|_55v$k4I*@X`?hhr%`m6<>i#Z? znp)pA%%qAUnytdTbE?|5UXwl@PW$tiiNP;4MKN5ozJy$WXsht=8l|s|A}uByIYg-M zyCen>vokhayVjWH`@?F^U=99TJTyw>GXRs6&ZjdIzkcg|)5^sr7KYvSKE^Q5YLa5i zD0Mcjsj3?)p6UkK@{Wj>_!U?TKNO~Ma_sueCWct_O9*vgV`e5PNs1=2c#al6Ga?Z; z-Oz7$-nXaeNkV+ac!ENcTnwbwvf!5-f{Dm`w;B4b{i+yt)=sJvVDB8e7-Nom`UA?k z8GPOW{{=i49a5eU%M9n8@7sQgGa=p#yTf=wfSBU8-5_ETX`Bx!CP`D6Hr)n^`*uJC zLL%f`v!-y)cfNP+94FDFs!4)l-}qM5L_?uXV&a!e#RpIHCya^>ihxla?SYH zzyGdnTk_63cFr}8ckGzJIoEcrsg3h=KFeX89HDQW_Z|#XVdy;3=5QQiNM`CBf!REV z{r<#=cQ>29Z==ZXzyFY8949}85Mxpkc0O+?5e$h`Oia;;0For8tj$rXrI(1j_gz<9 zepOY()GQ@Y1#U=H$2lF&GXR{&84ZTs4_(`~t#^!|DQOhUw5rw-0(6Z-fH2Pw`{Rd) z{r+$~k8|UQp$TL$&ZpCq567WvTkmr+?$Gy}ZFjTX+-$dP*AZq13{0Y~ZEuN~C{3~N zT-W%nYePsM9`<91F~$(0_wHuXi|D%#Plw})2wTtF?j_h5>)E$#pphMC8Pytv2EtF$ zy0QU|ZiaRWVrtnoa&@H{Tof|3Ewwr#7H6wV&OshBCCd3c`u*X}n}(Q03o8N%?q1y; z568T6)@tj4fF*RHGLS0foOxJOHZa*WT0u=yN{>(bFTZ>p<|$@|q^hK-)dAOaotY2w zY$0eWge)RPV&63VcH3_@G0b5cRZ^Ykm%q$vuuJA(R?j?qaW+;7G^-ko#no*2ax=vE zr|f_~yI}o{AF2upQtxB$eAjl5$9=9SF{PpF#(BzE9}&$l?D|b+X~h)BFm+9rMZiQ% z$N(^hF==Aw3DCPXNoswsCL+Z~$8)19qN!|l$*C<8%;y#Ef)N|QRm|w6PM6*mt3}nS zJi-cMrsAYQ>+$##t4sSqPoZUzW&pGzIwPXxMAFqFv-(r3EkOSBEJA$2`)UedP6-h` zF)=ys#8gB)JMUcI_vksq^msUgkdmY^q%_B_ad&sSrfDS!0yuVk)3Rek&?M(^1l8s| zpQqW8`PL)RJg4uc$9Er|#t>Ara*>*@bA8tlvxqVxGZE7`#VJHlA*80E*LOGfx4W)w zViIO~*z@7N4uOnK%= zoHpAY&>E&q=T4_7Put$p@pK-?kq}$&H=7QT=Mb65d*60V+qQ%lMbAOVKvd_b$1&XB z_S@F&cFneHGMF!-<1|0+k1>W66ER7QyIsHOn@sAh)$RpO@JvS{BEXDD5h67WXK*O9 zqLWCyQ0JCcvFCt}iQm?nHn}s^v+J%Re4a7M6l@uLGtmCuYUE*kMAE& zheMp_Otj9nDme(X>00MqnC28yMhkq`b;D-ZZc~^~heHaJmFE}TgcaRj0lmy9e@!LI z?9af)!eVMopB7*MkUz5C=f>Zym?xi?z(2($u>H6t@S68TM2<*JMbn$x*K?fD^VCCU zU_>y_^R^!j=VO#KbbXXGhG~u=#Cbd1FoKxPGKV-)NJK=cY1u|yMF--l&RvFMdbTaL$}fUt>LUvQYO17$Eq~+~H&Gd$6 zkqmj^1csKE$aNcSaOE1k-1Mu-+49~uj~8&A?YQux5nsl`VLSAypqa0Z$N-F_4xQts zahsvp?Y2*+>2N$}BGT!2n#XzaZk*6sOsrBp3k%QZVGWbboaO0Vd!pl-8jxu zh|IJbn(x0$sNw+Tl=hELAK!m`{P_5bFYjZt7*pRjyUnoMZiq=$Ph*&qFyhc}Zf~}~ zfH&vU7(!%1Kp4k4i-$r;Y8sQMsq^k;x7}_AVm8BX-tWKuIC-Y7p{{Ly@kM{X?Y$#a zokPgi%;`LuO5Zj^*W_`z>%4bN2A+Kg^PdoO^TP)&Gayv{Ghs~^00i$m5Tc=|WxdwL ztOM2*eFQ}B-5gkLK`{Yyv0D+X7E)!_%jB34G^&f>#qHTlErf759J{{V-rVHrI@hl4 zZg+EkJB?FH2_R|S)DkQ;I41#ObBLNEj8o6T<54t<)#>9CK}Sw*h$BraH4Wn%$W$#Ut%UkHU>eb9eUb^ODg zY*!QT=bHNSe-sXCu2qOnr@g3VQ)m%&%u}5Eu6OK144ZBcEksQO+Mk{7{P0H?Qx4*gQu` zNk!VmIp>VXF||!I^j+g!(>OEP9}h94!)cV5M7)_gCN)c_kv>O9TghTuMu zbFOJz-?mNLw5=O@ZrWz&T;rYdJ}b%qAqGK$3^=QTh#+C(-L`L%2od#N>zp&S-c#!- z`)oMp6zFM8cYX8v^{tprQ*cbpx1|9PrVzyfGkXAU{-?*awYX}2(+ZS5hKm0$#*i_QU+ml~|9(|LS+*bl?d zG)*ekwXx^>*RM{;Qw$;G*USumD*hXJ@2h|aTKdu4I+WU6U;`7K$LY6U|NhG_zi52( z-FM%g4o4}rlu{PMM26J${r2|O4BNgZrfD4a4xm#&(E zpXzW0OBe%uj$`=w*4_0#i^v@2n_)AC**mxChH;+EM8ufg;e6Z;+c8Z0^KsJ+x5G_R z2{Ej-Lty4y)A~MXn&z?bt#{37JP?v-N-BuR#fwIVSFMA#n=@7}*Z98U9`QWB^^lL*Khh{zB9cGJDS zzcJIkZ@a!TF*6!?}+itf(gowM=_l@tnF0Xg9Ih2{TZ4+V) zp;fh^Z=7?Svy4=yAp67kxE~Gh{&sUev_s!GrmpdGNOMdnroL;==Mjliq;35$blH&` z(7$^M4dZU(`!U^b`=MbGom1TJPv`Lr0FO_HufO^Jo9{l%^Nav<2;TGE{q22BA;cu| z@#&OQk$C93yy_mu7-O90us@#05JaSLu4(-J&F21g3q~O&A~01^BO*tZ4V&5)rs+lQ z#6p3liyo;clHg*>cqN!#7hs}H+F}AEX3hXEz!h)e+WiXa{6?9lV3c)(SiB@@iR?`& zjpy@ze|You4KPZ!nn2j@wl{aT=hL}lT4$pxB!i0w7OEB_SX>b&3r1Z)W);~#K8@r2 z#oO1v`s=?s9Z!e-;dDGnMi&SjyQXQ{w&}YT5vMskJv^SCo~H9jVkiMbIVNSvXIQ;` zvua%lWW~*+(jmMp4OvxmA$Sb;fVz zZC=$&Ui&s&wGm4qLcyY~I!%_>S`XQ)3E0-<{3>|~l#roD4AaUaq^2Ti9cQtUO0D?k z70;qVEM0;evL)Wj-c()VcitzlIYh_QG+sL;w2j=I!hI zTn@UnX}l*QHJ#@W)AX=EJ?+ouX^J5_??Xzro8C8WGxWR7K#1F+Ync1S4W0i_|M>NH z-+$b0`)Qt!r}N#-uJ2m!@V@On9;U8!|JASWJ%b^<|9JTA*WZ2f-Mgp9JrkYA^Ege% z;~7zz_;?y~hSJm1p>10xJWnB}Bw~!*cTLkZ<2aqpQxKWvpfMql_w2pD*$($N!)6#5 zX}j$=ee1pRt^puZMURblPfssVfb&O&bqBn{qO(2LIv99uiJHA&iIE*UM;eWYh~2XF zT`-un1Lczanc*C?5^`{1GP8jiV@{~B7~;jo$g2%}!L$^EjvI$a!{IM4u#vIH@TT4c*3Za~Kb*nw2W50-#`+GW}4M|@0@@0`nGS|(>Q;4cx0lkYsYbX`?h;^ zdy|rkbC|~IH}4+*@i)K!-FNS%^Yr+*pXYg+gMk5RHY3$23UD6BaU8q0y}Q|kDICsc z1SF>8$wHFz80I;MDLdZvZSUK*a}6`kur5@rO1Z*pnrH}SjA)j1y_RD` zb5PWD9v>c_Hk-k-&)h;oxVhQg-QUgAEGa1pfT=P-skh6UyUe|{1{+%Th(^Nf60I?$ z5aKkQ4hM3s?S^5~cf;VE2LMP(B@we{bi5@2(Wp z6i~75!HY=ur#b@L8iM{j0{@Ih;Aa47WffiK&P$^WC@MrGDpQyn-`s9)Q;I32sA=iY zJaOy$hMSnu;rx{I>#fL74C~ApC3a08QxMIeszoV}WXsjJmfo(y7;@bu_{4OckfC(n z)%s_>QMON!=gXqEraoNxVO_7BZRNI6nas9w=cygTYL^TPs|)dRS6$Hh7rLiTr!h)8 z&rwCaV|L8UD(t;)8~6Hdr>cj;p=*5WZ#_FgG=h&G_eo;rzQ&OD=@3(R+#j39-`(xH zra4dH{fCcnj(z7F?^HTwMj|_nW=0I4q9P&9ZyWAfKhHtL4#(+#|3CiY!^6JoT4sJa zpMUes`^Wv^>)*eBcsicODZ~)RscRc{BmklsLz+Wu8#m9pzwfd*LSL7qJ;3}n;S@>bNKDM_uqg2?r=J3On|0nnJ<Y_`r5KY?#G9e%Ti^Fx*EDK|jGE27O&=bQA0Hp{cbGL@nY?#IY$bPq*7pzsf-Z*Ybz!49M5D}>rN=G7 zU4)FNRWA$%W+}z-Jf2SH+xz=@;XEN7};9$iir6WtkQd1JMAzN z5?V62Sh*S^^h3Yd^wT(>&Zl`CB_=Ryz4MLpjlb{ix4Z3We>m))=JQ!o1T*G*aH*-P z|N7%@7ZO(5MfbvA^yW}zRe_R6(wY5IFF~sw@|T)5M-X? z9AXp^(HZ6`G>vx#V4!K1F~-vw4yV)p>G1CT$6?d$y6)-Y!{7hI@4Bve`|8F!H_z$o zcaLAbzU!Lio9`b&jMFslk7w_>WBAA4ee>IIzJEF#<~ii3+#LNIQvxwCH3Vilp2y8F zHf^)%I^X)%H_S{7_uFlZ@pwGXn!b2-H+1dcI6gh@bG@6Vs0dPycy`2Q8iJh8;~e6P z6yVCD;yeUrJ<^f}T*R-{k_HiNwGYmaM&CA8b~c1)$hdCvkdexbm9?^(Q&`MQL{kz` zQBkuT-es(2q-qXSffQ6tZJws5{o(fZ)_W(Kb@aHqxw*Z&8IPyDiULcjWF@cjYDr{3 zxDXl%^UgSjFgH!3swT?JZQHh+%`boXm6?6}&F_y-hcHhmgzPlg58ZCJ-S3Z*q#OFp z&92{Vjt`G9&XQ6JbDTp8A-`G~)DhV`LsW^HYD-Zf3xBFpmHkO^grCRcf9|j8$9)kC znYZ2{wX)%r$rBcyun-X#1c}~xL<%vS=W&U=R!~N6T-!AR049l`mQ+NAO5G|Ijfq2y zo;_p_th~jsnr{!d+E3Yfa{VOb_u1PiF$~YRDvPn?@`itqN4?ly)*bLgxew1Y$hNY* z!o^)ypMic0`1TAif7!?Bbn3gtd*3;3Ti17)vEtjd0f5e|Yh6s~be^UuZ2DHTO(}Wj zQ%Whx@pKOJoFth+5)skU@$8t}rUBGACr{`dwT)|9PlPdQQbja1Olm2mm+wB*x@66!i{&+f_=Q)UoNDT9QI*%d57^6ta?V5_JNSLFl8WD|Z2TeW9k*>OB5l)b zZ*P9_%dbx7@%LYUd)n{AG)an@V)n8igw4=visR`#Ph*&e-R;e*H*Zd-u=GCO|(%#%+Jz74T;#tiOZ-cx9M_*Wz&~L_uR>14X39`OKb8 zk}@df*k#*Q1Z;e303l8yl3RBsm(zR;%?bbk95*2aFc6a*cPJ7wHQE+msp}Q>_21#s z3AjwlEBET_F?4Nx@q>8I^}v5s4?xd@}5j#RtX`Bh*rNLRgF1W*Nl*2$mb*qW#>OAwWPS776*x>U@D^7 z^(eDwH2_T03;++0Pu_dy7>V!%opd;e7DOjZ)uEQ8U6$jgMxOi2A z;Rid31ARcVme~!xH=uD2*;;!HVV-6J`}lZ#+@CZ>6`3W08X_^HV{Y4~%j{(VWKdH_ zoMoL!L{;+qWnyCL2ph-Vk*O&_*ES9b3C&=RG0aH~L`18R+48Z7fvTmHvSq)jf@Z^D zAkY*i=Y8XvrfHaPmV~NtN+^B;Bug5EOhZgbC59MdOey7DFSQ)ugQ~)WL+4eTXzmaI z%wmjs)QN+LM3pifF>m^Ix7+ls2g7NeLkKAe0Hl<{9MmkOn36D(LsEj2G(X{mcEE(p zctwHESTwFzzt5^KGq-KC>DzIRNwN?KnFuhGCk)7NbunKT;CjCqis}@l@wD6Y;}k-% zqsnxuB0o0M6w~o^3iH%&c0tVy6k)p?Hrvg7K1+&{BwM^zdmCAtL+VzTtFpeXgjFSh zsUW-i&9?8m|LZ^g_DwQDO4BO@;h8#Rz%H%q8_mk2Ht9Wwyq|n+AmQ`3K3I1Rq zHu$Fi;)?(n77LD&=493AYEgJx8i4Ym7vj~@H(VP+|LDj2k59}*h|pr$b;RS?Y%VTz_);-rkwjEpLF-#G3XzvuVg7{G4CE(%I2SMI&m63u z>w}pMOl@7XmTl!_<5a^Mt^nNijM%tFBr!1p58cMh7_jx-)9F!7&6L?;<|C>VI2TL! zXI=v@Y^LjBwCID^##O7}gij~n5>9iyEna?atCVE?p$ct3jBKy-3JnbbimAPo5OdH= z9I)9Md|szMEHcFEhxcM+tPtj$L~hwisjy<1m~uW6KsG8X@ObI3OYK<&QmMwo06|2@ zF%Xe+s3Kr6&w-d##W6YOvj6bSX2|EN_m0@9s)|lA#T4fdrw~KZoPFfDro9qk_3Cs; z!00@)%WFX%1tEbBv-Us-jvxd&pc@m6)>2M@7`488~>|z;_^Pvw1%1qlir1(Ns zl*EjbV+IJ3iStdzSK{9i98x!$M9#ZS-!|SI&Os#if|)>Fyr79nk84&tT)3njUDej=y=#&9^EK-4)G#SlS(?(T0se)t%sNkvqw=A4+S7$L}Y z)OYD8ih)+?@}1jmH%$2M-N!fwk#!73zJ-X0x~}WHF4xlc-+!3Sql5^EGr)0wxVgXE z+}y-z)FfFGoM~qZnPZ`R>qQ!jKehUHI-Oxy?|_RD(C5d`4TFx7n8-2bEr~5eV0W8WUDJ(WWOk1Ic{)|9G*r_@ESR908D5)D zEvWc&`^l=!yuetvbY&J~5o5C{l`RD_s>h`eWF z9~I`)Sv3>n&@pRe%MWeawrx33Pz@o|3=v(EFjYsV0e=V_cmOexHUgoK1# zN(d4#5)-wJ^WJ5z=GHskx+Df*htrgj04m39Z>gptDaNR3mQ3=_84C_!kcB5AswygG z36b*-6#yjJ;W)V|7?im-iKrSFW))5}Ma=V1#B1M+x=6`gC=#KenVLiu)0YaiyJP{= zI#P%56AO+~u9%(UzH5ihpQaFF+2iD8@gf1LIRwil)@;eMUlEitJCca<>NknaK{kDB zx%VPcP|AK&K%y2yn5Ho78m;A_@B6OnPA;cG)HVnydwVR>{L39@<$W!H77^{X!{gIY zQp_Dsb#cxo4uPq2ZW#KmYYFk`a2UsPVGyWFieVbVJoLln*mfGDXwo{Z@YxIcFX5qPCPIig$pfHr-x-Pd_uE=l|Kx70|RX~ec37##F zpS@Z=6xM9;<(SB<>Z{(f*3RrSZ&&kiZBy2>^s{0Qivz+R&4~ObA5(~nr$SLYDZ-** zfh*&rZ2N21+s6#m0s|@ul0!m7RW>t2$~7%d5@ZO>Nal#=IXI?ccaEY-@x$ZO{%~UE z?a(_%F)0&oh8CVGy@(TbK_h#L1Y3ZXKJF7L{vmn zR83S$qM@NdQM2YLuQGH9OhF)-pThC*NAxOD)3s6*k(;C2lb%0vHXEj@HXhqZP zBa=-<@*4|LnQ7=-5lt!O8jMO{YGyIU^EB=5ZWzoIfx!8u-wgcV)VaPlRShBLv30Ge zSX$d`Ay-0DGBt~^>zm_YEUWtZCbI8{ks-Qa)8F0SG>uCso=&IyBZ}@`HH8qS$=~ey zVMx=6k<0WCYisCYJc2~_a&gWt`}jBi?%$=|Ex^Y=T88xb@t@QDyJ9CQfQeL|pl9NY zaWN4hIbw4j0UbHx;*0?RHN-bdewC3znA@hi-QIy26HoKmv5OK3OD^n^le@%j6QG){ ztM6KLv@*b=PwKG(u$dBFDls9g=T~?}<63N-pA)s#PtPYZUmIjD*>e@bT~3r*bQjzn z78lAD`O_BU`Fel+;~z1mygJ9KdIqQ>OM@)qw>3YUaAmn&j`u`JQl>6NLd2NT9AbvF z%gWjS5gC$42SyqtB#kki#_*eO-&e{GGCyS{DiS(Jt#d=)-So}v&8BIar~Uci@i5N8 z%wm+7#MGilO2s!Jrz&OVXC^|7IV>SFY%}tp8HrX!$nGh5j#bV8ERdo}{zIuO542R? z1?tI$GbKf8@rWSC4A82GNu8WDFB&R_3ClNXpM=2wsSq>~G2`Mx`OFmhV)o3=QR{u% zIzl>!G>0UnC2OQcGZ?56Ro#6CoZ(Xaa@U)UHXwJ@Iq?wkCkjN_vU}V6&Cu?T3aVv3 z1~danGS4%pI^tA8uzu)~7?8a8n*ji9o=waU^EUdD>RnmT1a&=Jdi9Jlmw<9K03=|h zu5F!j0C0P|-R(9AFwfz9%ppii$dQT2JdMM4)ApOQKcsm^Lo`&8_2wI{#QqnJ#7|}Z z1^Dpp-5y@8Am~4w1^u~D|1+20A14HU#xAzva4cGvC0S9!#37Z?g*r*B*0g|goZF@| z)2L~G+IPNn?8Y#K6dXAsjwwE;M45ph10_iaKO9(HE3Oi8meX9<;CznIdP!U{%|H?O+97f|6xJ3wT8*)mZLL=Flq`DTI!9dZrwy)BS?aH$H5c7Xt)!E`#M!<6 z#1sIFA4pd7o8rQDt33e~%)E9GMX0OgP&O(@6&aDy`mLFw397~bDWeQbh)FWxHlOfJ z#2y>hFdzdWn3|o(upa{;ibxD8#Dtk0oqspe@?#OqEG5YuMFNykFpUu$yRK^yVG1!N z6fsa0Ff}04s1PNAfvS{BZ30SB%lWG+WGzK@*$c+HC|jxSL~mr z)&EIs4Cks77G(w&EoHYpoMY#mckGx9;2cusV3&xYn*UoE$Mr2_YQCbDUp^C?aDhS; zAZK%F*;LeqKvbt7o6a{rh7j}rnXhV5o9CdS-1-u`z}OExJC{T}W7{>kc?|(16D;8x zf?n{1#a#|;4zcgM#fCFK)j3B*fOLPqdwqXHL@IJRO(8^FYv=M1oKlS99Q&pTOau&S zP?XJ=pu+3w3xxEePT-fWz|SD)&ySyV5zmppRiQ`EK(B?h@rjH95ygu2s+oxj05t3Y zF-e@mgv5-T%ed4-aP>M10jSoui|6x-8Dz$*+4p)f&NULRQ0T(%SlM8GV*Xs8_N@7^ zPrNE^0Mgk%RhXe#kB_)v@69`6xfb2bNI)5DJaZ0KJ2qGdPg=v!; z#*(V1DgtVXie{O1gxQ}-3ky3t9~KC@64kAS-9vU!K?H{c3(&pn(G3wC^U!rK@+Erj zpwwJ0!3-6GqU^!V#9SOXQXWN-oC8&=Z@4swm0Fe2;W8q!vZ1LJRnjWsjw>QvSI=k# zSs)A|t-7Ialc;1<&ss9)5R$~6dnxop7>1$kx<@rhY16m;&@uD=c$%k>a zJQj;70%~<2+1>}|mcEbfXCjbK~{H;uED@~9XC@Nvuz+rZq%&;{fqtC`?Yh1LJ zEp$wP$i&`J+c`uR=F|{7CPa*2QKeMX%+o<2E2upKDH$sXNR%w+HB|u>08qsMDM}ir zSp+0W<&j;CPzV7D1uSVXG&W0RxGvfAW`>lR;*>iIEHr4z9hNCbNy@1;m>8PIJEAPE zB|s64DI#Ilw0+;c*baE9w1~`vmn{$x5)jttA7HKkb)H8hWB54**fbL`)UafEfteX8 z0#LSXGsCR7RzNh>yrxyek`J_40|3A{$D5(eH!>0|_Rf-0N{Q;;836je?T4P(jdMVl zH$yXYjbqx=>2w}b%)c0{;Ua^}64pe=ahm4&{?$zgv!s-h!hy&)&70TvL*LCIr6j5n z=J+XvG5d5#N{GbHBQYWa>cyd_YMD&ZPr0src=v8^uipEt2B7KUCZ|2-u4d~WeRk&(Z_CPW@!3K|v}N<1PuThgu*Rn%nn}{UJT){_LNwCC zS+*=grHol4K#tnU|0ZTq@L|ebo6G)ZjvYGyAwk~0RRe@5NoNIwkW?g^s)=Rc87&tF zf~qCakaxl*z7ot7itoQt{<=V!85mM!+UAc@rC`Vx{+uobFKX2jsUpgT1Sks=7Xb{( zGG0%V-NQ4OVqmCZiU4Lq+YnKTvFn=Mw%_*c@%%DYl$J|tVOn3X=)9w~ib`|-Plc0> zgy@KUN+^0Mz!xsGscDMwH^2Mt zZ~pqLc?wSoDb57g_ubn!_cyzZ0zB?dL+e5a`8_`ChVyr=B9vFLSW| zpv6_0q4829Kk?NvGercmbWsiALif0!S((0BjW!J-b56mQ4U?@{SGk;DluIx4EtV0~ zAZHHLVZg4f3-ftbPosj7yWB)LE{nlJgefTth(?4!kk{ThpeMUemK}cKv0lu=vNK8& z(b)iiO5Ot?kz-XsBnGEsSX9}$!jq*`K6A#>@08i~LVzrNvSZ&kk@Vp)O)umH zouMTIG*jmCcK~o6m@xmdnZ=a*j9h)CdQ)KIxb<%6nmNj8oI_O5tURc>yogo(E087G zN=gb^oG>!A3|GN{^&-WXv}-(`1LEcCRn?Fp6B6V)3JUo8)!o;d&FOHAF-~((mEF*8 z`tJVjW*EBt;dDBk!<_PVphlqwAcpWQ^69a;7xfRH)rl%abo2!V+dpdRq2nMn9={_P5aw$HQg&-!s;xte7! zgUo!+YelO6SxsBlL`g}+IXA~pNgkyL5YVREbWK0aBLHstjd%Vq9#+1`mpX?Co?PAq zvU94b-t3=Dz?Z2PYdd%~0TGYiH5&5$o| z5AzI^M|%OwMk-iBpNN1MsB(q?5EK-R)IcODfI%_^V#>&bWkXW~Kp?`#GZKtb(xfY5 zyn>a3nF?O7moNJ2sDE09y%rhO%(U@373=0LX+*!<(*W z&P|Q>U3+&s%yW9&kLPKgW0+&esuq1A8IoN;aQt03;^LLpd6VLP$16 zYdvo}*EYlc9L6ysh!Tn_WtcZ?bhqu>#((kZZr%>Z(|A0dLx{0>rvM7%v6~*?%VIb``{g62~e_6^U%y-xu*y-q5~>Y`mBu3t3E@X z5Px!I_Tz%2axLTMu=c26<#OeEKIQ_A1nXrln*#Vv6%fnsN#wQCD^uxE@bUl;bI$N`6yHY z6f_48C&(5rIs~E=iJPp}A7IKG-#1efj3`!^8P>iqTXhh7>~_r)g-L?WXJ7 z=561;zS~V<9?x?w!!f1o`HWP;78vXKbqye2 z2lrlWz*htB^Ws*gTe~v1dKU0twoaj_%%r+dEP+TF23;yU;UZ_ecBo#hqihkkT!yv+ z1<*3Qy}&h~YS&1+tz=J#sBrOEMntI}D=V04R9jMJi|q&(3cP}3mV3qOO1dhRjdR(c zYleJtxivDB%3jZg9`z#0d+~zE8-S4+70N+blWRR9^F;-gSHQWDL!~HTPLmV8Wa9up zP&G4jRWf3Vu(qdiWJSTsDuDHT|fb{ z1C|!Hb*d?q`eKb#CAK-|oOb}2BvT_+POvNXTcJ*_xV&OuVuvxR+TFHQgVPwQUf|i@ zgAk;+Yh%Wu7Xme|yfVtSt_I9S$cMyMdJtO+d(=P>@9uAJ?r)zS9xF@Pz%0xu204#& z+qk~-o38EKcGGp1jYTE*7zPMA#W=?F?!(99;e0rr=4nnbYAnXonUZ1b+WLc+Y$;(T?W&4d;vGamD;Fw)=vG_{X&*-uk&HaI*5>UyX z%L{PG`*J8ESD+eIu7+rwN8H6YDT_uBF(<{Mq0w4NmB|9xM~#c_HtT9Y4G=OExRBRT zRWgWMrY^N=GUWh?tG8E?aGEHnNla4wy-MvdKon6zA}Ygkc6|~>Q%fR2O3*|Uz(i%7Q%ot-bF2z=oGCTlF^g*ELN!c)IF1lAwDUsjm|Rww*?Z?5o0&+) zD$3=ySaU#OXwf?Gaw#WfCJLunk>dTX6}1TpzAkZe);C(yALr0U45FWDk)9Vv_GI@%zkH$caDh&^PCz}409OI z(=^ZXG{+b7KiQ~1w;Hnk(1`cX zRqdZ2srZw>h_%yXO?O=gM2l|!a(RXnTHj_#(j0?#-jfR{Wkv=9?1t@OJOaRO*b&kk z=fzW2$i7ab}SAvRbxPL{c%jTkI<3GW!-%P)23Z%3}3pZWcAEZNbIv2bXWK@}3EJ z`OGfceN--5>QWhz@=$aMeMbPKx@RtjZFU&7OtP+wtz0Ky8A&g2!~hH?0OoR4iN2hh3Q<-c5fcDqsQc;`C8{EQ z%6w?L2>RCcFU8nooUw0gH#AYijLqcJAsBK823oJ~Wy^qT4PRmOF(LvP2^y}M|BDMM zpnye$w{Ks4^XhIok17skN<_|i?+r{ORki&E!TPhEz%QRi2%qB!|Dql>9?+_bvaQn&VBt6*Okr;Q z|HIz9HCb{bXJUSdh|D~fs;=s80Gt74II9OrFKaTBp7f$und#4qlGdo@4!NXpX9f*) z*X5j(w}^0eJw#@nJXHm9NYs!Zw$os3u&(NJ%}jUy{JR9toFu252r;l%Gc~(EJzQ_E zzPx=8hAHPyhfg9>P%_V+2(yTqA!2Zzkz$TZbGq!eE*L_1@d{t8!3$)*euP!o27rrX z!zI~mQTk3n1ru9L)-0d3Zyip`9a=pRz?pKjL?lg{ z(703(KrqajXJH5eAoIeY0RtdJMgY(xXCKJMJMWMX9MPE6z#M}Zq+~?q2(nDy1%W37 z$HtQ1H~ta8;afALj!YR7R9kvVP`i5bw3X*+bM{x#g#c1s(sGX|sOOS{{wfDE6$eEkT2rN#8|SS1wb?M*7SeL5 zCUmxbLL_7acCHYBZNAsiQh{d&X=X%p#X@l!mjRK$F?lZJXfEy?h~Q?IYDNs+PX@iIfc*;f(abj_6VJ%LCzn!SB@b3A@AbbU@a>Dn(FpM!KuxW%#|Ej{`3VNpc7 zuHQ6GvuT|7Ii)4j7m3)1s%gk^jxncXDo@JmJhlJii`jg;a4$1kJ|91y!FRz&r!D1W zO)7tL!S5}9#*~=YJEv+{vzo=6&S>PceZ+YWI-O6RoMWFgtLelnF2)Wo=zYOJ31}S& zd>IUEbBY>VR^PK`X-P9&y)Q-NRrOuAw&mhiJM$#%48ShBqZL1FUMioxD(3=RIIFho z#$aMyO_EbxfU#FPzIb~pS&DCifh~p(lh-5BN`sB1zo9Ap)u3pJsF+BScidF95A2;s zq_*o~jLUnQm*5i>8Ic?_AUI~GxqwVGA};DCBy`N|$W7u}&jhN%1kBER&+H6z@n0)a zWGh-HG}QuO8WCnu0x(r)8gnXz#s%Zj@1>kgvY7yt6D;LSgp^T)i-EZ+h*44+ltn;g z!bZw=Gpi)cr#7kxsAjcdw^j10Rg4hH6^qUZf@SAYdaX31nNCnN1~c3|QR8T3o=kHR znO-=@O-<^Qu`r!>ebRm9nPV12Bbzww1R#ZGxzt!&q_I-P~Xg(hq0TDz+lR9>l4@ELt z0HoEFSqc~t6C*P_RgGx?JVyr6r0c~JpKxX-7xM&zxs+a(=lP*$1g=146LD-xBcETV z&BBG*qhsyVG2QWA()*sLx+TBm`HI~Zc<%r?=3*pLO0oiAPFXE8mGnVE)NND0y}d=Es;aN9c6HOFlucDca>_n9$4+wY z$04NzfMxIC*s)_~=e<+SO}$}eQ*)jGunK_)*}2-gW>b3~>QHSq8${Y{H+|QaDfi9w z)z!_Ls;U8v9jBOwp$9;Ar8e`z8&VY&%~^=Z4BEDfF%seFbo%XI|CcU~!H01i**Wh* zKXfV*Q}*7+7*k5boZ@)*>COP03+%Yb^;^n-r*Hs_20M3i$HW6ULO z$j!urg4ma2_@;R!8E^sZt;k`gjqqv{GnZTfqDgj5{H#h&3l7pH{0Nd55ju8>3hKMK zkFL52`3;UE!w*kaS#ie9g)nW{G-xl6{`<5BLE`ky1og4kfNw>nqU9=>lCAk zwvzQsWt^NZ=UNUIUa;qQBD=WKrtm2nhVgJX-P~Mlx7)7mqT~Xh`Kqq>JKxl*I`+M! zG+FHaJ06)@`JT_P=Z76!#)VqPb|(na;6WG6btA*J-`i*k*`+ZgU-FEwnUwl>7b=wWU{oCJ;F?M}dg)qi(zu#q%)2Y3?yE}GW;rok7UDw;~ z&J4c)_%X#XXL-2$w(pNkv-P2gap<~k+D3|qiev#~W>6Vkr9UvBsS8+WF zo*ZG$CMv}XMH$DKrbu5vnJ3p0s8!@rHVLx;2|%qqo(96(n>S_tj!X_}m(0k98Mv)S%;NEC-*>^sTH{&nWYKM@D( zJORV!`ulUOzoo3MeW0`;xpSe#%fR`SAO|m$wIU*A8Dnc34IsjjYYuB`$te>Mb&lx4 zDLU{e)p>^0bb+atS21U!uQ*(0c+O3NHCt=lXG|HWE9ANOAi?^L%}E4!rUy^s_99bW zr9#29*2O8c{%QOJ6nY7O%`q2PR2#2z)OBNKAvD*wx6D4}R0m(x)i_2`+ihxM0z(BQ z9+U{^XF!6S~C8nJ6ZrgnI)t5=s`%~Zd zOf(Mh`s#}C=sl+-zx&{oU+tbx{A3`lLfBW6{!#E&f@YOiPYYpMUES=>ET^cVS*6}^Fow83Gt1)|Jm9!$R>0a5U#g`7sag?cK4DI+n&@TfeF`;Sm|;!kQMPzQKcQA#jKxn0 zRu^3E)sH3$&)FXG>7(KKhGj5i7fwlolb6K&fxyJw1ckK))-;I}o4=_w!IxI-KmNFV z_ujKFaqT)KB5>&m*!cpl=M)jJX?DS9W+o)(TvgX`9Ehk)nMhc+c_o)8RGyhcqzWOW zEICynAn~a^dglcC+1V zhG8Vahlk^*PY?FQbeRXwM4YpG}mvgW6ITb7wSrK9@}ngTgh=PyZVXUf$fj`rL_#{^9uOq zTD@mW{h8zp2&ksZ->jURFRI-t7va3c0fQ%oQww_h6kaxCBvS?Ac~G{M8Q!`aPUcHb zs<@pklh!`Y6M=Bv2cIcdPdLvy*;K7Wge&t~oWqQ!TNVfct^E;~cDAJY=zO&=Gx|gc zJNuL@DxbwR=nPi>$m1{nufGf-0MMpss;2hdJLdpk97iGyz7o(70st~OFsthdh{3sW z988PHv#JRLH%*O%-Z>;BLgzdYF!FZi7|eN3Oz+>lZJGuV>$)n&lah0ijELTQG;_`q zbJ3prlfAh`pa1zxxj@70++#yFhX)9KW0 zwmU$)`*ip5?q1DON|JM3Ro=^%FpklCX8<>wecN}t{Z$>R_H>LfA|Nqcr7R*T=Mchv zzkjv6_;O0y^Pf$p53J&fJu@OjDFf)ll%8sENo9sf`Bp@4XGCjC-2g-gj=C{txq!RY z;ooXdh1ud{CIl7ynYiqLCjr11$8n59-^V!q!#}uR{?eM=Hi-$q`}glaRYlFr`mU^N ze$2-uB7NW2b=~Z?JN8N>B554k!y%4?i9FdLFSiN&cQH!Nld=PNt<><($4~aFo@>&x z9q!Fi3P2+ykcTvN+D{C!Xp2E&z%`;sK?6r(IzW(|f zMpA$zSpgnTEhBvDaTD6-o1YhYQFM0r}ot5oQX+A>$+y9FW$Xp=1-p< z>bh}`t17S~=Ntm0l%4l=RfiCepsuSB0<$wS@0|0_%)Iw%;@G{pxsGEZLg&~3-`rl8 zN|T}v!!QiPn3DbC7coXI1M4tk5y={3>`twjCCMDB+E4_BVc6~W*H>4>WM(;McCM}} z$u_2_s@{8Y?Ahg?aC^XQ4=hmFIC%w$HA1Qx-h{K;wCcB5Kc9t?N5c+-?$04PpqkjM4yKxx5{^rki`+ZgrptoOqLF_)%;qKF2cRZ#MvL*QA{8(*$ zLnw@A=Uk}3g{s*QVN5xtbi98UyOX5&62gQ_;KdoNv!AZR@`V-UlX#iW$Ioa2zGxC> z{erEwq4p97xD>WxB0T%%7_J>K5YbHLO)#(G2&YO(3%>mH5_{q4)_#vK)L?w!N2^9* zX&2_|tGb?{&DQmva6*rl(V9y6pQXDti!@V64oNlQPXU;`&}HyaU7V*ad3`JHK*JUL!rSlhnU94$H&V1?QZ*t9zt-cDk{6( z?r=JR!MnF_|M21458rWYbnX8DKKozqw*ZK7>!s^~bjFTS>)<{OMBWd0k#aSwzI% zS54DwcTLk6f~cD2IP?-n&H3`7>>pbx|8%D!JMVxO_qor<&u#?_PaQ3$_^JI}tAli1~j0y!J&TpC>!qYgyEB}eEY)MuS@a7N(}o-cHtjLXknz#?2K_6@qK zzLQpJ!njwf-^uIm~RoSAnXk^6p> zoI|LxWGtSAW!Fx`&XqUrm~+k|%0yynU`^8?K=53J8UT_cGut#x<^5*Uh?G?J;6uop zB$5Fr4m}daID(;ftcD@fl@CdptNoUUDj$g1OdXT={?wl05S?@Pgn;my-~5V*5pmPh z!!X|8KRiAj>bkC~s%u+Ba^CN+_M1&ZfVu0huiso>@0zB{DymwPsa55>uG5^io96WR zcsQMyNJUSNk9AeGafmT~``vfmx&51)_wU|*`PG+X*bn`8A3n5wheSDNRUO9>(Z-ZO z5fp+CS){m$>~?!KJsb{&SFCDX*9Y&%am+a*y;1=#TH3QG#gcVY_9|vpNY9J&qluVj zily`xP0^|eX2NaYE=tTYFKTREXDiSBnE%Na<{cFSyY+?Uo%i1BOfMvaoYSf8a!Q2; zrjWZX=bYm(+`hei`^DRWSBJX!#V>!c+ioB3A08hb`}Q;rLyl2W5=khtCmkB9Gn0~o z2nNJN%+5Jq)m2?LO#_4?k|d{b7>=hr_RQ#{5U@bqY)7-euC!87!E$=2OVvGu^PA@17H#ZPl+_z|OBY2iKuC z1Lyt3FJlP7n<1GHk%*2ts%oez*E9gYNJQij2{fsAa-s5Iz(g^QXc9tI2C-r2QyjXk z^*(^v*mr=SdHEz2F8wcws0yBl)s&HG3pH0w(+tCqVq)g~)eZr+O>JP~5I38qX`1Wn zYl6qV8y=6xlyyw`YPY?*zKUb2>xvNBxn{dz;+*n`m^CvqF`K9;nVM(6*)(7M;;a3s z{j0zF&-cf}cC&f&_GTD{rfE3%;61xg*G<=Trdow?b9;M(H!Ak<_?T1b+KwH0N1Odl z#`NunkHa`D-)~(t-+%nrY#Ksz?9Jf&@4h`89>#GDJ^=i0ufoPCrw`i7Ubz%pH6vSW zmkWcScy(JQ5*pQ#*`PG-ekey zT@`#*(fN!X`eEn?5iy-D)J%t=&nXSV(DmKz?agMhDf-{t^>wpp_SaYK@zkD<-Kk6C znBtIA7Rffbrf31oi|W~X=R@T~aLxguim0mQ+?`JC!^7CM07{5H1O$tKYDuAFWtsg@ zY8?L5!|vTOci11x-THj|E3fM9$9xgfShxs(?KukdbfBGcW(_XbSMX%&d}3L(fN5*4 z6D;0JYXTHrY(dVCHV?*^M6h!cYhd&&;@;+bA3IN_=PZ|t7Xt)HODN)c3ST{%KGzK| z2-&*yK3!8!Q9t@*uzr=J?M~hWEfIYN<1i9)2!V*p_IU=))%h^Aof5m?i>qNxwPaB- zLLGA|*{LxL5fgE6Oh5)`szg+Jvy=r)i%3;fMZ`I$s*as!=X^*pHFd>~uJ^mT+2oY> zyX~9nH;BZAa?PxOP#ZIYS&oSu|LV`b*)(-sH>IdoRT##xX&NiJhQ!6$|Jy%&csw4) zF>bfp6r%yENag*6$UJeTNixW zcVmo0Kd|E%V@l$y%G8jcyiPC(-iyea>uUu=psqa~PshXIVdy(zQhlXN$&&d;R4?z%9 zjwEV=xT1l)Zke*BvHqh6o2+pIM!ZM`oyTk)`frYwZH`mdnx*ZdN{|Nc{5h1<7p0l974zB?ge$`KK&s;TOR z2)eF&ypPRhyJEoxz!*RFSHlhCRyYIjK?!&3=HcfMTef_&XeEV>C z6v?5k0=tjjeV=lUDW@Fky1Bo)pVIPRSmJ^ z^Wv%$;kj=OT4x>!-JeV&mnI8)Dxt343}zqIj%#gG!` z7~A=_qwDIs0@+q(^K-=Dx(3fKS74x1T+(IhFwefFz!R*1as*J*xw5Z^=GVNO{^BqG z$3pUA=Bt}G5>raaOpy?X`hJi+dhb(~k9YT=-`(82b?ic@QW(fj*0p0+xMHzCTAgn?>~N2 z5ivL%j*j`u_g@gxX45p=P0CqP_Q5yxMpQOn2+(%@>GZL#!*;t(DIJfetNm4s>3BLk zJRbhxcfUuXckkaH4v+uv```D&*!4rGyolX*Cq}$~c!=YuYQ(4QW^-!0m=ie;F1S!B zLf^LKtQb-xAjzVthtttSgLg!fVjPAM046e*_lgLT4V2lXq|82q=9LPtmUAAaa*Ke) zwL;O*Kuyt53tM5P{vjBQW~QX`8K!C?CFgz)7=lZt#>gjH2jncP7@i$F-@*qx4bRo6}JLtw`Qrnp=hv`8D~ zD|3=RC)F5-zHR$cJG5;cdQfFzWGl(WDuwMQDvO1^6~LWFzGYaU93@@83Jej(K;zFB~@&sjEuCK7RkH@B1&mcz^Tu1_7(O zs_Oc1I3C;f`ub|K+wHEeQ%c9j$3Oq|H|??e_QMCU+@AUrbKNw-`^{$a@#FWmw>N5V z|9Gr7n|He{05}&O9v)I0*>FrU=7azU#GZ3D8G7&ih>%m1oVVLO0;);hb>-?%Qz8P< z-ELo3b$+EZBvm1T$w&hcR0&Z*5yb!iSxJk19Ki%siTfR-g#Hbup=TO05laf)hr?+Ip-Ktj6>hWag6;C$1$f^te(rP zKul(6M2N~pW->7pR6)xeZ?@X5&8bV%M{^b?{gf&&E<51Q<@aYk1J7e30%{3k06jCB z@B#rTF*T-&$cr`f6V`DtA;M>M_lZUb&;TY+=4UyBuqIqT$FVQm+n@ZY#eI5Vkj+}k zmDFMFi;G2BN%*ALue`vZ*j3tv7w)-^u1Mps@~uQWmumgNjrwaG-+ucC=U7yTN*N}{ zj@g+hF*B1Hgi!n7gZKOW-aGf@7hjlysD4TBV@e2cb$xw29SO0nYco5ZdQ}PD<*Wwg zJ@5C|j%^qQ(`*J^YoQH?!?CKHt{a-V+FxC%Y6;EzbayW)-@Lg(@|$gQJazprbX_;Z zNJP$u5P}au)cQWAeCWn_I-OJ$07CFr`zuk~?RS9Cwp|vRMjx~7TXv{V%ltXOl+z^C@KVmNT>ER48!Yui=qb8{={Y^$^cXl0BB0C zJzKZXOv+M3Q>{D`KoXhz#HpgfIpu4{XqF}Ov{NdViQ0<%RV;CAvQhz_c0fjiOsdDzk}EE9Ywsl{qjbs>KMA|o3jDXOAMiGapM#DG7&>bA7!|9lzJ=Y8?N z1yb=Z{vsyZjkCEk&3U@3d2z}H1Vbf2RRtt?sjRMnDp<0?f3W0C^rXeWd5ZR(N-QoR z3hPZU5rO^Sh&(%MD&RR`^lZcN6#K>5T4?QWdErbl&jypp-~5tZ*xs4h;<|Ot`F>{i z^QVyhx9xE<*G7bMHv>2=X;E!56gE+2W-fy)GL*1p-0gO*3QW{gRbAKKyY03a#?<%S zsUMj5{_*(n)1!*+_PcQyZf|cLvk&>ZzW?;`!>_;oRo?GGg@~@+TyHnq+uOJ8=@etE zn(FrE#)oh`ow}|IJ`hvzUR8&2JRMIVRD`(OZm#zG&35A)nOO*44cg-g&Hn4({Qdv? z|NMUshllNUI}ZKvbQ)8<+FqU7qpJPg-~U|_-EMZ9O}*P~e)(sACP~0-=!cxMW;q;= zhvVtgwrYB{-NmtY?7w>V{^4*4RT%resr+WU-CtdwPHoqBZnteuUDqC~DqQW~h)7jA zW=6vlV>g@t(K(;92v{EDYwdtlm5~f!f|nO8s94m2Oc}gO2{ogVXoM($Q7w4nGCkS~ zZ!S>@1r45Ru&s(8WGz$uQqQ1d9s@8S8tDWim)%Q2ZV~&aGLf|9csL!7ry|O-RdHP$ zybzI{2QZx|T4rV{q9SFAwb{mX8sJO9p{N#^Tcu=ksfd{rd2xwe15?m*l(0?~*7LNB zRyquwsbz(zZ-_vqL}XlSWGA!OfAJmoPa;EF?|?s-)}M3{euaNLU9>7woqOVF0XWMa z6j#OdIo0`c4mRSlXu%(P`to43)XuY&$HLQkX+&NvdY{%{I7bXlT+C^$RkBWJbNfri z^O+sCQamqmqf4?VuD$v$C*XCrp?0=3fu|qN3VZnR$Ej^qwY)86SMt)utoVDDfLS6y zWHBgWR-%&cWDbd$Cx>AI&&-4&)Xa>IH7C!mX==xg84W1L0TJUk_z=3bD__#@KYV{Z zj4GMgACJeczy3PKoKw1edo%RoZ-4u@%&zPD5|fxkciYAQ+P2$Y?Z-G~m3K_rZR1@a zMnq6i=iSZCP1kk5`txsY-n|{;s3u@Ij!7h&LQLbQPoKX2^KTGHM4fjf^QUjSYE$_T z+Ec3lUw--3@pug1f9i++_T9VoaQgPcA5L8lOdg4=jph8|`};q9cVC=4>&hdNuNvoE zKgPZv2;q2Yo6VMp#w1_}W2&kO*}K|d&aYE|MT(mwD3lRR0T5APPLl>BFe3&4R5LOq zC7NP`qY3~!0!EuvyXRV4C|v;ST4iI(m8UT#1VBOpLZ0fjieyzQp_G$@q#$B&&ieqw zMH!4>8sp)38v8+Ku=)(}nwgm+3bixQEctw~OfkZ0I_;`qs;X*cpi#VXs?y#Nk{Ke=pJ)vFk-t0@VEkNuf1c%c<%BgCu(F6P zo6Ok`*`EA%N$Q=J$15@KQ%ZA*MMI?LL*ROP#&toWC9wdWB@C{|+)HWl3z+a6@r$tkvtJuh#hlT5>ttvMNkvU84;0*iB%;yZz*C1j6{SgQVcyDb8&`J73W+CLDj0t z*P)K7|8zHc=K%2GUhePi)GUc?>#DBmW8b%J%ShK(`zlmObaV5jt}Ev_$8odSY_{9K z{q29W)AAa*2FasnX{HIT! zK&{y{lGTL}Qvx$$7S*on0HLm%!{cK={7=rg7*mdUjInLouJ4ixBbg|9RuLjbwK2tU z7-NdR@ZNi;qA8`ZAI5R0>pFxgguru<*DJ6wLZwwZ=_C9U%P+31C_gWOf424eVhCG#DPKkxlzDccESU)rm)iE+ zbn4mOcUrT|W9w}2Tpp7yM7K+P(Q~Hpllv7Q0V)`+f8oNSd4ABd&lfIs_H;)1z@DMX zYK6UgIs2}&kmmt+z1v+db6tW5$V7D&>P!hzl^qY`AYyJZ_5$zy z;qi3$@bJwyUnAJ5ZQpk3emXu-?Rmp;6O}z!c|M@@u<`q`Jl2?j2 z5XfYF)(4(p=Mr7QP(q48%kHL}fFfFXa!igOCMg8wQh%4zj!+4)5V^*f8&3~I%vqM| zsWTisT}Y+YB8Cu}rbgm|0i)SCj;F(M==yScoF`FJBC5PYgn}LuLggKpj-!am0#h%B z8|Mpc@t0dJ{)O`!#J=ssi5 zKlcH8!g6OsnAeNabNVk#F2<`&-vU$HlrH}iVtv^m(qM_$o#Z|Sz{^R7FLnqo?^ytp69OPTos>G-)D{-PYdYca&Rejf@fYsf0CmcI_*pq&~Xyk z)HM=mHdU+Znwbqi)yHuV$#vZjvkXHLC4*2^08k`GOw2^4W-4(MRb4(Y5kW#njL60F zWQv71WJhK8%{dbxJI9m(#1ycQTIW+l%yP~%VIDm@L=aF^Km^CG3c&?WF(E+P4|Uyo zc1T=77-J-0^vqmb8Q9hC?faV${D<#8+}_>}{JpFE)&9zPsy9vF zwvWfhei(An-L65Pzxlhr1GA>t6dXlz2E^@lYld0n;qKEoj))jzL?#nZ&E=DfF_sU+ zIVWO|hleEr@W)<>ISV3yD~%kj)VO8cTeJ!~Ax!1^GbmcS>7)h#7!-piM--Sw6)7*z zj1Y(?O1`Rynu^9~SDV0$#X-_$r20wq1pvofg%Cn0t}JE-lDf9-yDq0R#T?Doi+9dD z1~3sR>s-ku1dd6)lPn68HffcjHhIN7t-An)rohb35fe=^=}9P@b1MHO$w_iLtFCN~ z*sYQ3i%WMx6jXkS_vY0O`11(-a~^>&Gmb77x+VA)%YqgbaugL@7h%aKK;*@{1D=h= z^ZzXR-}%82rNoP#uaygX$n|{u(n%@^Je%a|IYSMno4$e3k}|Vci%hQ_*FMqZr@E|u z7w$Anzx<>rId>;W&&KF~TI~C(Y%F6(WTb^XYgn_Rid5BkGKDOnYKW9o+rBr`l*LpD zFiI|1dzpV7k#nxoo`{)QY$m!FZP{7=1vEt!aIioqB3Tqvfk+4=(IhJ?ZYpRK-45^kxEKpI$JPacdv10%uBzuI-rZLr=1<9CQT~{i~%)z@VR4L}WyHD3w*QRD5 zs1}^dDc{^&1s{m`{?onP-QVBe7YkuxOgRVV|HE&7)AzlCg4pl=@Q3|=A7kvgZh1Y$ zfT<+zZT4G4Xqqavy>Gnf#bJSTk2$)RdEWp@_+{mkc| zzZp>+L@LM5bL}x@R8s^{EhJ)H7g{qrb>pt~DdrNRP*%X_+0+cs9CHYvssj=hVl$Wy zU4J^Z<1p%3ssxTHct;3275QnB7LjqxrW(B4G<7PzW6>_0YhY!>g+PQv9K5gVs;+`_ zY!h@X%bcEb&N)lUDW#lK8iy34#01H7g;kqf0@o`sA%guRM@%~x;HPmlpO2r>5_q+q z#2K%Z%Wx7bxsv$Y{XCK6o#V z9dW?jW`hV~Ad(z7HOX02HD$?B9`26@Mh?IKbk}u5O1Z9ssF<2cuBtGOV~H(#I6Q8f z4SV07T0~$+l@HB!Tl_U0)3+Z!G<9`*`?iRfy?0Ghk7KN=DyA57Pk=-)3?nmbHk+>N zPN!pC*YmLY8rQL?f~*W{GJp}VnwC5ioCuGGipEa~5EFrGqHaJmMYO==0u7^%sbI`f zNDOPZcn~$!t0o+}aS)mJzU2#70zjhRLtWR*PPDkusN{S)o`y31s+w8xYjI44RD1z4 zXH6;RoXs?+>=;Avo2Irp=H*wQF1b|v-o$tZ@#!5^GAPe6gs^N<=B4qIklhRGW}Pb96c8+6JoT&y$j_F_FJmxkUdGDos$gzZ#`M|G ziB?>#i}Jfl2wts_S4nVFt6~2{$vo>Wp5WCJ&+KL5^s5}(?XJ{XM+}6Uy7t}?k(!BG znIuFs#+apK&+`yd&Kb-Aa;QR#(Xt>~(=^3VvZ<;VqjSy&?}(Uq7>0R70%9gaqbW>x zjA&{qVrql{P@Y;vvZZ8T3`B?kSfnK7-4{I>GFhHm7BJPEvx?FiV_CTq z!3;jn=eE*hw~c1j_i;q%ySU zY3RDXZR0qqC?olriD{m9XT_7Ms>Ly^)i9%&SNX$q? zsxl12!~J8|_A!oBqX{5;M2oK=SB@%KC#;PT$+j4sK)cm{ZDGB!u9-%aUVEU`G9rv&0zDEM@V| z`(`VW)U<6|A}%O?j1fSU7>cNv$R;rfh?!;}qHgHNn3h(HkpNVQ)GW{8tQpbNm{$U15PH2Bq>kX1~C=)6#$en>!~s`0C~?MP~MKnB#MjUA?1Yd zN-XF_Pdwdy4JQ(oA~6Ar=B2tKBC1-kjzUC6LiEm2`Gi#ou~<4v79=EuP2kKp#GJC4 zC@eB}Gc#-ZF^+M+@xfKy5XYoqKt#d&x~_ew07#3!m87BT+tW#6V#2DanWsz+SgNk6 zh@_atF_pic3!Y8uTa|1!+6Y<@DrF=>^xkcEji)dS!>3R8ecR``czfmoIXpfbbBdbt zO5ChwCG@%g*OQ|sA~F*gm!1MZSH7DQ+3iQWK--^OhV*&%{ka}XVR~W|RXmJm&J>oY zGX#cW>^32;G+S1^z*U~SAOWAOZ`aX%Pl_v*Jfcfs(CT6B91F3gXHS2M&e4j6l|qw) zYrB04cpcsMFnnU$Xw=wf?Bt|z(%4pGHMVWLNn_h;Y}>Z&yr=i? z|6JF*KFwri@9eYJnx(xkQt9Sb3BNxIveb(zbrBkoJ|VX)RDyk$2KI7z`S$bU{}?-u z3BgMJ+;D^V#(tTaR@mQ&pOoo#U{44)?SYcGi#uAuCT(tH6^RCh%T1-gdN7=>g{6#C zT&*?w%?ey034|COQ$G_xZ3(1X-O>S%~KRwJpBDGdD!lqr2&^aOOH ziGUK?-;TN}u)|O&r79|TN6e9d>i&4O;Ca4St1+X0iVvi*AMt-7C)=7dIYDyhS&vud^pt>&7{lMpTBpy;OA zIoPM;+4pNZ{15|w=`mQ)L8%J=ml*D%9VY&;VC&NIg49a4`*-_rArCZ##d&~3)fZtpx zhZLr+C*nBowLoKR6w3HqUy1cu0Bf|YcPOijjueKtqF&!f!JpIMjR z_e~?gmBiTafOR2}n?3LcNPkla(m@>;fCSp4m!7s})}fF_?-rI0kc*CN2y-IVVa~%V zsTCLx%IBXt+$NP5t+6;xq-7~dXOu>ByB*GBzOcG|#jl^jVB_7ZE#vqCs;WKMS;`l{ zG7W0FaSs=sVuwwZ`mk&on(7!Wy?_ifzB!8>Qg%QGqO;5Nqw$AH2|ELWesi&6_>v@R z7Bd0mKT^Rn`&}iQb`iTxfrSI#P0LLqkA|j(me3%0S-*Yxo|Y9&759aYC7vOQCim;r z1b5Gf{W(`eU!oDCvWXA?&H8l-rKH4D$?awX6{#3DsD@r=_b2z?vzT0pH&7N@?H<q9a6!WS0RghjQT9AVq7_rT;E=^fqJLb5zjzDM}+cd=rAy< z%^G4~lW`80%k(~>gKF1KB`O-z~AQomfwwE7PttQ^6~JE~+_n^wv)rqfZ}DiuGY`)BJCv4If2X2n4pgu%;S znQnrH#!w@{QkbbUqS&4;n|tZOY%)1EF{UUNsK{&TEL+Foi)$o^2o4QTCeesW?{=Ug3tb9p!7`H95zJG0~Z1oMgwu9ylZOW zn@^~O|4NuJ#u!hAu9TeluYRs#BuH&PC>InB0GF*wnW}RN=00?Otw`J0{1VccLT?rz z381{&$dM}&+3k_enlo-OFdH3i;9P(&n(rVS<;y09EA?K@Yrs1!G=64nX%4lX~h0<$lzvf69KBN3pqR57X3 z4De?NR&`+{-mqrQq7kG8bBDPY|6FX-nSCb^`6Ae09uuM@LX#6v z%yoEDN))WC!kKY!ZTD-V&Sll~@#Ep)dV5>&?LaL=$-|Wok>+cX4&^yV#ug|tt(n#e zDC3CD&dk9@D5tZC3@t+s4G#`2gR4Z#fi@&GwBcd+9e5bJgeN3C6cNP5OU2DAf7WhF zYB;!t#E)uyqFI}2u|Ajm&J`I*9vi2798H%1iGyd_oV*R{Qarl5M?Lbw_J7Km0B+Yjw#)6$7J&5(!F?aabm_+=y9nX)3BjInRNj63A%S zf-YunOv~8Uo!ZB(u$$t9>?O_Zk39U-VJ1?Ll56xfUQBv)zm{D^D{)ny4(q$ZUOrPP zA}QIk1x5?L_>khIWBwA{=l26rY3Dv?1|KzE;_7k)Eoj>ST`;h-d|MBXHhQPK()d<# z1+_jLr`mjr@5y`1BqOC;stiLz5*Azxw?YlmgL1=iY}AnYOF&H?_j3H6L(Q0~J@qq- zZj#E|iuk>Y@|BG4LK~V4S}Sw#U$R5wW;L`<>81H|cWGucIMCU5N=WzM`xYF^ZWW-j znOjKcxa3>Kpm{9Y3%5zXjuXV8rBqJ;aSopQHSSog(uT%;P)$F68uUDmld!w&(lOV!k zKTp{koA{-0SSb_x)jxr_GB8qpxHOI?hDNORm??BgiY1E9Uy0gQh9xYCT6o&Lq&5R* zmW`oEGr!YTGghair7)h;r%2-onqbFndjm1WN^WtvZFud`CRBo>w4+t#^^?x#85B+F z5oMp|X&Z#81lMtl)HliPD7{u!Rt6&R9AiCQj%Nyzr26x(k?B6IDmak5-AYoxQyZKb zGv5=^)}eonEwNZzTW@dO>8HF9rorlma*+;>X`Yh60u&44XIcSRVxSG|hd1vp2gmyH z`wLY88UfxPuyLtA+CoFzR4xPb1x+>#44i`Qa3f1nyJ0!menZqFN+Z{=^J{Z+Yl>4+ zct(GQepalkuGG)07lgB@vhaeB7K-F9DU;_d;f5lC7bK~MbK)=5OkX({B<|`vnCy#G zkjzZ4usZBX_+i2uNK3Q%<#92l&`l_J8f$QN_pQyWgYkkY7*V6CV~K?(nEa46Nq#V&791*bGs4HB{c>DfIH z3j3|-xXTw^C>1=E9c^c+Su;T*T#g6Ns-M+faRJ5L*aY8vT4*bsCM1@Y1$jtQo${-% z6Zr_-dTE0_rr3UVwp58WO_EM~lCq=cED!vw?UH$Sx(X`f`Z|A-;_`ha z-QL#Ddu&SrsR*2tNom)C?hnSuuXSAeGd>u{87y;!G(pZs8{K8B@GFZDx}P#rQY9j} zQyUus&Sy&k1yzFw`NRmoZ6w&FIA(tu>vh45c3zrPh1ofu)Li4BW>+qN+ovFhHD6*etWi>RO{_9}d z+{zlCK}4SZuf^JIDMA7Q7lu>&q|rOX#a z1vrOOxk?j93mlYb`xP>Qyk<`5GZtc~8rc_?Wv#a9#%JmR^$Q9VwD*bS>_Y`#jfF8v z5F1bva4XQ~*CgcLD~7k^Cktt(3lch^=R$9a1wuf}v7Z zq{gk6{wY(ILaS3vPZN%BA87zb9kee|t^_I&4njf-qhk9DoifjXms$P5)wR>ar(+=N zXP%QvYL%uS2#}-^^DmH2NiPPMXer7_%c`H%Op!_&N(2@whY8^>EX*y;%&lo#Sz2FQ z9G5ER6%#UCXxIL{Rvi2>f+#`~YnVH=HkaREVPm7yXq5)Aw-Sa09|y+OEG$VWgOMKn zjEPbxPYX?}S8d@&7c0lYVCz;zMB+*0UuI5A&8^5c2(zjPVnATQs0+nXrH8kYOkKhf zA*;=to2r(}*pFl=x=6kW1GxE{G~qy!wB$7};2Z4}YgZ64W>SG>pZCy#AyLceeM{cAWuaFyrg@GL^t%-}q( zTN$g{chPTA8t-?*ck5r3gBApDR`AeFUOHEpXjJxHCH2gzBT2BniqXsJ+@EDgXsS`Ry!vA>jQm;1w}>5C5fX+5;PVTwDBZz z%_+G~`cWovL+K7JBH?)wINR>3; z9aI2j-9jlWP@#MTGox6Yn*7gcDP(K$v9j&2@8(=43P6$oIFm`r=~Q)K;>?)w&eBSs zoJbG7R3N?9{t%l6$kn8N5nyC#lm*RD;TwH!uq~)7d}V(aCa+%R zU-Wo35obM%I=YFH>-v?MaTzA2$lzGm;Fjeql;Kfy-d5V#B@41aAZ`WihaFcugFzrF zGp1Tz{G$bP!=c1bJ+W|UMTq9{BU~2I?sr22WdT1Bvp-O=I4LM72sv?K0<#?KK%Ksv z-CoV*(H|1~0W?4P91S({BnEH^4KB77>PpY6iH4TJPWfp8y z|AwjZ^l&I6Yt&*A*d1y`&6Lr75nPLk#GR$o;v!738f5SS?J>aymwLJ#nE}+lxCB%M zxM8qTG+CJGsHW(214~I9Mtf8W<**uP7;5xrqBN#-W9907wX*6RsY%py<)LX}L+JK- z_ms;%^Ty<0b-O=hZg$|pZkJSCs+pP18RCJeX-j z&a^lUhZ6^9GGIAwO-U>?Y-rvPUQU@zZ9Guv5YzJ1IoUioc|3BmL}7jJk_rc3N7QRS zIKOJ^Fe#%?WiWuE0lylj!mR-uW8yJ)5`1z9@lqKorNnk|^)XlML z7#PN*y#gR}{{*8>hetr^(5lfU4W+B|YKA#z!1w|BnIrSU6OkY%G#M)w__ti&!cvVe z@K}0;aUl(;Rm*+T2r2RxR#-?ZDzZTS{ZmZEj53#F`f9o_BiT8?P&ze(EZI~5nzLb$ z#&2yfOtePTL`9KgG5a2wVMs;&+;5Kp8Vh8Qr$<1p-KLsYixN>OnTdr~px&;3PU4M`1OiG`WV#rdVf?gx(DC`10>FH8# zLbGMOMcQQK85A5CgF}h9;$!j|)sx%)Et;wUqG~68d`kCe0px=^CxweZ;(J}rv$0R^ z8Bv-3o2AI|V7Uyn$2$4P$&AuFd8K1Q^9ecgyk$3$F3PR?sBtxliJr9XCLPYm1(iL2 zYM%;xmZbG({KJ(x@4Y_pNN3@I&sFZ3H~M0LB%#AxAt|>}>tX^Q-$LhN2xw$LK#Xum z?W?4=AfLr zy8)L}_5oRaDtM6RH@>qyCAuW#Q9DglZr2#wAgICL=!R(0LVVf^=F5l4~!bl2FTI6H&T!P4cM-EAt`}A`|onQCVksgtONdkcQvg-d+eY&KoG-T z4CdkbAC!YEm|+c2D`*g?;tatUxVgF_q7Hs}|HyJl z<_BE1DARs%dNL3Pb?XDEvXgTb+2c+}GnSx#d#@Lx;zuE!ER+4ser<_`*G90!a=A8F z(+`HY`txDcx@|o08s@C+vL)wvtR6@24xtkn=Dce&-@0kp{jGW3dHFfP%xhl)ZHT|P-c0rm@oRgYCRv@^tsqJZ%41%W^mf-7ATsVn;&-_`c0M; zX%IanRHGZ|h7@Ic-t1w>XY!fvT(n)>%vX836%*wnA!Wmj8mVkg@Ln8gHb#c>@bdb6 z+~#CCJy6wQai!X9y6z%98XSx@nNE0~{)PE)edO<2H5mNzs&PfIGGunS9E5<)_tXvH zXgc}a`~Fy!OqWdL^HwuR>?1?tba6Owdb;&`(Sg(b)yK5{Vj{TzT z$EGk0u{KDJX?wt5nn9NyR+~+`T|2WWcS$kFj)P&VFU1^wQ zx7;Ep2)-W6cioJPR@N*|>o(hMgZ|9zw&Ohb#qn3?$LUt8X<0v}IC9lF;AYI?69 z<4u64;q#_P$Nq^4IY0>EudO{vj8pfc`=?GDO2MM%N#d8S;kL`xQD-e%r@PmUjIfjC zI@9+>JmM@6T0rm0^L;cUy-6N9;ocf8odS)Y9yq&b$cnO^R~(t-Jl?{nI^UA29%fb6 zPadxDs|RTZbBMfMFV;-w-ak9yd}zp<+xR92$fWZ=C-1k#X4%5&`S>e@19+ zYXf^b{QS6-)_c1Y6ukMlOCyYW*0QL}z`)?+bvKQp>-v{n*Lk=gM&Jh4w@cvVXil1` z?Yc07V~-}adLR3uw?9SuL_piEe;-BgZOZoI;~YkgPnhOoB5L#8vc5>yeYh7z5V9Mq zc6@62AGqz$m7shaPe!S&*_>9y<6JjiziZbJ-?@A0an9m=JjeJnqkw`x*2MIl!)KpA zUJ-IW2QlQ0;n$!)$mwz3<<}6HKvh{I^j>lr|AQK%rlX>=*7W>CL26U zFuM`ckETIlh%KIHt%~FY*A^t0rcLLJ*Q>>@53Fv`@A`Wl8=rP!UH|!V^atSW^|;=& z;p{O!diOU3(7th*j|m@StLx(>sCH)d-JQR)D&yEkj`-zP572%$^Xu`@aZ(_KpMZeA zmMRy`iRjLo61ls2yBDlj;6b#5XSZ(td>g8Iu(W@z#gX{+RPPj@*lmyL_5d_}>Y|>9 z^>m)tGei$Fp@1is@8-JW zy%ep>>z52$?y&nVdHys+%>wW(twkTRmC>rT$L@fC1RQMy;Tv{3;Ior2X>;Y#u|vRS zmi6mqc;8{!&F!_-u*&s5N$rKF^V$@ewP@9<4#}6E(LF`S1?(zrR&E`zXtbLUOMJ_W z2nPCv((I>Yn_;{=p@B+Y)wfVHC@VbcrV}9H*bktDv*$(^!DEn1iFSPGYFlB{(kxLh4-@EalL7GAPS+E8P=bnY3(KuL%#ho z2F0pr-T9&{f~n)KI{?|j+?s#O7lNt9s?<{ZVt+xfnH0X)u4&!nbB{acWv)mtOJb0& zitplSmviOkACcVZW7CX#wiPvPw|Vc^%gwntWqNG2qZx*Z3cZe_Jg#V_t~*fkGxZS5 z$`0pM>!x*!(~8%B_*XTQ8;r!e-CezG{s<-jl>fTBcfTdy8+;2d>*8<=`H~sjdYJ8T ze_L$4Wc|3_^?ZIxC6_)oH&?%WG>t(eCuLgNRQZx-gTnLNNF`Y7HF#BEi+C02c6;#U z)=$ZwOBTuznbmeO)tJ)jkswHVD}4E}sMO zE2RvZ+7eYM8cH%l)4cYieq6T4br+W<198hSAs)S@#{J1chI@r6P@cu9V0uP+2oeEy z@OGSd$78vC_Bl+Sk+m-TJT z9u+GC@Ia^!`3Hj*0iz%Hlt)O&m&;CSg0LMuXiJsfOzueJ^@>=A;*~mq>+bE|?+8W2 z%m7!6yWl{-1O;PslLok?H>|}_a>sg7kbVFX1o|b)nz@UE&^^w}mS0+h7gBF2PE`9} z)J#4pmM=elTNc{Hq<}$lOQW`yYyTS|e9x zpj7Qao3@A9N%!E+lc{-gz9=zL4+dq<^M0Hn5PKkMn_t2u@;>_e_{C`tG`Vg2Hm`RH zvcr3}%irh292Z@k)N>(K**v`g}j3t9qKR@^Rc#5PyG`NAcMyue)q}-1rm2->Akt z7bC!PKO_CHY?hPr{)VGry*OH=>wG*n8g}%$*=9c3@c@2xGs-0Ivp+BXag$P|ODCgtoYm5x{ z-IQ=TSm%9(?Z?5zCdjj8O(H)bbTWn1PQ8bfBJcIyuy}%B)p;|5$7cHW948JU^MjNV zlEuqmV!r(}kiPQXxcYHA#`bz#Z9h-%QqgbEXEu>Zyy1C^%zLrqqXzhRJNhI4_I|nO zd2Sg(Y;XKI>La%J+KNEs+yUKAYPi;HKbT|Jb2}-BvQ_+N;}qUm!0z*XkkHZU&)M-N z{@YxFy!TyXOhbL+LCTalG0*;-lE71!{JZUfIz4s~q5DyWZTs{j%e#8<%IYc@-|ZON zzv-^2GOxyF?G$EB&Q}ZuHz0B?RAcDOM-WfUWLe3Hu z6eB%Vt}*+(rT5kHzWXyEC*Ub|8D9D5gpcUkcSve&r{4ZEP8Gge4#eLdR&52}FMaA1 zcd2BKKIto*bilYQ&#SeQSO5znUt{<`2F5fd?*2_v471&vw0{0KKk$!|RpPP5}^!ss5a&U!?r@o}~8q5aXk5 zKd%Ck4G_l`D)gWCK!AtU&!dZr&fAHcvzo)~3n#au+z_w((ND*_=|Os*Q-1Ha4xcA4 zRU@qKKFI{{&o&R!$x@5qwk|VJg4?gzx98i;vIaH8z0~h#wWo|-U574Rujl-2`EkQh zk9BL7<`psA51@(;0;kQp(X$X!+TxM8++Hj7P`8JVFBLThj)!_vi%qAwfQvuKI-LXB zRsVgWO`l*e-#F5_K0vCkv6nld_q$x?H*=8Cx-`Q=F|I%&g>HURJLWG}0bhFc8ib?swoYKPWPbCY0o7fl>pI=k z^*oM}^OAdTV7lnguc9{T`hNfZxO|8~d^vmmE!GI%ep?J@)Be@k+P@7!C3aYUxFZ4Y=rm0nxnkHasI5}&9-hA|7|3j9MAR>QiySL70<6{e8&##ptFV_ z>n0%Gxi3x}MBOTj#09>Ha4miHIzJKs+$& z$K(z;PV)1*8L|)DfGjkRPp=1V&k@WNTKKIOTQAF$FD_iifxDj%PrH@-=iH9bT)#%p zLgd^$CNljV*IXCgLF)41McaAJYGqg3VK&yua<5UZMm%yCXd|3z5T29$=racj)?JhJ ze535Zv~?jKaNXaoKVB!FhQwQ2TWga?8C&*dMvJ_6&gv?kSLQ2C`i9U@K&t#d?abEe zmY{NfuxaBZS4sZ08%FSHSIhQ`>tvLf&aZ7XpI@uzoS#?XDcZlbyFGNfYCe(zE#JgC z&(`4?Bmrz@o%iRqUS&D|zZJZjcV{E482z*#Ja5YK*m! z0{~+1)!7#pHCk3Re4U+QuVf-HF6pTq@Md~&=f<<~Ciaz5sMtak&XC+5wK-XW7Y zKgjf&EP|5BeWe*&k9NMLH7|k|It<#X=CwEQGX(sGIeQ|afI+6q7j|F1*Y&~-o0lt5 zluol4{6%vbu4C| zPJr7D3<@~UzzxRW@jko|*c_eW#&m*moYx%}b-G%2CwRqe+OI(#3Bpnv&b@d?%fooj zo1D*Y1MQDqm#0N0B+|9^=A4Y2T>t{%E6SfS^Fd5r&vYre4#W21T|RZwf9eJVH+(jc zdCy$0NJHknoXN0io)UC=%q~{7J)AD;c=Wp1YBE|In+`p{I4#O`?2J@--uHCze>8PQ zF9TS*@tvFAp9WL3-IrChY}co!YaRt&jnAVf_VCO4_brFn7fQzFmV1k2mQ8z}-XE4< zb76>ax5ghe(-=P^+^v_V!o@04J3V%za6CT{-kT7OB_CSrUo~wuR#qaQ5w8PwYAo#U zSOy8b##p-E`kAud4h6NP3lyKX$D2Ga4~UHiWiq+!|N28MtVq(B>0+t?LL~^ryzW7? zE%rq57M6o@dC#}Qt~Zq$b*rt7_%ZE1KCJ2KgOI=_*~13ywkOfuM8UsK>NJw&6hgs>PAd zJY6mAnjr*Fm4XfC-HJ4)y0s-%P-mLvdV-V;J>Pc=5CbYhwPY#MT&uVZrTUycD6&9`y@96i_V5IO#NED`SKfFf;&X|YAGU4p2r z#VjZg)u;G8OY7Ayc%QGFzVMj#_6b=mS##Trg1j68Wht?LlVS-3z25*;^Xi~=zugMB z9GfVi@V;GTXJ>;PJKvPMiWigHd^{$d7Ihs*VB|k$^@y%V?I^0(DBSMZ7r!x{59}Y{ z=rfVrfG-(gktvzfFUWs_vhzB<9)ex~Inx=oA6I%G@$b*~w%%;7o+su-S?(+59kh~8 zW?)=Tv7#ReT1RcyAiC*TsOEiW-aSQrohm8Pb?V3B+_>Y%VNU=p@O38Tvq-Tra>LUx ze|`s;zi44!DYyUeO8jGyapB?auFqbZ8WY<4wnLZhAI;nMlgaa4sCVHK;K&I^Y5X4n zY1?>%J(PiY5Lbr`x+AIe+O(ZhZrIJrR_+h|iEh26a#?%(^Mdb8{4sQVdpIum+=qe9 zq}$#b&1-tDrtNf(Ga={$V*Y8>^Qw=6S0ug&Os!9ub(3Uy#A`Rb19aZ^JrM%8C61jw zv$7glQXzCzA1f+q+8>)aT_mvney6ihixzKUQ4D6;_5*KF2ppM)aYU!+`I^zyPOgVz zVA=blXq6o0*$#n31ce;!rIt$-@=mn;99NuIrPSih&DIgTMNSs^aFQUwL;$NQiqv*r zE>{pTSn3-*Iev4s)Lo5l@xLK_!Gt?yq##c%2+C=g+u>IJ=LwF2{b%6CcyG}ygC2r` z{Ju4<+yAc1!CgUH5;A!6-;;7OS4w)&dmsPZA#!UUCH*H5>4GmeTz3zWEtH?UEh4{--v`dyGif8J`8RW=YcklsQ3r+uJPqPg2ex zh8@T$40>En``_JY(0@~phEy3JZnNxNng3^+f+Vj5;Pp!6f8OYMm>Yc1>i!v^_;bD; z;Q!~Zejx#g%KwS%0Q_qC|93r3TfOMZ|DVHpAr_i`1Lpr;*Tm8{^MBy@`G0dl-%$SF zB|BtJFlc%IeBcVX6loBR)^=|C>5o3C*g-MTRUTl5i>Fe>tM++GRw{}!A4RTZXu5t^_l89TJpy;EdOV?m49F&0LNE}-ggX7Mjd zKfd;DfT!21TQZ%Q?-**3qR)x~Y}9Tn1R+_pfQsB2!8GFnX?@XEJ!ul|B>bfVhn zgHWEW!-0ktr)a@Uw<({O1B_u82$RNPAZ(gnkSc338)r;0A|o@T9C0@)7?54ENSMx; z%;LA)nhaX>UGzEDDp8JPSE|xcIssFP$d+jD+hZGG2l<`lultBuk!4AQk(4L)w(@DKeyShI;wq4IHH<1 zvQF(&hE_Y6NMjFlIilRO>^?05Of0;OrLmo=cIrKpSr4xNFXH0i;Xx!RSy}(IU=oVb_yCfVVe6AMp-jqQ`UCddVT2%sNcI>Hqx1I+AyM_?JSC!W(7^p* zWAp3M+t6{41JW%jFdO#{^a_wu}UGz}vvWqAa zYAh6}4oq5VC@dl=G#o4 za;tq!RK=UOj`fP&H_0N$Yl*yigJ|R{7Zx z9HyI#MvTbE*1W7p!mp|O!5{AOX=#0RBih{?3 zYmm`sp#~uKL;9&tg8_oo<9=m`fJ@219M>b5i_kj#2GAvbK$D@u^)+xM1ja%IBHr{; zhh}wur~O2ST0Bp);*e_5kt$_x^9iMXJ+r|8k{HDmmw+RnsZ(7t0O+t6;sFbIhUnLq zZ~HAB*%-I9%jWU^utVsO`lI^Wdz|PRO*I(kwbtv1K5QTo`L!IO3;IJsfh;}tFkDoYhJ z>UbXu&BG-qj{;e-IM6!e1}RR&>L|Kf$3=k)l@5V)oaXpi$+a zr@^a(r7lsrP!E6jk(7ttEO;?1P)-4Xit=gRKx82J^A6OT{VX{Ul+lCED>J)mc%|$tndX z;_;^#^y#(Wg4k&&(ZB*=xWnAqLFbKcK?o83g>DGgm_2rV-+N&weEAoQ@XlZibaKEC zqcDbtv)hxJbR`OrdwE1FF(iN`>hmc1(Sznpvk()sxZ*(ED#g#?R{N*kGaMr6c!lH>|~=t4tML11VG zq`no(=zqzqpsKOSF)^$HWl+iDN>#01MpX!DogiokCdkX+sScRO=Q*s(Wx*u@l9lliS}X+A?DBJeIb_`K|_E zO((MmAX_^stoPk_*Lu&kYg9$i%nN_i;0F$ys!Ma(k5xNGLu65_oKr`&4#=y&MpGy{lv{LY6Yl{nnRQZdP zjo%4z{G&AafiVJCt|=*`G`Y4HWFS~_IWHP3q&<;=Umb%M-Gns*nQC8aj4EWhMTH;=y1xYzTh&0G1;OFx(|pd{?;h4N)kXf<6YO_{(BNbl-^1P|tf(XyUtTtA9d zIG3e+RHUcIUq+9nE*%fXTBJE%&5%ozjMMyMuS;u&CgJ4I%EaXezSMzQOGI(cd>B16 z{GfTQace6lnv|K5euFc4(WVQnc3J%K`P??)PU4G)Xhp?a3|E%$%k!0l$p^0nwUZ6U3}9n9 zv(d(&qlTg;>(39xk{Ie3n`QXUD3OjXZ_U~+)eVl$49t{DUlQr#4y;i3TUyz}#j!2A z&ET`2P*bq`P!rxcO;QGR$B0us?n=b1sR-2vo>C6Va2vf^KT;y7lhRd(>199}vjqTW z>Sh~;S;M+b;{qsIw9Gm!=*Z7_l!2tmalbH-qAFZI^7?~Bwqt2RI(gpvxuVV5zrA05 zjX^{RdPcyhXopMZ!z&m}7wVppO8RO9)2MewD+VPd3#FpFyv1r%P*zl{yiC~3ZA06#Vne}*_gQd4acLrUK> zfpAI|+%H10yDL(Iem>oN$2y|rw!SR~Ln#-s*5Xpf{DA-2uGBygA%`8x_1M@JQHo4w zsO^o8V2=Ed^Q$`>qtRsbea$hZuQ4$#bQaD8wumTTOpQVA*;&~1SjoomyS606YOb%Z z3bl+?5~L_=m=ZF7c}dIjyg3uk#36O*nCE-Lt~_5!TiI)rT47aR_`-4H-(I5zf4`1K zqK6Nfwzb!$V|hM77m^r#W3c#x!UK)lHnp9&`9KI~VxO%_t@f80t^UUC>x8OK7N0E1 z*%2tPM+V`7ft9ljV5V`juW(~ZroQoW=FsRAIZW(LfP~|@5 zW|C&A&C&CKWC-P7mTR6Tb{~I+t*%VxQb#J3dM)AE#6X%*EXx(F(v=jZO5?j^1<$qs ze^QhShf|ZQkoQO8ieg0bypH3cCXUXxG2H*^;&|^*!p;?d9W{#DPFl`#dEXxHPx5;a z#>_1)Zs^YaPNTU!s_~b=5jzThn#Dy}%~32#w!RWknLSD+-({Q~3x8R9rh|vVd;;!3 zIkf;1%kBC^6F)24-(4ZOA74$cqhw}y{v2QeR+E;T9xgvz;Bp|E7zEiP8R{gUD}x_( z7$y35Op@GLMMN!Npbl`@{;Y!rx4aiMA(`#O9+m#{$g>-t><2a^HZ-iNL^+ZO4h*6n zES@!#rX(7Py|Argv$g{R97={oArwOAT<(Xmz2iUeMsyU| z8xd&Nn^Y#Z$zR7y?jz|h8Ky5uRWn601<<8faDRX!(Nb41;1S`QS+*$S>+goc>Q@0g z%Hc{B!%<1g`=-M)f%F`6fj@(CG!fdl&93u;CUL$c?TST6PxE|JRdM@@gl$wZuUnEX zr!<t1SG_j`shhB-P)Nz6;^IQ(!`n*Hp)av#}g0x8qhjj_%lcyajCAI^!^E5Q2em6XZ z7@~U3o_`p{4@2wU^${CT2sP@Ws-YyXp^@m=xKuV}rcSJ=S;iyrw0Bs`WI{<=^MsXTWTvF1st4eO|0NCbb1 z+)aM~#q|KPlfDU1?#2=G!AnIEO}9VWZManFTt1y|jzV~h;?=~lOVO1l%9`H|^oC#= z?EJhP=X^fAWlKp~K+20JEKru>50%N44l19cPK~9-QhC`()Si)iVU?kQ!ze6Kp7MuO zK^xPY@fuq7Ll5YW=P{92*vcQukQ#!hy z$MYpERU)uBI@|H6$0&8^xi+lcM73|BCG{&r0W2vjFi&4hgan(+pAtifFf7adRUCa-K0Hg1YXCX^@|STfin76tdDoFRhsLi=*z-|uVIMkX8CpQgrAkd>{6j%zk) z9@#n5Z~mK?^f>Mo3lQ9(NJRg@q4|*xkqk9G(}v zmyDV-+}{QWjW%@FbZDn75weMYbF30NC>4h^K^u$~-ezYspnLfBOD9`kpq}OROZQc3 z#dsx|`jtk{x3h5E+l4FBl-&?%m!8xf3nr%Qh5by?R#sxDFxE+~oGVTCPXz0YqsqUb zoAoL_k*K^lwRpsf$MAUe)RX&D4*(SoRrMNQOzeq`{rbA2Sz7+apcK6foQcfBmpbV@ zW>qu9DGMW!u{-YS>p=vMXh4-KoP6hiqQqbcnqf~4-7|C!H;)F zlO?G&BpEn7 zy=WVhzkFGztLmJ7vKFsfF*MHgQeVwWd5!Q_1%9#aSL8mS*SaXbOB|JzJ}4)wK*C5z z;EARa?)FnHSSpvc0d=V6brXr6XZZ||hi1={Yi18*XP^3RS`bs(!t0hx9s7;Fkz*t* zP5)MP)#8rT0aK-fyV1ZSPQ$0p`9k`LLoq-ZWfTWk>K?&ObD1z3bGs;}lSEOPz7#?W zJ&O06BI*bW!PMVS7}n6*8Z11@kmGwZnQ;&qb6kx+sUpxA&={?w5$6B3T3-sD3KgKv zwLoP_gWO(?$f?ve7e(Y|7BHH?+&~i zO1WZNm)sEwR_Xg=CbOuP;UQ-u_$gV@5bF?ZYWI0-ML@V>I0Nce-I<2a-|MoxvOH*8 z!1#=pIgTAxuLN-gI4gl?L>Y2M9UgtfK23=LcA6kN>p7ne=ra}olDd$7!7tPS)8B=e z(b0`Rt~08-I9@9_L0B!f{cY0yJz znCUEw30Id^xKvJ{ta8H`%7eHPY|oB}XX$OB$YND|u^_4se*bAO2eJf)jTHYH%w-U( zNsPh;#KNk=4rru=k;EGlOfoS=kL)L>#t?dJ?cC(Kq>RVS8OJK`g1-Fd<21mjaThf? zUy)6Y2{18MsYU6EEr;h} zU~_r=}a-Q9va!ToK%|GW3qtGah< zYv89R$X zIEYbG3)py-$wm;$G6j+((a^7UxCRM5Z%`97!621e?1_USlEBuHv9<_zM~1=5CduQc zTA>F4F*O@`__e1#dX!v0ChlHrCQGxp54HE}so>S*ej(L4fHK_DuU~j9rf`7V4hzyc zm=be2y=KHfnF1%u8D_XtCqJDL+WK|Fj9POl*+^G;t+JM|K_ZBKTw3_34DvUMI^9G0 z@fFKZ2=$;aXJ!YgQFgZY+KPn!+*vW|;9sAh3#FlTl}f$~=Q92sSl`zppp_GwPU3EMu$VPc9hDmDF*X(+HZAuPh z$R52RTG47OiD~N`h=hJvB0q+sRV!`KElrw{AX!UlHcBgxWdQeS0PP2DYzka@Fh#LV zql~s;3S-1~C5~W70$OS%Bjm5}#0BGbv6{Xaw+&Ki(o*eraf_|cLADs558!kp8KD@{ zsL)Ds)B3aDUz6(&$Dd}uFyl5{4}y&dTAZt12Aim5Qyeaer-1N8%V0-@u?FAX#0NWi zXjv0j(tv?skWjPf>tl_fic;zJV!D0C&AosMfiMwXn**>g{yblyV|`&xqmUS`x_QXO zO#|nyKfE-big2OQeamufOW?685v_LsVyMgiGP4Pv>rbMF{rj8q#!PE2v`SgET0?0W ztsLUO_rGRqu%l&Z2!Y4hIs}xA9i<@G{hwcl7*bg<#~Xl+T;{wOe=?Nt!Fw7(?r_MG zpu15eHl?U2C{H~`a!SwsgmYP1ny(yD)aFoP%q#R%Bl5karK9zkn|U!4am69hsAf2d zvT(m_PNb-mwKRvd(2)-S-|-`VrQ{Qb0RR<=t`%t}6>3II%Su4HMsgEeMk6W7;b!G_ zQe{~p!yCzs^`d2ZA_VfvIFOW)N;}{7BYl`&e3*1i|S(7|% zTUd^i@ks_^s_ae+JglHL8&kU_pTNdy zQu&hXx^T(8-J&{xc81t$vAluC#k81y3*V4<811i590_?41*BFbc{yEIV7>Xv%9P)O zx6tG67iJ4<+jE`9vzMmV>2RNm*PFsx_LXjY5qzu58a)JqLfr3I>5vx`OcwY2hzFC} z-veqIOL05vs>?6L)VbZH6bidbB$%XtI3-e>ItYd3BBzJD@X zZjuwv&TN8f5htJ{n-LD)O8*iu39r}f-7WEflRPvm^-mCc+AZ?2!^90R7rL!y+=9?+ z;ySA#mbE-(Jzwffj>)+K8#{4DDtmMGoWu*$g5xmFOB1GOu3D>45*SLU6_y4#I2JN8 zg6_VK3|p4qYK##VGh3N+Rueq;R;&|Cgj8xWgnii%!Gl(o z)3U|F;`>U=&RCj4%N|?PUm+?Prb!TQl)kz_2Rc5>3ioI7up2w*NJEZhoRMexV|LeW ziyom#UcA&g5m{I-`ze+oT{7xo1wABy$T1XBw1P?zBCUPq5ilJ|OHBa8{;U;EB)9{% z%)qFX9!MhP%|m^dA9%WQH5vC)&CfL zI`qBp7HZz-ILvtKAX#U(-+Vpoau%_!nQjUE)GRG_yfbqd-y2)Azl@b=W>zP_!wQ)m zz1iGQ(x8lZzyfWF*x#}L8Wb+kcp@im|M#|@CqgtFjg?K*akPg5dKkR-wwgUzv2@-9 zD$`385eoB&{czH$vOs9&B^5IP`y;vx(2C`W5aIMrntt;v=7LlLW<3tMOt_6xpW6n< zIPY3BC3i2tQH?JBjn5!Sw!+K!dy>W3ubj&b4ez^r6okh$-_hZfC~ok%8U)^x*3qBngu{2V%w2VgMGleTH4kF9}5ku*X#GSmD)Th`jDI{+ny zbD5MhF@Mt-!NVR)M9>&*i_c$YUbK@C!pEVpC)GTF@s$oDqd>o{15L!ph`eTEoio?A z?mM<@3v?LvbWwT;R|6*1di)559#y*GXfNWdL;#Ska9OQ5X1TU3ML7d^7`~T$5uu_X zPL)eNfS8`e`f!#i{rBo)`4?T6eQ@$vfxB>UKFkQ_7Lz(9iZ7GdO-@8sk7YH)Z=Fv~ z8)g7)XTy#Im#wj7` zKcOHU#FsJL1kjFvz%F?HKUhC{!yuhgBgPE*TxmDDyg%ffnl!~XEauAS}G$oPzY z6;~b%tv6%ckI%t8)^dGXWQ`+@9~4!_{#fvmOJ$`wT&PrLDNIM7v%`W zalS#gR0s#!P3_abCs+V9Rb?48V|QRPkn57$sQA8U=hF{1gHP5Id?qkPn#t#d%5~CO z$E=9{`E|K2Rv$~w#G zq_pdKfJM-8amD+r@pOHK!C2DSXsMVCR4y6+q|THU0mD8cPDIhh_hl;eOgDnrh)=aD5lu(|nmS!MB6d^@4(Hb?S;Um{pwJ+flAV0?w$L4mvUlwp`Ct!?Uybah%#O3yU9*JU14Da*x_AS z+8WzJJq;MI)K6)sbevU!v4R^wE(cf)XRE1kv_S?&B>shr_;mup-Ctj+6LdUC9U}67 zy}G||((`vk<3_g+)C)~iVbp3ih?nEhZqPvYbl>b{YFz(|nf-j``>^$~NWk&zPlBG4 zk_N@)^jO_-zu^t`^@>mY6Xp9+2R4UZytOnc8Co{QJ`O9SX)G%5jq$k8%Nm9a`mWRs zhiyqMcLX~Mc7-KCwFVG2VJ+-|#D%WU2yjRX+oYA;88>7bX^CJO3TzlE6a?(Hn1&)# z`Tu|?CZDjJHXIf_t~_Jm!}f$&_^S5n$@Q33gxBmZX3ScPYRMk0ZhfEn>56^ubF?uv zGH%)y*)fzdVbhPWhEsj#_(bUT?MK)3C!VE1zeO{k)2PWAje`sNp^~3X)wH-`%A~m+ z%bE*E&DE$|?I_DdB2VXbRpqW)(t0iFf>)VqSG(;(A>r8Cy5^*jGVmhf z!~crZM@XM-kvdTkLnoy&1~Ea}Fo{uO3)j{1O;6AFuVbvlH7YB{n!&E@xpUC21+Dj(!aV$k^Tbd=8^IRXj(%jRvN;& z*{5H*9BRw#GLOX-qnkhYL;e8aeiE*ilr!R!-`UhLw2qhUbhDT@iQ&3vkMVeO@{d4MJDPkR_ zeVgm+qoe)1Cpt!^c%)dCqp}TlDJ=z4D7oyjdO1~!F*efRFVb)<#=?XnUPdcTb&#^b z3YnC=aQoqXnC*E~>*{lEPsnpCHO$zFN5w%&Tz;;Xx)5bEC(Bg-AC+Pm?KE3H?4erP zWd)4@e6&1i9BU8iX@xP2U0%x6x}Wgm6*>z;P1Jsn*SuwMsAo7xusywIYygI zQO9rslaQ!ys zc0CmW&M$v=*0zU-A;_Fg=HY6=g^ExX^N0TmU&hHQW|%> z)z=G$LKMxBMDZ88c#0ydF{2c81X2<()|73G9S&29nz@*=PV>MsHJh|G_)83{cSH)*jUARrv>-3h9;)$rwn673gICWf29v6CYjB=MU2OBS>m@aMrrSdWkd0B~$M za9|pu`IZ$fi3}1{X#b;h@JXSO|2qZ0437vA z5CNN;FkHLmq>HVf5FBU-96aRys*wn&)Z<_MnYBFu2@8b;(Jcmuqb$_IB*rV9v8aOe zB)Y%Zbhvv!>Ru{j93SjED+K@XYyMtc9(W6*m1 zO5EPACJvU6! zu6!L0g{f{GyiY=1pf|UrNfrGr&(4ujkZ$MeZ%e_AZIJ zi3w`ly%cKSx!5v{63TqaoD>LO`V6?lr}Vgl-|+6n8VrDhXr@g{d939DEyDI=22HR0 z{LMCq)K_Dpq%?!fvtE6ddH8-cnugvqevptxAyG>^gZ#PBds1yX%Lh)=Avd64Hc|10?OQ^q-PF zyL=BeW|}4{=>()LZn3Y{??7llF=rUsqw?I?L=8Mi5`$5k77eNvhQCS*=Sz&n{9aWF zOcq0sRPcXR#W8al51z@T3!bDjvolo>L4~k^8;<$MXGUJ4!wFb$8Un`hJaAEbyfA?P*mTm9!ul7Ip*~CW(9)IBV=PnY>(1yoM%2H1;LKd@u?k$+@rUR~jA`3S$*1sZ!;UXrlDa ztC69$=fTvv1G{m}%e(wgvvEJ;V{3GD^sEdicZH|tau#MyUJmn#x3|EjC0%#h!)O%3 zVV}!4E<6(N(y##|N9*x;T*7Z%OX~9+ut?|@;OBu2LYuu4QE}lt4|KVY6`}jd*2j)C z=)UQ?)U@Tt(4r$>tkUDCU*Sb&^ZHXaF+S7RY2kzmG24fc+0MhyucwVcL+Iuw~ zS;AnQCb+(VlX8G2-3G>~3Vr!g2*$?lp!gX3w_<4FDjJfAJ&G6%!LvS4ruZ zSvYBbDBHtotpYRgGUiNh5Z6^*C!n4d1% zhK0eyEs^ z!LI_*PsrcH<_rdL{Y!9xte4H@v(OfwUxlz0sS&@7SP))+wd4Wom=fp*DQv`fAfW5z z6jhn}+i^q5M7B*T|HIC0JsVtZ&c6@ogQ*^j1l)%6<=aJnmzxcLRf&ZE!|+y8XUpE5 zMuQfp_+2kT>*{4Fx&7Vh`}cr}#pn6CDZgerrq8V2a_%)*BI;lJ=*Z*#@p+ba5oPGgn;qobo37`xx> zF)?>##zxnV0|PloDu4}V6NU0huUCD@7vl}5+&Ua~XRD~{#l_Jp?*qvf;~c@kmt9Rx ze+H2;sdYZyU#z7_jv@e>dK?Fv!CM#a*-#8Ei}aNB%EQu(9_$ z&l(0;x@ufT4%gg0${h82t?S%6YYsvFw?{QyT^(n03hX#6eyM1+Zs*Uub>^l%uRFcL z(GS`RR~KwQKmS{x8oPCUy(WUf6kZJnFGg{sq0k3qzfV^~comh1xs5=Rg`-8pyqFcv zzV~&xQ3|n*Sf53?X|9RD3uAe1mL*85IZV%gzIZtui`Yn|iOODXx*T%Xs06?ryYNjV zS|uWoxvceT^Z3{92M*y|x?@_jX2RIQaig|5K5vfOx+5oAY7?0O`{`={6qxWTcr}Kf zQHfaxqfmd#6zjs;(1|bK9Q&fmZgrlkkOaPzpi-IiA}=j0E}EIxczG-$O$}s5;Af^i zzkRrEInDh}O%0`fKUwS$IwN8e;J%s8-FkgSQFyB9Gb$@9g9-i9-7}tRXb68zfw?Q; z_i|pjM!l(}tBc9c7=rP)Z_^i#K**6V6D2g?8QGV!e2Kt&^O+BXLuSHxL`SBibO0VW zPZLB<(FDnx{@;2SSYiLQ-p|L3+X&#qk8$>5+Fg`bo+Q(C)T*ddIEwLVy$JSn3MVJ0 zq2Ds@T@xb{91>~YG+HtJ-u;4<-P6ch&nBp5W|W9nt|&dIE}dH7I=Y9LFYGRmkL_?c z0ki@;X%zbJ@gYYgj1@mD$kksm$gPy<^W0i7f

    e8ZwQ|?~6>-zBVT?pmdKuLu+St;*lQ>aeoX@)7<+u1n(96+qtTFgiH#96zL}~Ou zK|w{4Ou6w5w6;D^271g!zuRpteY{6U=V2iXq_E{DG3m!TWCR%F_@ zS1-~8B_t*e4Mk^MPuJ(|#=W1y>w0%@e}aN=V7nr61liWUKNz4;%})720dCi~^aWBp zTus$Fmhvz#cMm7Co*V}c($ZF^$;g}!$0JF2d!6^6k?|H5xF~i*SUg;^_-}TAsJ5%^ zrcc@oXKoUz1)kUCEUr=gS#oogn7Silw_MP_(J-`_@L^;`A=xTKEm9{6_m(Avi0cxR z`4e^X=6V1zq_x{pIpmB`1Fi~X6vPo10nXc_>b;4 zmG{51TJq45Hc$XJ8j|ua{J7_+x3!MYmfFyF-}m% zTY3KE%zyJ3WJMZW?qDG?!;Mr__8DK^OA%DJIjK+0y)5%({Y?l6C_hRL*o)GNAT>} zIqeO#zRvkRs0|1S3Y>jOZ(U9M>Fu5_3z>spux)JLl&r2!8X_eng^bWi&&_OCQa&Z< zNJxf{O`JPp^_@(Esna_U6>9wytzNoxls9Q0x@~a^3nE?e0rUUEl3W&0xL75eC%Ga3 z>ywjvpATJY?X?BcTD@XKBqRi6yu8^GVKNPlf1JE*1Guz6eKVc@Qy*wlIS=np#^Veg z4dPH`5U?;vgI+)NMi@THQ46D0hHnwlC(4)asL>CmGdN+>@14Be9oNyg7zcQt4wfxw zaeXy|fN){wrEkzGRaWv+tFY;{>3?8EUy9e$MKtTB|4@02s z*MHD*8w2nS7WW?&Ft!aT;sX7TWUfI(A_ikb2nZcm0}LDp2q-vs!&IY)@fA3RY2m8? zWy6u~VZVxg@=?PSC8*n32o-2H@SYns=*|_RNNabDQY}kGpNZkKUuK`Cd0;J99A@uV zbh6zASWM|KMj7TMY$I+ggb-8TD$kBy(Tg^~B-B4d%vv2oSDEx^BV5h~!$MpHr;HrP zR?8<`S0kCcp%bk-T;br9nUp9Q*MIG!*$f1=0PYnWzMgTZEyT&3oh*|`#U)tDd6*Q4 z=Xc;ggZei0^wg>O&c5+}KK4PyUHr!%t$J7|Ri=;)Mks!mKNFBX!FzRjR;4PKoTHWX zMb#`3Ig+q9tcz8wHWHWGOS9q#YgG%RA%T6S|zpWiCFkdo}aHk{B0IU zw&D5Tgv|<3joBDw6*wQ+up<0<%I-$KhxnwbG#{V;DY%bjtQL%uXDq>b7L8@Qguv~q z8=e&#kXJ|6`SwkV*y8c+V$uO|BWaCh`KF#BziS${SjC)D(#&8#lCKxpA9F%c1jm19 z+rT{d(d|FfZ;@iBq$5JU`Tr{2QJ#X;js8}klM;V61g7%0IY+y z;J`^hpak^>!OJeF${s@8zP_ZN?M+PIm3oV&!UD6(A-i(3-m$ zQ?s>+#=ePpwoZfB1ejw)1VL7|{?*0k!j!<9$t>@m!_L#8Hz6W^x7X6*ECb-8hHtC) zqZ>b|mX5NPwuX@1dUJSqIOYmXd^`qB@eTOt_X;Qhzc%cO6U2BYE6bQ_w9OW>x09A;2WL;BxhkpS{sDI$Bn+w|8)Gu)Vzv4wvzVrj|+F8UO%C zoDD)NRQ9A~uzqcJ$=BOb@X1~v9SqI(u2QYMdmLw`{1!4q~M4|jC@0|x<$YxMXg;@TYpFsb*NRAX`+CCy z4*wi3Z!Rj@AGkF|LQD{WhM`*t(iU8M_~R!NL1ibpep=NLh*rB|Q?6b$GBQGxn8xmU z@@7`oA|d|)Gf@~g_ixxZ+$W<+`(PXlkqD{H&YNIEYsk73sNg7LTR7^lOa*)lL~*h!|&Wis_%T1m-KTDo>AT2K4+FM&+5Pp5C_%Xw;V@57dM zi{qaVc+5)wkGF=4@yKW%Y;0_yhO4m1$h&BvdvEuHRab&aJRZ06&*gJ-LpC3~G72yE zHK-mi|1DW1F!zo<_1a*;$jfr-Y@A^%8$vLB8oF9ab{9KfT6W_JPOM-ZVAZFokmAY%B0I$bEmkZmG z+ge2Zl{II;=yzE7?e%Z0hlOJeaq->10>pqB@xP0G( z(+crX#ttM&_7$aBdox)c4KF(*e`kNqln?FOc~S)_lLgtOdz>C9G&XbizdC+of7}9O zWx?>5mbE+6bN4aK_r=f0eV;xkM!xt(4E0!s1md4mJtyb0Adc5w)4v2%C5q2FjD! zFtNa@7QXI~l<0cQ`yj#`IG}!tu&o`Kw9p)=#wFPo6&2k(*e@)O=4J8klOXuQ@Nk@&8iHajE9o+M`T2aC3v7;tzTFHC|F(uuvk(sfPwr8G zPjn1I7nfBUSF;!6U=1**t4`m?%x^0Mah_QSdM;~S#P%y0+x=goZp8G4uWG6dZme= zK{u(a@`jvAfhE(8b{i6RcgSF?hQ-Ae4vA>#x4pS31cXVrKt(mR^U3*BS8VLWH;lj# z({Au=PV3c)K9nCntNwmE-9xeUMMG7NI6I9Hd%BMRECu{OfayHr_ShbeRr|}WkGY;` zp-oQnds+Pk)7Fi|!24?TeC4<(;;G50DSI0m+;r~2p^EY-O-Ala_0yKwoF%R%O(;1( zxZINyzG7Od`ID<^v?-WOj-OC+h5Ly$GiE>a*5=Qm%pT}=S8WlEKxXrG3M9V!`;V;H zwr(3GrrJ$Dls=ujDO9p`9jhh7)=s}Y_bn?H9%*TK=^QWCf!VfedO+X+!{gpwK|#Mq z(Dbb(YI~hg;WkzX68ts3h+DDwWXk(-k}b=dYt4ccS2{%!vnMv$?Nvo6x9w)_D+t@I zje>r*{c#}~4WL53RcG_GwWaf%rd--yEjYbmDh{^;MvaqUDko(>}eZ6u+>>`!AIgJu_3wdDK=y zG8Q`dLwk2fi1=^y`~{0=&6@Q&a|{WTOQ{23Q(_EGM8m|zFC^4cag!u23DmWxiH`wM zG57ThnYe=8*;y$S>f|q9?h9b7?=OU2@A>;u8d-@ylaCv(M=A!>W+%BCXZzCM4xWCN zSu*8aBqVxR__Ai4m*-Wh4J_y0%lC;DsYb$u2>9^>VGPpA+OtjF{Vil^+?(m@3$gnf`x0vd zT$W-Ka5=>-3)Xwdy=j7~F6Z%*d~3m1HXaQt8xzeWj?}h-51iVQo}Oe&lIPFcJ2I*)nm0(R7mNN#(1z6el5e~bBRRo8`A&&=kk)iI4@t+TxQq^uPFiv8fALh1b3 zR+mEgOc3;E_l$xA9H4^~&z4jCw!?A-6I8Cgr|rcicm1Vcj%w+{*(T`V=>}`I;j;j^ znP_nTK_dkDQLOsB3iV(+i`x#f0YzlzN$qZ^d;3Bne;{?E+Lz)}T}QqG6F)Ws%YR@z z2@`;c5f2uYRYjUvSy&8DjO=_R#I{?sn2L^HTRSgI#QtTdtgQSq@Ml$s-4KELG)2oYarkwF$u#SN6KVY5TzihT76a^ksTE2Gk=B^Pryg^UNS}ha&2!Zr( zCWJvz;fj#J#fuN@=d)Vt7e-5+yQbBgfGNex61FL(qWa%B9x{+r2XCT4xzt4qxk{OB z^8nzEw&F7I3#?EHfP{rGm|ix3&1Yr8tWd&Whco-djEj#{0+*H=96wJ5WsbozKL^oI{O7O+bwW;ED4U|@umA9T z^2ri>Au-hd!t~_0^gqG(`=@r6|BR~n$remPbQj(S;9Y^WnqZlL@(;s*s2|*aP*5Lr z;PC&Kz8ad^@IS?M;lPf=Ydcbyu)+UZKE{`QsAMUNtNW8|;Qui0t+GoWF0F?nn=FVS z5UWu8A^(qG&X#4JR)qCABm!5R*`Vu?R$>nNzw<{lgeaje_6NCreEHX!=_hY^OKfmt zFh5aNx?%p~=U3CYLgVZrp05RZU$DiruI@@AgUhXxP-9&En;*ZekS3b_Kd~7@ntn7TOtT|Lf`TxHP zw)Q5LW}g4|3Ns#sB;X2!|L!1eYUk`?>SS$W=0)XFA^JZTNL5T-TrBO(ok@jA75}S3`oFJOnA+GNjV!HzD?&(#$%|G33pF24YJ`L;(K){{a7>y{D4^0G9?yL_t(|+U$J?xKz~@?%rqSHhPh6 zK{{4?5mAFw6+|>@R6xa;VviNOMzA2FNi@d95;Yndf)!9iDS~35C@M`vsnS92<=&aI z-#)vpUCx=Ai{^Xp``(0%b7xN7XRp25zy5{qe`6j3FN`rEA^%K}?`3|=wl}__e`59` z?2m*k`L~Fjj_(Cdg87*+a`uXLA@Bn{GW{G960k$Lr{h9DI{J0{LD!bX^mJiBmu zV1nRf!0T7{sGcl+NBU7>dEPJ#-8m^f!`l=y5o38h0ob13HaN39dnh)bL#Iwe*uL~b z2nJA3dp%;IH4QKh(#DuX^E*r!FfD$1LL0Jy#kjHA%pSH+CJ8(uzg)4q8p@Cu^8?YQh}rqJ(S`x!0X5Ap{Pg2->umXg&E6(68NjWB*OL%V-`A$h&-6J99WY^ z%`N+mjO*cp$PX8d6&nh;_C=GG&u=yYNUmbmWfL`h>EjFa#RqbQisav3{snI6Vb z`BYNhsCxm@p~jxgQm`bc4+KmpwVuIgF9taphAbOEq9!?5K*O|{X3oIynXL2%y$HI$ zQVyOuM+i0*DRQ(cn;srLK=>UK1nNQp!X;jGOfG#-SZ)3vKZ|cn&Tr33TI;JaWI|* zmDX&`YKyqQtNn#m)yhV%j!emf*=#fy^^Ih?xrC&y1Y++zQ#i#f$y93)G-`}tgzK6; z&4_%;NXaKMk0VzcCF)|~3$r0SrqU}RSaY?gYyBBwcqVq}5Uh!6;sy4!k`L9mKH|62 zJkJaoHu7S?KXH@#EBQ$;klv|n8mnM}`V2pL2JxK=AS^L3Kbo_n-hZ1RIZc|lT0q0#I*&?S#PORrA$mi z!JJXx@`M4(g(QsBCXtpO{TC>EO76mh(HL|3M>bjoxU_`qkRc%iK4or~8P~~XPIOXW zKN6v-F){B;8Gy1pJq;>zEr|NwdVWf*PA?qarj+9sZMLCxNSocZ>=4 znYg|yfl4L-jv2Q;h!Rd~^x&mn$N6-JSB|-DMCiqf{TWE7D}+BerzXGv*0#EFYs7hW z#6Jky+9ZyeLtcZ+rxl4b)&gTro6flrI|zw(`LNz5%Zv!+9r#=i=vT&G5-<+r(isYq z1j#{$+9;GkhY)(;#{2;Wrm1X+Y5fXwlJ6^Io}|4K(Q7~&>zNy7U^gEU!~1t-R4y1E zY1B@v?!&yL779Z4INXscUTGH`K(N-o-7jfn~ts09>U zUXUEJwWP&kk|~Ro87G!$%m2eXmB2r5pxqd+NWszo5AWSl7|)gs3FAzbH4Y~PcHL1v zc-XdU)VY+Zw5N-CB0IckM0&7!QX|v^7JkA*F9g_HSz%!!=)~${I&%@MyrH-+Y)^4z z#Hp*2Rndj#C^Bk{__)OFa5 z)%Zj!UP}{8IPIvnSp2m5vVCKHZ|bUI^E8HC=ecp~HjG(oC}AxQdWx{fo;TU!xofC8 zOjV{r(;zYdhQe`{U~pgAy((fvgoUOLtYjXWAu%^@1RoDFy%JleI{_GVBI$amiH_YA z9UP4?8zMuuD9;*m57lwtk@7WE!U^PSjKH;%ZqacjY03)2gn5I)$;Z;Ibv;2IH6k(y ztbQO+<*E>jG(51O%M2^Sc8HX6GiI||(u{N&R`CO!%;8^QtuT?}YWr--!RSg22hPI*bO0#TDv0c2COpv8A1;+>Blt!Lo}9c>LZ(u@Y-}lEx&FQJX*q z?6uGmWl_r;!93&x-4miMRNMA(oM-jaR4Bnrb;3s}E>a}lMVK9|#r$35S73NgU8~ls z1e-AlncqU#^gKo8iHizfBC&{mK^t3y5~P%-Q$aeNN+;tGRC++^2P1?nEiddd>WGs^ zg-X?zchV7i$H7sWN5=-SliYW8rZyAh1=y)4m?H>59!0OR_DZZ5cr!9#te`&E7mEl1 zcdJ5ATm+=rL+JVfpNE+F2HSboDSMu3#7YZ!BjLobT);Encj16T_|U14hI(3oR+#Xa z5^aXt%2TXS@@mCNmCC~4kwNpyNZ}#q ztp!*IC{#Gq%<`*mvUZ-@%~i^2^if2 zc(djbMu-7s;L9KPkA(7+(#6LuR8JqQ0iBoiiiZ(C4%hknbgY0R@l=C0z>)WRUcpeF<+NQR)Z2H%}i#mzibw4dpt@@Djn;^0c*?!*!-!12trl zJxx8F1VRqAr5uSL(`r=80{#+x1EZ6EFNQ;JpujA27++RXDMVcSfSFG8q4w>i zifGJD=rvOvH^j*_gx=6A^d~Jx9p)0XUb55Io&{1Nw~1cRbfN+pM8<6*BjqTJ8YX+{ z)W#Ls5Pxfi>*%2>MSukc(Y`FQj03JpRXRShROxA}GFcR9RpH4q-5woR`3}Iz0*eb6 z4v0(VuXL!FcC|vl*gc6U8DWZ(!>*$Rj3~qw5^;hMp#-Qy%%qpk&+1*u;;x;F!G^%x3uED57^I+l1{6_R%DPi8LYpp^ z9O4}Pk`1}qq(`r+5_YsOP`NlpZbHBmBHb@VRE|eiQxIg1t*vHcM1To7*Q?YQCCDwa z@QMM%4@AzoKw3tDCnl%VqRudF8nV%(Zgj?2N<(i57v&=ig!p&Sip7|-LVd})D??NH zW|HrAT$Bi`l{2psIWTXq z0dnjY*F*=)fR*+@pj-}On1~H04s@PB)Ug21(vPt>LJ9Cph6SfASPe2`7myNJC1HbC zRaJ%pZwyhjtSW`-P+nMqSUfhM`=%malnN(<4>3&}i29KDX$C=#>eh(DlwfY?nrbSC zO~N#@bm}9qjD#~oSC}jl)GQBhMITh%f{RU#$3-B^KLI%#v6SLOLzEaA!7VOTQ-?Ty zm!32_f9;B>t%!(~)HI`OLYr9%5cAqD;)QiZ6{MkE8(|F>TVgSoF$nplkqX!vW}$FB zLUjcBjs0$(NbJI9b3nBJf=x&RDD<^`oM^xU9%w;IX!LQga~H~gR)rwc>r<&6*8z6x zS1c{6Qg;DQW(Qb3nrsyB5%mC`G@I$XDDW1O(nt=eWTI4-s!z;=Tl7zQv1ttFm3Fj% zvmlWV0V2czWXKtl_J$2SU{QthU^zGDYLiGBBO$HIW-|0M{TF?Rq%^X4ReHl~&Z?vu zjNicJ({d)QpoLMaL~K)sn5K?5=wknb;4}tP1ty`eSj&|uOB@T%G98^5hb!TJj~c@u ztua0rL`sbKsu%KZ4xlz3tvYNI_XCxxh$b+TDdSw<|#@J(?jjxJIDknr`k{P$D$kYvjY>-Yd zr~#cAsiG7wm!=Y-t8DC{xJWBS=cPKnx&$ep(->} zRk>^1wu+zj5F-3idbkWTbiF`oZ?e$`0G2b`nts>>APMiQk;0}08<-Pb=2VE%RN?^vcf$xTyRm&Iz@fl~ zkyXsj7qTUwMy=Yl>efd^gvE0h;)&Y}3jM_e590(85D75gbEZ*zLA`_=<$m0ot%F#7eLy?d!*jnu!S zXs|0z2w(Tiq6BQm53!vFL>?|20M;`W(HPnArWyE38Uq-%Yh`ev$YB%DX(jr-(NXgz z0@GE&(6X(b*vEv;lct>;PjY{?U}OoWGv}PMC5gEPUs+j9=FeMh9`lnA!J^_`Hn!Q^ z-7@ibVOOL-nNycerE1lzkqS~1o_Tru-ikU64oFjDH^SGZsp(7oQVws>+0H1AFC%=) z>*J+o0cI|D5Xxepz{0F^#FI*UsL9IEQ3UaKQ4Sw6=dp?6hPX3O>+l~q*^ zEs?H5{*TA2i<*X0zxC@#vjZ3B^PO1JtyvnR03a z#1j_r0+}ci#}xkr*h@jTk%o^4;+5k6!4jS?55SKd1nRKhU$j#yaKCpq^L&Y!eI~Eb z`V3z#SYOKdjDp2l=ThZrHj6UT_h))+u`OzO74dXJ_0AdlG zOKpOvso_5$2>TRhORTqtylM*PEpak@zrZNd7JFeQIIq`%IAxxXg-v|A1o;+Nq+im4VPX_NvRHEGboNqCAeo4 z2Mmdc@xVKG?mD<><47*3ftfDC*&s}@MUTa+G=@Y!dcTOmTmrKE%q6@NLCRcSbCvP zfz6mX=45=vPejIPbV3YFch5Cc&zr>-JC4_UC4Q_Q;i(Z@T(KuzY}DDs&9>ZvN?-!k zP87xR^!a~^i=r7nd8JgZ6oCX+qc|z`Wf`b0ttu``bC>{CUnD|_Az7P3bY#&znyOw3 zxLsjTm!usK2zI%PJVP9Y@EOT}b8fAzybha7LxD_gL05sB?pzWI!it5;z^Os+Xy>A} zU|{VH5|pRl#UP6FfQZHEQXYfFe!gg5ctu6Eg9xrG2pqCZFru_afYZW=)ov4lG!CG! zK9D$J5S1n5a7?OM?`CMn5aOOO00@svVU+7^Ka6&1>M~rBxO0m)s({J)daV$$u zinQn2kXx9B-Jnh!0@UD(VTnm3zL#}| z;vO{(nnkOvGQi^OY_r&;i(8G!OXj$7%TWr{=FU`As%&_mtTl`v(S~u8*tTSWo63%E_nnBD8a3J?n?w|iNuOUkynPO3#nvO z1=(~!--8rRr!Zj^rwn80iak`Ayjlmrz^@=N0A$L^t2<;;lB6gaNtaXR6pvdBOLJlk1ZVR>C6$#>~U%8n$_L+2W;ya$MQSa5#+3@nN>Resr% z7C08b9FQhG()yUC2dIOY(p(CFH<1uzi38-t(0N3$v^YUIpZBjQdLb_;spi;`!i36V zJ$B(IKhumL`!gY=L!FmcCM5KH8;8j`Oly3QpRO|ed9SJ(w)+20-uC~6tG}BnH{-^x zqC;0{C-vBrbEKYNz{*XPT^j&Pz^F?$OBzF>*_L$qwS@ZleQ|L$#E7y855VGvBm@`! zbji;=3FNKiy{P9>R{k|v=Q9eta<94JrIXHOr{MgD2qXN9<9pCAjyl?(MWKMb9PqJl z1(-uBYqn$+6f#&;k+f33u?q1^%(znJ<8=+5M394XavmIVz`0ApfI~?@C_-$6ee@+nQdFu*Vm|D=$Yb}{ zvXJEh$&t)BofE%t-tJ-^ccD^z4jZ^fk$QBU|8&G%kBI$3&buO+3SI9pSw5|z(4=K0 zztyl%UGz(zE*so68SC?C&=$k!=*VZGDm0&Eu^K}4i;AnCl{U|rMiTr3-lmZw9JSDD zGEvFG$7(0DqLiF@q8Wz%Q%^tbp5ExP3NOp_7-53d*%eqNag%XhSi+M8k0mp z-7jy7#LFadK?`~4N$?Z?rLEjNDW(d)1`InoS0hE?87}Uf$-)3W69Uou181{Y*GE!V zQ66mt=prB2j$7O6o9-lcpfpeI=S@I*1VAx11lC~EdoC|8-?wic=(`VWvpPnwv z`6X|>=%Son&(CQF`w!^%{Hx*RDxZ#E-T69|;#6f3l0HK?@3}dV6qhmqV0xpZJ4Tu6 zCRQ&ahh%?M=7GS@mX*5||ngv7=OE&7w4m%w`yY1p&<=WzRUVLUW#RC@cZn zK8<`RWbevnHdjNCt^_Bbt4ZDgQvmD3F<}g>I3ozGdlrYM`jg7%K?fb!pniSTAgG{d z6E%;wZQHhP{rZxUl3KNE#d)N8n!Bz841tiaVWy={Q5=h3Apvlbhj1nXq*c5winnRO)J+X;Ev{ZK&$Tw58kFyK}2JeN)bjTM8YtIWUF!sWQW0dgR|SQ zP14BINY5niLeQZLRVz^#xpip12&{&~&QnP?7vVO6Q!fg{62kyF{ZB>0Yb!VqVJK&#l*gqF@%4aoA++SXWTHFgs3tE2ZU)MI{6D?vT z$&w(9Sm;yG!IjOTB&BGev@h1w-gZtQZJH={(@R(p=dG>~J?E68m4}Ouz1(V`+7ePf z5sc$fJ8bF)%9!N8QTvwO=jv4}pZxce>({SO1wp!q5meAu5qnRkIL~6lx)c$kRb?0h zQ#Q;}`*!rG^SgBJlI2Z!Ohx4eY&4Z-NB}*BUzZ{u-W_3(Rr6N@l00Zrs}nL&lIhWA zI4Q}z|MD4U;(ApmiKW!qUkIUPLCBH-TwwZ_aRN&>k*Eq9*;XSuYM|{bv2R zY|#&aRGCqkjzBZ>KULyC%!c2uUAuMbRxp}4XIj-~3t(3(dbOybPLZe8LY%DT88Pyc z113mjyl}=T&+5r%oQYfQ99!O@=GZ_H=(C;^or!?FhzS~6d1k^0>{+{1-O@4)sk(r~ zV6x^pfOs#+3c`gvO$B@}YAVncDJ4fc>`{mcm5W~i#<}L<`O>w>2 z>`$y%jMHsHsX5*w-)Riz|!006iEDMbM7?3(dj`E&&p#Wr7sP5AOv zBUbL3#Dyypg)>fvd*eg-lZ+*pxN$19pqNm?#W?s%;;ki0G@E^gl^|~rxM3Eoj3lWz zEoe_Hf=dv=i$NFMG**4e5k@8g@gBi4AOYBm zIYBAGXeFtML!_h^afH2)Qk^;hOT0l*qf5~hB3JcMhjteWu^`PNkGw%(q?lM#$67xieF)Ohb^E0a=M$xKD_Ww%yZ(k*SXMeL7+kkHzYkFbSw)LU>-(elv z&6qJgkC28C)I$$B*j0wu>}qAfZne39b?CxA^vR27407j?ue%&05zxjnk;e$9EA&rJrZ{ zMcfQ~@4cD%XilGHn_D=muRqNX%f49==LQ!hs5#8$(DWlf0dX=y!_7^aE3v9)5Y`*S zs1Pj|JV&ZKbV%@EguIunEkxiaG+U&35jMaIHFUbA)l+UY3m0z!zW@U-H zA=?pvBVyssa2*+`&q#lYSA+TuZn%Ez-yeDOsw@9gsdOpRr?M3iwxkrUK?4U4nmFmf zD=)u{ez|`A`m@jcb;l0vMhqXeX3e+s*CB%ku3EK{e)#UYHQl>*rl)Jwl4?=BapT5O zBhPE!woShij$gEB5#RUMr=Q-gZJXi4hOS<{ntn5F+O)QKmO<=sL-gQ z``2TS4H`Hg+Hu|bGfp4Ty7i&MhMxTGx8KsMq6Z&2^4zvMZo&t5&U|W4L|Ww%$E^Q0qhKUTO%;|M0`3 zjyRlN>i28EQzO&*&_mQiY167DegENyAI=ytynDAUPd)JjwK(WE>(;HK-}LC#_35Xc zYS+3I-FV}Mjpv?y_Th(hpx>`qvnJYW-4AD6hY9b2ObA*!ebOh%2L-vBl!}EV7bJpX(nbiz9(!Qp$w0s%Fia_3G6x zDK2f?xXIYDH}&k4)2I zz2)4I=Ph3H#l^q>!wuJ6N4Fn3?9^#*zfC{9_12q1hYjQHGwAEqn{Vpa@vzSpExG#Y zYp=WZ8v4!6H{LjE^yn|XT=s`QUV8nt*V5BnaoMG(4j=yY@)eg|e)+Z6Ty2@YO`A2F zGW9k3;ienMjvPJe%Vl5v{*RZ?&FHT;-!!&khmMPuEWPI1>#n)xPxKqO4L==X@W%Jv z|KP6=KXU0G|FCB5_w<`@zgw%+CO!4*uSLh7I(6#cAw!~8UtmtpnKS33g`b|#uix#r z-IlP(j{EZ+#~=TzIdebUvTX|=uDkBM{e%v}lOp+j6=9#`*Iq7cwIlsz?%cT#{^hS_Wo0LweDX=`;O;i`!*750J9>mcgT(q`J@;Y5 zPQ76Cs4K3#@|Blg8h_8d(4(gR8FSG^bl>0p_IEwHbxD}A^fsv!(Jg=f`#(PV$RqTd z4?p~H;)4$r7Z+dryWc zk3MQpUthm$*-R3EB2+#LLT)5Rajh9{bdjl6rpGS*fVn^;Kf(>{Y^d53AXgs<-6n)2 z;AWxQ=z){2$P_Ci7&U+m*jGiaFPb+{M5;-Nzzlms1#x)=qMgl{zCFaqQqcFkd-pC} zxbSa(`|GGtBYXAk*{fI2Gk$%>$WbHvo!IZR5yPn~NYx0P@l+-^Y}io0e*O0C+i%~# zog2EQF)h+jaIU;FW5(52T}ibT{k?nl?oU4X1f7mAz4*eJXN=%uGIZ#v7o0!(^bu#k z04cqQfBy3yboNi5Hm!fZ6X-W|-zT1+`-U&Q@Z#yG4X57>?0@2}ojd<{$tCBF9CiPM z331*BH4UD4{Be4zFTU`?86!@k*Ve0d?|(k_4{8@opEkXJzhBXB;5PK∾$q9XsHX zbn2C>mrgPELx{4Rbqt&iZ*TBNM{Lk zhn9b{{Hm+2eEmUF42i?KaqUy5w=k{${(|=c8arylZ zOzJ-%irn1!=W!n`Sa8JQ9iMvY$#Hkz!}mSu8BERo zVW*zzK8_Pl>`zyaC5sl_a_jBtC%R5i(H+>o-++OG_+!20wmUxfVAi?koPGZJ7o?e? zar14r&z}AMdFT9Q)Tq(?o7?aF^T!{5bo5b2&_TO%-1x|szU8*hKKb;rKmK9D#0Owf zDgiKXG-R6?J zc?WJHNvvqu5DW$y8f~aKmM4CIu^6Os8}`ovfzWB4u39dvwyQVh!VF` zSo3*0y;dw=e&UJ!UV8Dx>#x6_cL6hdb7?*Zf;5Y%NWhTrp1bck^UO16z5jmOcI_HB zYHT$@L#ipYzfYkDJmzK#;`UAalH`y3%OiFYTaWU|!jJDBKkk)Rr&@cpY1MM&>NN?+ zv{p*GCQg|=`PpZlnfm%0d}F#)PMz{9{btH*ucMd_g~-#SF!WZ-=4Feb z3N5GxKTgP?ql|$*O5HVY(&!I&PORUkNpV?OQE_QeNl8(0Nz}rS^}kalrw=!#eAG}$ zT&RdqY&fW$lw*MWkOZt5UzT-b&V+=6aa0#8p>mNAb0g6?o=}rF9^-XN6BvDP%rm1G ziL%JxPs8!x%v?z}0{ggnQ=o{T7}g)qNG}11>qm5890Oa<|CMiz7`4wQ-2Xs9U;s-v zue;{zS?|5~)84%uJ9M~r!i4CXYp;HP)-3+bJ@?(0;35(`10R}6b)A-n9l#5bPgFhm zv`k!2GFQDf<`u{+LT-jfeI*v=B!A&Wf_XUftQ^j2_4Kb)}t)&)&%p4 zbQKXcO0osjJu<>pHUm!#kxv0qN{rgego%|O`L4Pz4;mg351ch0K}BZMmpG;2Rg%e} zkz`nTp=x%?7t6dGP!*c2Hq}Ayop3)gF=zMQcfW<~i=F7QD?BJ;u*gtFt)(9yn_E6f zoP5S*{&JeQ$RxNWCi4(aqzL7yCv%8E4H>U5ll{|(HUAk#7h)iIC<)*dElRvlnD4I2 z1uGD{AVN@5FgBN&=jLN_NNKz-t;S1rWf8qS+~Ts3BnT>kjayJsqmejnv^?by{lbjT z@u1F_ZAdO8V50H_B4k$22*xjxxc=rPpB9ePt+p$uR9){L8fEv&YQsqNCginP9Nmry zAR8iHI|3wG(nNuPWM|OOX)*`+c>L%yb;W@$;7nSRr26%<;Kel;avWO^GDB?~$XbE? zUp}G+tgLjs(uaU!7W@57NOuzFrn>&c&!Q6d|CNtqB8U4XFX8m5EKrk-P3O}Nt>?&p z<{_Uj(p#u}`a_!`fh-}A44LpoN|+b8q}1gR7SD8_yWPkXiEKz9s#jzcOGrrIX)=xC zFiu98H$jhqSRy2c@!~vl<3(Zs$Lh-_O`5c6(b2>Io+ZQHg@n>O`oRpKzg>wJvq zdB!z#fN-cdJW3o&{(m5oejvVbVo*$%3W6ZVhnFKCj-K_CsXT3cWpZ}s#wYwT@)@W_w_XJ>NqS-AX zvlM0mr-=nl!YHYSs=sgVFQX(Av}J-pn`1roX-+eF7&=Wi2tqh#>!&#UP@(>39`YII zg33r|WOZhhlS#mC5M~tFpUg&6k2?$@dI7oil-e@wR~lhxb1P#E+yRmh2X_r!uSB^t z1#z~qpSRk)LjGlGX=#m`HMVWt)}Ud7WBc}vo1w{3mTlX&*REYhL3wftDsn47G0G{c zT3j&%M^z_cw7(LI@{Zq<+?S-8V`GIA<~*@W>yc;ir)%8)59AX@Uf`D2D#H!ZG~&q+ z-Gm;os!`RgOcMb4XmQnCN_#LpM0au0=D2BRS`;eMNegi*a3`hP+uWjukJF_&q}2J6 zifEH2P1mgb?#pG%c%eqTGY4pP{dxk1eR4)ReS$nF31zuz&%?<(*yhDb#Yt*yz=Gg}~!=NhmO^RzbvA>%~OH znzN6XJred;N=Xts3H+XlR!#OwNFm0xsfT`i+!XN&s!m4dl2xNWJ25m{vT+;NK>laQ zvXH|4)m)Nk4VRBjg@7^3Zy_kexQ&y~Jg7#Yd|K&HGiDYN1vhY~8jSj2GgF{-pmvK0 z5j6(D;OB8Bz(!AeI@7RMMb|^q=vC-jnYYD~5fpn9Bwi`CcnWPP1;p{*k&P>eNru zP0e96C?hgd6BV+kLC{)6E&VE5p(EJXU_F4wu*suqAnuXuXov*@*r2s0vKGb@BH|i3 zBtZ(}{48GBOGcg)Ynep0E_JO$FSs`uJCSTl=Od`qkX1|GT-_K8bpYhc`{R^WvsIC@ z&GMB@V%mp=1#Dx}DlsN8juB>*Oa%<4Q;dD<$O~>sRxfg)U>4LIEOFzjB|P32v)T<2gY8!lK=X_+CX$qh0OJtHE`7{A0MZj~BYFt&h$)j%-o>KvVVHJ#83Gk#)?;8}gj9T6k^>@X$|8|;vEz_f z+a+$l28auHlU)E0jAFnB$lFNIN7F9)d|D>13HQrWofaghC?3|AzfyJeYJ#|;c--GF zmvQl+L9BH%*TUrV8S(Pd8tCY13TF&UP@c*Y<)G?DW(EkdsJRe29bgZ6Yi)yj8Oo&g zUSL;3qD)*Vt5Qd5m;o?HBOcu(HaDX=mt0nnQIF$m(1apOH4dqlv#qtUUIb>iD8R@} zq~-6O#v`Qj64d;aY60SEN&*HWjD8`2k*VZ~$tIUmc(}nPNFzZ?6Vx{wy#ln>$?y32 z2wOFjCyMQJVFia=1iyJeXF4%bTpvoD2;vp#d16h008_!xijJ?7>066DT)IRA*b^^aZG1odT6dX1 z<_J?(X-nmf^5d(XDIjE%R`w-Qyj~!LBk}l(ghQvHb$}5i^WF7bingYI}i%H^x10Trvn2Pc3ch-=<|aV6`JCwl|1o)El#qM zaB33%y&7ooSr$?#!g#d}>~5wA=B*FvT%lyjQ%orC?yB>s=dg&Vu4)9Z*?Ui|u0M3P z;g@Y}O!PPEro=bMIIP;;`bJRENTwY6A;rl!WN%ftje13YrvkN$`cl2?&79+_)~)W5 z;Sr282FAs(FYLY4AM(5yCK%;0Q}7$Ok=O>Dnq@%bQ5k5=xGz@wK?i|PRJLo19Yj(_ zV%5FZ0ix?_9}??INEOG*ML~BTkRxR=)*xi8^RSyXm$bB6qMZB)#!1Cxq7|^F-NZgt zYH4-zAy9SYP>aIKX3n)|WcKw>$cw6tQ=xXmNOYmXhDMcEg)|MY#gpXKU7CR3X$h56 z2PQcwe-!$I7cx=2PijcH+fAKoqYtgI60=TeO`>> zKmu_qMNVHgAG;}TaA;Fx~|l;y_uQ1)$%d>Q=xgFX1NI|=<@a{8S4goV_MCH750 zzdD4OA?0IY6}fQ{3m)!l$)g0@qYxEam3BT$9|jOUtL$2$$(^IlE{J)g($xwhEvoTL z#E8d9@STw(2?;V+CNlx6rIEJ?Cl(8o)XNZglTYf>$+Q87kYFoEsyH>1f$y=&7|gl2 z<61Gsvava8mXH|tk`xlQjsMazd^|DORIT)offEzeH=7xsGO)tG;j{|;E&}0;dcr#x zIcA0-ldw6r^N<3J-6!q#`Aweg-jJ`K?2Gu49EAv~LPW_cFCbcV&0)&&BdhJgRHVN@xh-8wO0B=IHNqR0mGoGlkhbGt|bXPbRHWXvr zlH|KKqmNQJIfE_~7%Y4AN`fPT<=n$K#UzMGO3k!RjD!-(BaUv+92p$gPJ;;~+jX1a zq8x2=-T4jCDqiLYLwZ$i3Tum06~d~+#tEv6+QWJtlQ#EbV|0t*(){3H`OKtV6}O_FfBh3ZshwZ7iQ50nceLE1R`O(_pW3gjqLmO+x%aMF}s#463#bUZG2Dq@cs9 zWn!|E=2em^@)?J4uzO1(;r&`_R{d(?B7Dv&fN13eIiUR5F;%-r%h&VDXQC7t3>8{3 z4H~F?MXP!=E4f`$ICQxrGpE`_@tq2U<3`LZ2v$sAST#Merleun`LaGq%G1QtC$tIY zdJ)V2s2mSgc{?nf&nT`V%m6N2ER!mh9>o=$w)F{T^>kboBF$hTx^5H2 zL=R3*?z!>?A;Fdo^vbqj8;3%FYOa1_1e20V$q-J)8x$(54uqweT$^^>2#c^r{$lA* zEEj$;afK7ef!Y@=nR%#9BQj>tfO(EiGBSiPRs<_oBBDVn^urGtz#vs}p_COykE7*}i^s-t z%*oC+Vo44Ce0C~vX01FR&~;P@l3?G#VjhSjuM-5dA5-1~w( zGhw$}{{6-c8=iUU$$Q5A`QGv4o_pqL`X}A+h3B6`prJSNof;kx`Ir#lJkgpH^LDyX zbFD}I_SZ}%t6EXhiTvmz5A!x{@PPM>yNkH9h~)A-{Y2O*=&7nr6#1U+9H<;im0iKY z@j)q>P)@P5aG;XI;tlbSDV7q6!bSG#WdxJ~Od)pZm2@mtV9n7Rx>H;X4AAQ|dbr+Q zb*ivF#NZr(D%wS{Ba_WZrDY9eg$UHcR-!Lw7*;L_emf#TN?|_9*WA3YL{6T?CEkNN z&Ynlbz4FqF$MiY&>~qhfpTAtX^p%%hy5zFUR<2l%;uL0#LF=(;rDaHTp(XcIA}K8^ zD{I;6&{Zpzx9iY>2Z6r(?z`sAo7bvUt02vps61`?^p^67q$o)Ff+|ZQR2fETVev*c z6@3I{6PQVC$WI{wggmU0cCu39*n-W-oB&q%7vVrhOB?8>&cAj~=~dzWYww_U-wVEM2^)d(U3mckFn5$`pRa zp{EY7Tdyv^`1{6>yY9xD__Mh8?z^rZdoz6>a?&a9zBB#!6MmJ=X6MZQ;FO`m+q7%9 zYv+!)-gte(`gM&OH#vFe(0cXiL&81R1+|D5xW1B0yHJo4Q>FY++3r?_fDn;H21a-~ z&ltUBJ@cIzBx>I}y>;t0mtFOzpZ5O5FXQdE-t649>y=ku+pE_xZ@uv* z4DdB*(11R^ox66?KPxKsl~+_WY0_lI+ixA(sukV-;6o0cG3_k_@9qqFkV^gL+)raqEuN=$>fHIVEB{27fN5{Ng&kND@{z4Th+c}TNWx53VZlb=Ld?xq z7T?7@(Zb#><{0UtM*q?}l}fBc5wSEIcR`d0YdsmrE0$>zK)hlmi-=R;0-Qq>&xGLW zH?KzZ@p=K!hZPmGoN5S>SAj1A(1-!(3+|23DlDOq5)bz$N>ok7n0L7h$(zCfd#nTT z>e%tHwr$(3U%&2$?|+!~_FG-LcJ17?o4Sm(->n^S`ma-|RPWx$JT&P6zDt|7?b1x^ z{^q<?Dghe+pq^ks}5PCK${)KJfyq3{@1Etx?jDGg>DJ3`bF? zMqz-9t7erf2kk@+pUnuy3Zv1^rsT|Fx^!~+)?WKkJ~$EL17d5$uu(%`>ssOpl9#4@ z>P9$lme}>8`IVTU7_5j_cK635#(r}>=^#{c4m$V{`j5)zUmtpqi>N~etwSs+Nmu#O zi~sH1x$A)kA5yz^t$#f7h^n` z7Z~IODu^ReB!S^Ws~WVBh?rgUL9)N|8d0PI-2_6;4WrOk;jXvG3UNU!$;7_Mo>vYN zf~%fCvBurxV2P1iBKyVeC-~c*7#l8Xn^&u+g422ftu}B!|v>gnVB18(5 zy*!QHSgAH6$6lj1^aW!d{@Y(SZQe}3$Ye6>*RQW%zaF1$73Jmh!$AihG=Khw^r!jr z=O1+Nfx4)eJ;yDZf25}A0S6o~Z_XTk6^FEJ`SF7JJGO6o@xTA&m)7FI0~db0fa!0@Ttty7oMEU{Wzd2pM6Ko` zWXQGP;H9hV{8+YP)xk5YqFw^F4@d*C>}{$+>cmHPfH5-7 z<(wK7B@+J`ZYN}gNbKfd1eTD&It}yPhIR#&wUO&DtQgz7_bR10#a=xr%|F6~3yddu z73}H1K6CB|AN=sc_ta8tabSz#r=LN;KlqSC9-K7s`mr|+95m#$*QU&$H?L{4X4HaJ zv2s37j{nuKs2@v(r+1$|WXTfx!+^mb2w6vt8w78_CsHm8_yQx$_-U)tW zG1nYF*leT9g+Fa%DG`XRaF-X-c}X)J5nza!U`L{uhvYdzVc%kfy~yE(iV{8yV=_54 zs&$YU@v!&8F;vJ2fC`Hw0pw-~=ns&i`L8xw_OIm`&O=WYx*U*P8a0=c>V7{)E`S(B z2nPLH_4?zHZ$PNRA5XB(o zv2Nld075z=Y?O(Uf&>+A5XyWv!q`8jVlq8m+Bg;ZisKE#mS=7qC(np(3?|Ma=lfyk zCLA{J9d&zXK|!Xu$Us36=4mQO2I{|tQ-+x)lZBI6xpl>i z?d9{C!DG3)%_vL6I33jF4j}^2ap}eJjnYbCA{Grsc5S8_a*Mz>O6P$U>HgF7kWGIUGyHie}z< zwY6?e2vMA|>M1hb-2=LZHQpgLAf|YrKq|{kL08y zaIFi-qaP!RwxFU!wp)n&z_P?gnSTMs2}NhIAPN%8;ujaGGRy#DB!jr=meabcev~Ng zT*MQ@A_m7IQu%dgzM4^CLnGlr=*vjX#U&rL=~&L5tQ$^PBa$ieiG8QwPgw{V$Z8i6 zXN_{9M9gWddlPC;0INk=H83Em@odDp0Q$fnz)H?@sG;=)Da2WBBBs!AY0Lk z;|U5ej4f(H>7xTuXs#oHZcXz9DFZ*4#Mnx7iIHSyv0eG6)ZIjr3-XhOygz3`dmgb@GYw;mibGjVbdm&n0uZ@C_(ec-;*LvIL(B=uqioxBj=mP!lMcV zn=V!aoU(_nVFP17%!_@KmbiAJavmH2K@4IfL3Km~owgDvNl>pEgA>fsJIJbZQ6rVj zX3bfSv=s`7le}3LC#MptpZv^y`kO$It|clf6yFxnBXyR{%g>>ido(5=H4(dOGBWCpLY$lr`VIWGyqLfJ(W}!Fk$!S@otpQe?*P;bZAZ<{WT0rAZxNA4oAvKO#48x+>?ny~6WpSp zcbmy%6#H`mAR*47P2lqM0uPi;p`y4r@gV!t3_Dp+ZCjfB3=oFgtWrC_8l}-hWC_I%)fjmfj6wrt!vKmq028J=_mI*?z z(&*Sg9;A6CD&le3$TG{y#HbAFinwP4HVnfIQRz#pZ0wL&HX$>68EG%K9SDD?%9Gx9 z(flF9)uFv7|fJ_w_SID@@^a&fAH#SPTLXvUt){$6h90n&wdGWVrHd)?Q0G~U~Cjrl) z{CQfu3BWy*2Lk1zpA)pJx12SXtQHRWNgfuT1)E^d;_BMH#PO^1lH@`(d0b4f8cRk} z7n#JT%$e~TH*UOP<3@(>3#|$`hwjWBLq%e(BP0I^Ld z0Rfu;A&6NGNUlcOIUx-R6A1LFK(Ty}j^N=uyjjTqhV93lM7aw;7Z&x&O&oy>*RI~4 z!uu(i*rd14OE|IUmO!XS*64r(*00}?E=otNC8;3J#I=rqkS1Gjmo{Qi|AXfQ7w#aE zIN?sFjYKmNdX&H#4c?5HQJ!%`4Hel8A)LioLIX8>5ZB`YNT@}?`>ITNd3kYhaYe;G z$cuzE2ZMBUNiIP(vz-ZPSht%1q(ye-xi`&`(DxpBNdw&!kp+cQh3qIE;6Z$YK;l)R zyMfUK!Kj|d%ap~g){WEso~9monaUROIiXN4e;zjTb5iT!IQvM65Y;QCB_$OV6*W>d zS!mNvyuoObTRA{r3R4wJbMAAZs$mQhSM?%gZOU}SG|fCuZoD!}mk9e*7_@pz`c+mj z;VE!EcGhD;KpS7S1wCRm3@a-u&DBGj2^cWSpVG7$I%mF^FDQA z^-|2IZINn*js#>2=c$xr4|QTqdK}Z*!L@S3_>DUS3^}2-@1T2J%w>H4PtdA zGcUF2jVg1?lxWINR7G`5Cc{;zb?3j)f8lv_Be0mrfAxke5yu#XV57(SyfxaC4g>RJjI#R%5CBJ{a4D zx)>@OoM+UQoh^h{5r?EP1zUF_$cKZ(+p`745&ZhfTEj_FPrIZHY0krR6a02?OdMY=L#!3B0gI?Jyol2`-iB=0X1d$J6h|FxEOggf)Ic4>61*em-Tu>lm zL*)WlTo#Jb7A?`d37RNF(fL=VLHS-p^NkUUFxAc%$+Qj0HGJ6H%FC>>Cr+?CPiERp zn>G&W-_MGbQ!{48^5tj$`ix_GcE9?nD|RuiD)@Tuy_r3_cJ6%C5k0zgnKy49FAt=D z()UhB9?t)D>wNU^p{LAz_g&rBk%XO&Jc9r0*6HYz1`nJ$^WB8v600i_ zKFU~)l*E>n#{_V=k&!{rZ8XHOdMkx~)@7_{bWHmwBo@xoEV4pM8A&XHtYR~JW@|0V z(-M44gp?||=9O%`SD0++t0Czo_asLnB#sLzFlbmNjkG zLY*rCW(Z&N=g+_I?r~eUZgn5tZMWQX$z_-I>V3@O#h*VkY0}NN-l~p3<@1&s$KEsH z{(k*VoH2dc_19cI=`Vlj)~&~9ijcA}z^$O?a(X{>_UoyfAR^kQ!xWKkeQ7 z^ixlM_uY3MXV}*%bm8ZVb0))*gE~25-1}(^=ist1d+k}#3RiQ&y@*-uH|#KU^adfW z7z;fibnk`@8*10A(XLIa4)p(rwrtv@X^k4SH*Vatuc9J(DRr0CXPWCwbnlt+Yc!V3Sz2?qwiE7@RaHxtE;;AyGrM=~JfPnRQ>RYh z=l%MduTDSh)X^i){o(uX)yUA1(dl!O`+15aowi1tJi$rfrv3W>r{z`2>h~%f}1T2*#0;KTD zH&c-q(7Z&*8IdJz{4xVzEQ@>LJeA^txP!w@T>57=LU3d2C z*?Z213%YjgHh$b)^qV0=PJZv*h{)#McV-Me=_Ie8fArwr9-cViK7P_^ zZ@vBWf1dBztM}b^k5_|p&-n55ytCPP@4Wps%fKEmXwclbv+3t~^XAa?i2p=)IpfST zKbSLb^aW$+E)iSw-FNpsrqA?uX0BYh0uJCEx7|VyOD}cOU;g&M{r8zNW+2X?D^xwP zOhzerBvaRDnH;MUWn-j#6kWBeJh8e54a(KBt&r-W0?`Ud_W~yf4qDjvG`mfu`(S%ZcL zJpJS&?b;n)r(T0!1@rH^^UmL#doCo4p!RTidHLAut{X6TV4vfTqu(rC_|fdy?~7C@i+=BuxEOE3ET3&)g|mX13Ag8sicUOj1g-Z}8RX8qVf2Oqp;^A>99 zP<=S|#+$`$e)93$IUlH9=zV?q>B4&^OeiZW8#(&?$N%}5ntcEG*W)k0NH629ufO_w z&+grTDUX=s5XqI?*w^(G=Y#XeZOxjW-HD;Wz4kSLN)&8Hs%1ifTA5)sBtnRyzGYO2 za!PCEVPZfOsfw+!d4ZsHv>vszsASOrVA)4lI6qjF%LFK^W3m9d`JolVF#~fR?e*H)X z&U(KdU1b2qq@=in-wGsFR&5{|`%UzHvu4doN=xT|_+e#LRr~fG>Ccy6^2ZUUpK)~O z&W#&4K7IHwzHd=c5f6g_SWI-V8Sl-iU$4F!o8|xQ+_m$RS6}JSzI~dNdhl)Dd2d#| z`VC;FggY#jlDYD-ONXC!dZ*4^8Z~P4>k-2t7eOK3qZb2|Q-%{%s%-@ul8F?bmhZe+ za;C~!W;@qvhYiHFg-rB9go%!#sz4uv6&ZPlP}hB`wk|@P11$3>*bL+7Bp#O9TiBo> zFB#ztoh-WnHX1VXY$8Px0$@7q@?6`f4H`B<0kZ*U!OU;ZQCP} z3Ewq>z?udv)@lkJr|7g{L+8z%Q&CYqXU^z(IpA{p0UXIb|sKM^>#`)xJZ=)@@q<>#={RegAaDWmF+Q`S`!O zckiJzMW;@ksjHg}!`G%x8FRsC1j567lK}$<|Mj7Vj;D)}JPzIEIl47~+3 z>e;jBlTZAMp7gx4&w`iAE~5jzjK}}=Pt$@%76ory{yD#faU{;-^)nA+l&Pws9`%N(BV4t?KcLG%?c^D!@Q6QQ-iQVXOp2~+iv$eQ3#!J=2QV{g3WrW>Dl;$QU0ciedw|7pO$fe%f3V93d* z@INoR{E9#R{^B4=T{vdU+i$(ezx>lR*Ijk_rS%&&q;9P$gB*L)&9~li)3M^b_qx~F zqD6~#?b=gUQ;pKt8>uyYGvDPdcBpHvyW!>=$Ig7`oj>1w&xNDTQ%~~J%dVgc2fd67 zE*vvWUPjJTOF?PdIE+Wa>-+D%`*^|pJ$v@h1vJB6JmN*4BQ-Q?)vDFKSMLK4JjhC- z*km9UJEX!7VJ)A^-T{dsok0}zC`i(g5^QO5k$^$i0dcYmx%0&tFn7Y@L!7>kPit*a zhEW+=ges;hQ>L=AY9D=-?h z+*@9e{2Y{QtY5#rPVJg>FnRM2q-}J@Us_f5Q+YYH?oblXZ4MkP&b2`vc!s>HTjFl> zXL}V`G?x<=m)|Zp#x$)?f<#hSlKm7*j>@Xsx9_6`^H;4{@zYOH@1{C+>NITFuzB<5 zJhHuY>sFrqu358Y>o#q>_v%GgSoi25eWMwak$+Xk~Ebj!h8RUD$>Z3MUr|R z6W#HYvlfO~qJ$nZ6`NwpQywtVvWl`%VULKP%{*qRv3uUWefxpU53Y*fS1DZ&$1wq6 zSXx^1hxO~I=L5Qfdx(M(o-2&m=R*;c&=M*E1GvBP8PoBlnqav?R+c1xkC0?xsYWdi zLB#64oxI**hoe+U4wcWTlV9O-*s4{lzJ2>1aKHgnVE9^3?XQZ83i{JK@4T~m^=kTg z!-n<4P8$(Psl$6>K@>bSE^dD`;At@k0|T6fc5VatXj~9S!|TjTG`rFSu>w(%^VFTd zxTFePy>fUtm37E5eJGtyWda^Qz`pel;93dFzb`dn{3&y%t>|=g7wY#$Jl;V-t(0}^ zerVb9P;LOzHE8}@Yg@Hyt#m9>tS|zCi}Dm#;)qSM#KwiM;l6RVT5yecVo^aHyfJ_I z%wM#tp(jaxY!XSx1m_;Hi*|HKeLtK#_s1W9q&D85L4%Gw^2mDi>QS?nN2GbUi_R{p zSI;`@tffnrPMiR<*HJRW17;bfWF~qp~_@4VI~uWnjxxIWGo0Q1PP6h zQGTy&+qUgoUxczjNl8l8C~e%hfe!US2OW|k;r1=Nv)?zPnwBn*E{`tJEl{zSz1Grl z-u1WuQ`Uhu`Qwbzdns6Fn)E?=VulKm93MkxwS7gLKchlUBNltjYZvSzS}l+@->zQv zj+m2|>sXbS5H&0x9{6daiWk+p`Waa*BY_sbr~c zT()c(Gkb%#U-+z&6}b68o+?T#uPrpuC@?N1;gJ|&k^oYPi5XgV6pC(XX4+nzCJb}j zzN%dU|Ew0h$Z0#9yH~II$}fnT8|)h2k2tgnDf4PZY{vK?>Np0vfF)r(5_kiQDl7NB z|K7|!d-k+x)23_Ju666yEoCq6YQFmFt1q*jXjClem(&rZ;(F9kM;&(9VRV<-@6W2N ztinF%AIzG(*w0&_LXK%tpZ;I+5sa zMJakCsp52s%3f8rsw$JM$_nFJSYCw0QV%QWslH=m<ga@)2o)XLqr zud+9T=}`?n`>n4l_LaxYp3sK!>p$16TldJrf15br-p@b(OwC#mi&ON8W@A!*+?nr8 zr|)#_c;No~2j|kBz_|O9r;}-~hv(z`6bpM1xU0M6q0ld@K-x|3~9`+?N?eSCt zsQQm00$WS2U%#H(Uv$G0Pdt&@w_H`Gn4|RGd+$-t^P6wJp;F38iKq^s4k{JY5hF%$ z!)?Qcbt(fW)?97%z!d|lhpmk=9RUWWt|BKQm;gRzQ7uMPyjPb;fUgAAr|jR7$>NYu zJ2s7jlE}NmR1CPzlvm6+8~AR4Y=o*^xlnK}fEme=xdz3HwLVFugM8&JOsxldckZJf znm2Fp(@#Iut5=trwNWsA#m36YOhsimf*QumSF3sxWqER##oKSb(ZBzI-<&)0y?5Wy zSt$%Dbwe#DpxAb4)LIYG)%U8auSE{kB6j{U3m+>Qa_jZwmtP#(s@3IJTtR1vt2wRN zNl#7RtE#GY?cQC#etmW3(z3EYU2|PNRwxy09{tW~U`981&9%u|+C^eRT^$5i7vRXT zAwV({+-X(z;So!y(6B4L(c8ui8>kD~ph1HsO`353lgsC#MT=(5nzd!imd%?tPnj}h z=FFLV>8IOJF{V=5tXVU<*=uY&o^XAN1u;9a@bWy+l1CBWINC}s{i+?!&gyW~aI(fy4<;CnE z?K^bbvwQbbPdwhXUHeU&H;x*8f!dh9kG^0GopH}T^Y2X?Hy+sHz;i~9`tpmVt5&XL zO*_%t*|R@dFrQA!69)`bC!)Ig)mL8Lv3+~1HfOC5B%;Amu%g-b;jFob?e!4^~x1PPd$w)UTPO^-n^;r@yB=X(Ub1@?mN@JUiMXS zN%6ozL->v;zU`l#{kE*w9PwYQVS0c;Q|GtsxRE&G#tji5p;4noRNgq39lbXCtf^S; z+_{s-cbh1m$=VA|!yZ zJXsP*@eCy_9zyQLt#Afv3~E-{z^3V8D#MTpYRE!Qm>a+$sNZ0Hf01f6!Aiy@V+wJ- zcS$9RywG7gOTi8>ecH5>Pa4v&K|_GcE#I=PylJCGxF}m%yNK?wX3d(36Ca@RL$7nw zhF$csDyk~%01qHHQjHQViV*t6`?KDov-#M*$0>3H`rf-wpCgVsYV*d8Z@fO0iYV2w zJ$m&#;DAQYKK*Yhq8E($EuGmTM~$YET(4e(2*fvIM)MZUhn#fs+O=!neEl^lqT9Fa zC@U)+amHC+EM2mdnOpQl<@2J8F5dmqp2;u0q$KBt8*l#m!+$&H-1FXj_ub|#S`0b) zl<(KBedD#MR79!xQ9ahVYgeW8E*$gQ>C@gGb^ZlQ7B8lAZoq&+bV|+sAcD?r-?qJe zeF0adcQod=7w_J)8=h$9JMVPr+~u&t4}bg3*BdoyN-vwpDyg&wcEBWTlo#X_wKvh`3U^`DJr7W$15o=z2x%C>5i|y@)9ga$Q@kZ zswR}o>mCvosFVzFoyzx#U$CzgynL-+w~k6+^XARD^GVM|7paFIewZ4-^uvxFJE%25 zWtfie*s)_DfBbQ(Z&U2mwr$%PGiI=IB7Y=8U8KvlBeDt7>@sJ3m?dF~3SE@jBv^KB z;5kuEf-fRL0x|>&J((8G3LcXP)+f;tu&^z}hX0@%py5zQpRw{ffG%a#r@p5528@;+ zYunbX4eB?z?e<$%tXwX)_wcRNn&tS zhjvYIJ?{7uTD595W%A@>`W(yo_doq~;lhtTW@bXzu3dY&`RY|GPZ>Ilp5^i@ucCi0 zS+uA}&z_M~Y~OlltJd_x@^8MTijl6tRK^&hgHVULTaTV~>eeYQFQ*2%=wN-unRDmO zJ^0{5F1zw7b&+&kuTi6{Uj6#teErplC-#pH(!6<=;i%|ORQ*Dubg?}3kDE7l?be;1 zZt}}7cj?xZol#s&bfPoQnmc#SA&0cQ{Hi~xL0GkN#h@WW=oF;$hw2vk&9X1Qq$B$A zM+m>ojUJ}8lw8D%oVWMq{C?#VYwqclJ(AO-l|BOsk%&0XZvE=NZ zVF>z?0=RtyqZe>N-iSiCz>1 z_;}irm3lC0Pd0E%m>(#t;!I}Owte&#%PTALO#{elee~}SpV)ukAuU^O+qSJnjT*d( zIKArkXU!Tj=C^w*DyB|;g=!K$U$$-AP7U2pKK|&u(HE>(x#IYK5t5!h>8{;+aFM5; z5A|V|EMC;ELr3~I)tp_sN3ulsYTvN~{V-|bgmXuZKBo6Ek24UTx*jUt3PG-FS@3%wV-ybS|~c>)^6SD#h^*| z-*@h)(Z?Lq=ZVMvrBo=-fzf%Ht*TnFd^xXW4N}4RV=khu8XO|3VCT+$zhlS4snAj- z*`-^3{yiNfYUnOpuwc{$7t$T6k6`VXJ4IsVUsMA=yPCxO0vl~K{g4;0%rtJ&gsySx z)~(}Off~2R9d}%xK7HuoQpH|ei_j&en7yc8rQ*sl#`OCpO`EFrO$gf&d&4(IkcLty zClPref^~t%;;9y;`ZJr!V7eeOwU*_cHJ43Zuq~`ol`zGU374=g-H1^oL?RstGL!Cr z;84YoCC*;USj3{A)nkKwxCJ-uru&G(2LcLws;V;FdAReAySjGiI{dVu^p2>kQcsl+ zE-%rdUsU{*p_99OU%A_vJNZRTO6oxF+_|H9^A^KLoQ@=g*WrgB`PgHRwmkIEpZ4yp z&x%p{9M|`$ryj3Yx9-qk!|B=SYVpQvuMHnDg4&jK=|e@R|Db`?G^HB8eTNPM1`MFP zY~Q-Ie!Y71O1AvCrD4M;TT6}77oUHwvZ}IYk6uu{FaP@MGtNAde$#*8z&GhZD)v#4 z9x!lVl>6PVfr^3JnA#CxCi~iyDW{!&x(fO1+_AG}ty=7i+oFphA@x6Bc>X_hpr}m_ zr)<9g1D}8P8LD_29&iA!m7!a{_}}L$_f5?TIH*Vy6gRJ$g{_^G*h8Nl{s)50`F99Z@Cw?jjLV~cxDG0h1M!Vkm!gMZDX8v8Mc1 znTT_f%1x%SvZ8!%WktpAZ9iT;@{E0zm9pE6jO7j(S&cMx z)=ElJMa4zwBDxl^=yD44)lhy_Y zAAE4FTD7RT@x~i(oPYlL)Nd*)E4%;x`?VD+FMx^&olaDMslI*brI+^X*+Wf<0}ncg zK=8Kc9M4OpZO&8+Mh1;x@hgWasGfl=EJ>n(4~e2hSpF2zP4dx?#bp6~0IIWFP7LaPDnlzAowGMgp)=1XTKJAREqF`bFHf-29 zbm%E##*Df1&Ob8|6!g#tj7lFb>b0o-dIz+ek#iQBZFrVqa<;qcFyXRE7z=9 zy>rKoY^KVq5vZ1~Rl62_*y#Vi{%?C>Or@x-M$OW)8g1LP=giCi2^KxgjvWs>x>M)R zKKO7RFsmnV00F7{YmBXkw+e(cI;6{AKjtjVFqm5fh$UGJ%W7v z-A?9$go3Lxi&zkqbw)BMPq=N$x}8zyG#e!pB0K>rW?>~}gb^pFISMyarE6F%gTe*H zycG;qv@RH~D7qdTWLy}-m?V9PmMl#}8p^IP${0{pDLm%(_rE_nV8Fn>efy4MFOE#+ z(iMe{G8y_s-Fmf$Uff~U+k11!BBn-~T*2Z0N9K`}FyLPDtr& z*t2ujmMvRKN=jR|Y2$_L4>{$Owco9w+dTT{qrH0dI{WOisrAc|fU5Bs)t@iE_#)Mx z^eIQ9bn;M(nkd;xA)xhv&yj=uuT}V$$BhV6q=ffF$_D)TMhX)MTWTP}qfKySK8|;>jWD5vxt%kZqBDPHqRY7X6G`jRfHh?jKM|Aj3J@r)g*-+`- zv12=3`S=hY+WNrk;JqnWBkMtgAWK}=e*5jp123$%X~Wj-#orbem6j9-5@B1hud<>t zDpg07ne|7FJ$T1|8aHnAOHa5jmo0n#`R8}<-d($PE$gSp{vn7?X3v>TT>!Yj=btZn z?)m2~{_Vw`J9qkI;U`Z&^Yo>cUec~@JGBe{Kv%S7UoCs$i6{FU(;FU{$~N7%Q>UYU z>88WKkcg&>(&4Vm_N`k`o3>WR4DM%@mXuulhfCgm^Yulaf4*?x!Y{t~qGijLty{OI z3mLuTl`B`STD5BR>eWB}^iz!*H9B?fOy#qrw8RcQ=vfp3^n#yE*s$ASCljrdqlq42 z_=H47maQVE&SoOD$-+pYg{a0H5u&f z*i>UHdR0qm{YdOTP^$s0Rn%7Ng^6u~UX;crHT6QHn1UZ|R1gNVBO?ei@5jt-UacdDUJ2 z{7;WR{`hyl``sa@{ru-YACrstb>W2bNhk}bER zh_1jJ06hlAwRuX+{#^;ZM;NIp;8hwUH1$3OP*cfIQ`>YtnqTQn+Pb`JLT_lRbYi3Bo<8|%_5 zuN;Es0}nj#$iv5uJ#_5hW23FXkxO25Oq*-26Ht$dao(sijEP z+hIZ_Pka&`AaVDi`cRVki_E^fqvC$)Xd=arQM3To;;%&Lh$o0t(TCK>}{rYd*b=Mc7l>@(%)2H|E|H1tiT=0Tu-1H0Qpa1&b`rXGKdwe8P zt^H#^J$~htM@wPec_;00q;QC$XVz1X8XnUf?rQUkXL03Oul3+V51shwiI-n}^~B@< z;183A;NO4hQ~dMz{cw=ockjI){n+2#aKjC)Umrs8#>NP`eEZwqzUQ8M5@6Q%!vpG{ zoE2L%d_hM-Ij)|P2kE6XY{HjbamD3BN(>dr!Zlp3H1-1-6BQ5i9<}ioDjEAoWJhX@ zV6+uxB2w0_<)$X&4Ig+8j0=t0MR`6YNw%go46p-t*!7U(=LiC=9n0Q=bCqLx>yDae z{ICLUxZyXks?mRP{C~djjjx|~-t!I}eoo)7PVSuY>(eKneEj68CtrE(s}3DHtaA($ zX}r-j87j|_%yD|p!KU3XPqRaAcuX8A{6AZH=4*ZBKfZF^b+4)aX}DZp|N1vx{pvB0 ze&*Ak9x~w%{LKgA!-_v&am_VPJn>}x4E&Sr?QK4HKl0%_&O7fp;*yp>IUBx4bTbZ^ zb=}s+=I-7u=ZEdmqB=73Pa4(q~UEz6s0U?&=T?2Jx#*IQ>qij*pj_CHfeaUTstdk?fEu)Mh#BapMCf` z|AGszyZ*HoUHn4tcb@p!PoDVMaqst!yy%kGTzCEX<5-NX6(E!k@;8ytv0C;1%J8LR@V)WIUAPaefQma)m26aefzC%|KNu{IP6R} zYTJKp_DUAS>WPjwbnV3H3nRNa*ba+HnTSlTg=w=Bb#M&_vjT8oly>r=R=UjT}Wu(yC ziJRd-Ijt4vBj+hTzNO8vrFPgqzSpl-n;ZSsQ08u={B3yid#BIr?VsLvqY~*DY5)Je zZo2vAAvO-*9DDfTOO70=A27tvxBcnchR7M|Y{UMH5mi2e3!3yVz5Mbwzxj`syyzdj z=}jNH{q{H9a?6n;7vK7}Tg{)GC5dkQ=Dc&CyS2F)`J{>!T;;J?BmP*kBdD{YskscY z6qeJ@=!+&dR0%7|GA|lW=V2OwVj3LDP+)XwhC?*7TWy`9~? z|GNL!ZNGBzoO90oIa%N=Y`X01?3~=)x%`TwFZsn^`qA;@b|q<`5LL9uXT3Ln^W1aK z`Okar9gg)OyXuFEy%3H9V0-x3yC41>j>QlB!{?rR;S0954{dI5Z)|R@Ha1op{Wx9I zt;P_FvPZ-KRd(Kv{}xi+aq9-SD2|~~=MdQ4aLf%o#Do^evyAoUqwtDg;5t?Mem!|O`6Y}G#Y*yF!^%`5);(0{+oT6cZoF0QL^c;#7pe{yJjp?xT;TFh;Ukhs^ z3TeW}cw`xMeH^`B$-H~mu}OC`P>@nm>iIR|P$>2wRFW`Gga+-u2vPZD-UNBWq*(8r z$j%jq9t_*5G5Vf9O(k*d2US2jdE!S3WYb`_(~7EKAyOG1;PYZ{fB*QSCyu`CiZ9%D z`QGlHZ_{fhyqli=Rrm})U#r}B3e5gi+46J-43<1+k!_8HlWz6ny>>+)R$lHc8ZTcTl4@UyV{4!0QzDZ9$-FeeN?lr`;JZjCNa;5ZY>xy5 z=lf(MktE2X)QX_oraH89=!Cvt-2323@hK*^Bd9CaU)s`X!S#KA{P^)pFTHekcg%a+ z`6Nnl$40<}_Be~IX-mWOmQBlSkfd#P0Fm`VQ^#5JYZJ4b2buX?9!pVQI<%1Rnb(KO zmt&PpXI-zt*1nR_RfAJ3AKtQxZPcL?$0!y`-(`9@@&Z;av|hKjwjTK5gJTOebYWvJ zGTR%88%Gd~i|$KV8#axJtS}4M0uOD+;NioIc7EL0xK1OQm<84_xO6AS-W+?=>BxGQ zae6HPOx{tIN+RxQR#lOcBDYs$v)yo%jDhszsZ;mgfB%t-FFt(kxm;S*o6QnEKv56# zZYd*8Ro2RZgGnug>J)&;1)1Krt{EQX5m1>y!NL^REz^IPbrZu0+gzM`HnT*po>svv zrfWOfY*y5B*Y?ZdtO$*HjHMR=cyHA*cfckN>EFAcM7z7Y_x&H-zq7NuxwT0*5uF}| z6@q}kvYL6elpFKw@kx;;M&h1W2V?6sg_AQLsd*xNeu>`LCv=utE-A|(Ju#`&5~)k2 zl0Vpoc&I5!M1u_ib^} zZ#~n94^&AV6!oN4WkEABEFm$FwMiAB+q%!pk8`Eq5E$=$Y9E?mwoaANO{L~V$$G%t zWK3@Rm0ypOG+Ucn+uPg0H?wE0pDKpS3RfwvqcGYWzryS`dYaG-gP@Ux?}eIzL+RX| zW#oJ3$Y04NnQhe90#n8gAmnIJrH&B&AS88xemB9-qajRarbkty;hQ*|Elbv?fUFiP zz}VFlu3N(k;rXQ_mCw!NC~3NA6X66hTk9AsiHCU$NelIMS$d(wT42Li`8XM3I`pDm;@PJUR02( z8_d=iG2lU>5pq|Rcb@}6Ta25Q6o>j;<_f$gumC9C?I`)}LM_bHB2}>p?LwIlunZh} zj-^4?wO^k(lTTl*_X#?DmqL%Z%WFq3dt;->!zOcAb4i8#r@33FL6fYwNf3yqiNrht zbzo1!)-E-!Sdlc&o`Z$8rc_V1b9J%WTKSay5ui+ltsGk}UAHikY398J>|tROWAlM{ zzz)E-A#s|-^s>J73B+X>DGjU)d#>|cHhGDhzrZ`loF|9OX8>{?>C+^*1IJUHvCIU_ zXC!7?u=eF3p%=&972PTAU}putk8b6#+kirS2%7`kHL+8t@AixF8g$S16gQ?#d;BI(I; z11oT7DtJPfeK(!IMOjqNmto`VMwRB$%f<(A4a*)Re6aTKk~EiB4g z)jHP1NwaMT6Ec5GdZ&rrSR{lFB{y060)uY2!K9cV=wn-HIu*qaI@v7EQW_R=YiDca zj*v~@W~i*HHZWxP#14=)R#suElTe37-$msPzGTAax|)}IY9pfRs%Vx=`Ez?uHp*z! z#Yw#Q*@DO$$+V;;6kLmrZXaI~8c#v87RA``Ol{8u+oWD4@34pjc_-ana*XadqNWRx z?o%M?iXIG2kb~YsX|LBJks!O<&6LuR0+TW^tsebCT~^ct-#TD|?!pyaLe%LiKbWQ5 z06LS{P{-J!R0A=}app$*0UC6OtT*9xirBDbDKF*^uR~M9{~H*rpoC6Ch|y27#vd zH4wUgfL*HN0~h)7{F;JlCi}xhJkko1GBz9H(c%`zB{`Wrp}Z>dy%ziDz|+%`>A~vI zYIqV{HWv+t6lv#yXs`n>5)iB{dW&5-Oc$}`(NlC(Scn{5;4xF>)0UeF{0!cwx|f=$ zzG{Or00(YHa=P)uHiR>|;p0npd6=dRIKc!iLW>fdBut<-ous*+@R-g+JB?h}m*bfx z)rJLKv@1|Shh-TxAa~^!0iIyCE8)ldHv3ZLo-8vG zvHHE$rI1wvXqPe2B`eUFh`g%Qbil#}I9(@?27*;L@ak$Gi+76-nq7A(pDW5hjWj|S zof-8w$7k+BLjc16t;V$@;(YqyY=a{cWXYwFiKs6h?A15mC5$;S)3U7%*|1@ zi}4C6Kxl-%oF{s}Zfu)wdb^r|6ssLevjtGWF!rVuwJSPdN~g;wSx00~Ax!F|Fb(+> zOd0zfJ^}+(~=C}|!rip&NYvTgMMySRo3c3qofsmID4lLax zLPSY676n?oH%x^`g~nw0p)!wkicoF3jM5~HGiKrf5x4LAtySM|jx43suqjtPtM!~Y zvku<`B_dI2*7WPX1IYfLMT$5&t3_XK)Qj5`o}kGA@9X2&;?~r(whRI4KmtjfyR2R9 zCr4|9*X)#5n>Lr2Y)@R%rW?L!*ef?h7ltPu;Aat1X#APtnnSqa6q zl&GFTeu~WY4)l>dzR>2zsEl=Jw5Zrz1t~0C<36nMj1Q{v$U>ctgmgzHJ?7VZ94ccjRL z(C1w$5;ubuQ*nFMs^SrOnXxz9m5X`52Wlxlg>gC6ev1`*l45Ue82*XZ;(1m32y*=b zbc%6*ver^>r~NH^wKA0u_>P<@Au5YV0m8GNS)W<2eHRD}T&iMdt8|Wm3!y9G;;2l5 zHyon$tiae8^-d=3lxdLW->U0aC)5e?L4IrY^1x;vQhwS6NN?9jhRMdFDqk%qxcDK8 zY8qPP^#=ag(M zZ3;wOlVfY=7Mt)M$ct9KZBONDUFd;Rv;;+7$u1zN=c>;v+0oW)2P|4??UqqVsLIVf zX7C_RZB%3EIXB?~38q0aF4{7Aup6YzGR}s5&s|f=nGsi^BWk-em~P(C>e5ZzS(9la zcV?kNRv*?_e8|LdiEb?`V)8{l2~Sk`j4|_0%RRr5qbpnXNTnCy`iyKxOQ!fco@QsL z6JoTr19Ig7W`@ODt7HLbL2Y{`?qkqw0^QM>EjE^H+A5r)xyDd3CRN~KH)hd7DR8Rx zz_+@36Xj)v++|bF z5PROYMrX@C+2BYsYzt0}Z$a*ZsY{;q+l7)lkZ^*7d^I?g^SOtVwRPiD_kd!$g z0V^gmAexUX^Au^i2Li2(lChH9i_QHx35FT77OonoaH$QWTH2h*=0a%{H1gy{Gd7jioU?NcQIe&6eJo%tF!K%&yQ2h$z?CgZeZ&~jjVKwHV6(L-D0RY3Qw9+9 zZMw)bo615liw3HQoQnOI2LnhvH_7UZx0_R2ui9b(Z}Ng(%M}E(;zsHMl4K__xeIDl zem2kTjHHPT!i?&fkxpJ#g*F%WEJ~C!s0?}Qnzrsbf@t?RG_i!_rB|T#&ak42yvRkH zqzaGBV)BAf#H~M54tE(&J5j6W?kyXZj6HJE#Fo8?+{6ai^-XE67k=(o=*SVL55;_Z zvEjvwl2ZeihAsAoo%*C;Ks|;yB0xh3L_=TM(msuqf?J8Rggr>vZ(`g{Yfi{{3qwkN z`?^D@WQmg@DKHS}kt#{bxuXVn6W@6JpQgXx&3d|CXGjyM2pfD4f37$B0 zg^DTdiNgDTB{JV9)pYfvqqGt5y zIAaM+9`u81bXL})i@LZaq@sAx;=?Bs2QA%z=*mE<&Sj+J-X|`-kKj&0?qmElh~vg= zJs&%no9%lt`Sn0aRMvG%vjrK6#ANvm!QnLNg1T;AIBOQdtuN?I6=g?ff6N` zn!1(&X-;8Aqdf6~SgP(dfvAE4Ar;R6%!XlI<#K8xHn4YYYQF(YWxSQzgegvdiV6jQ zOO8?NsS9#H2qWDBK*A)?g{m=SLY;5REIR#>~P|cerjLSL8fA>(lHPE z*R6q7LkVRaBWg!$J<|*_Qc&3PfFXc@OdG|ii;(Y4%s2$*Tqy*wHovU*=m3tL@UFAP zK@Oa}fGgg;Gp1g-S>zO9vmqKTyHNH;2oZ@6Eis|2rtw=eMp;A{QC&w4(~MR&!D>*t zIVQu@U7%zw!d4(9b&6!c(I{Lx6O@TrKy*cC6bM*yG}M)thf%(o2SvHT zLee5|(B$?h@7P+fBga^_b>o(->H~pmN9OVL65*5wck0^;l2E9!CxV4|%BFomcrp3) z+DP*%kfQDs0El7Yxe|Rk-Ie{%Rs_OYo+~|V)*O;)ITTzDI_1l3BBpOldJ!K@Di78O zP(kZYmLX{oIMi<$B*^>k$YT*<=}Y>a?zMAtx? zuUTVAbVl(aG0CoMf78##RM_(|5OsQozx7Ge6`h<;0Xf!(*{3ZIyLnuP=SrD+*V4k0 zd^Y#&M%RWCSBCzBHU(&)Qm9(d)lLF#mQ#bum*!YHqTgdUTex!RV+bQfh?ORBScAOw zgw6b13uJO=@mpXU0V>^1`JRM{wGp{JO=U>q8D}!)|uOowNXmNYW22Tg~~Itho_b%6D&OsqhVeTWu#C*e{}dz z-T*#=VVcofFFTqfH^H2R3by_`SVtp-KC2PR}_5cV(>_6#zxVJ zxG_-ffXrkrX#nzIQpK32od5-)%ALWfxax3e2g?=jj&@A3Y8#9dTe}HNs1gXn@)Y4Z z9}*?kxhy&XW=!90PYgt1-lS!ZWRnw=IhvncA&Rd93CnNJ<;% z5@!x;S-4jxv<`$nMRo71U(b9Xbk0)l3xj;#=mu3WGs!Y!CGTMf z?HMGjsbdnbt*nb0CeIabQJ$cUPN*v6fH4;4h~~Ue6`e?~C%QL2z^7d`KvQrMYTXwp zHjY{K*aM9t@PU^nvn?!sNVKR6YB_$LT0M+nx%A8`_xXP+uWNeM%dn-4FwhnnH zh32uxiQP_IVG_~A_K*=0QIyU?C=^!b5@D_K1q$*Vi*b&ACS`5cjPvO`%6 zDZNueZ$)!G(LKd>&IA!x0Y4pWR9*ff3017!T1o8Jw@)=v<;er;#L0d)IZKrVoRqzr zV>LiQa&lm!wVh>$#3xHmCUwr4Hz0ss-B>%vMBQg+31rU>0M?dO*1xHixM^~k-B19g zwpIn$x_lm?v!rJV*jLz()uA0R&xw&ROMK+$JeJ|6NLEPnBj8n$U{0SH`Qz{QE+a*` z^`2(d2*gg+ZEC{MA&X(~)H}dJ$YRtR^d5^S>OlLmE9Xx;FKU?!9CW)b->9g;cv`Ya zL6ZRqQg1?Uz??;jS4ORD8?{Oz z$InCXG$PIkDhcn{h36_%9OP-zrHeB4iD|)Xk60Q(sFC#ROXHk+ISP#0YcdIxT9 zQ5IO#rHh6em+aN~jaty?tt>0n{h-`1i$!7=cqD<<-ES|)+72{$e zXP9vYlL2tx;Xwr(bgb&2xmy_$s4pux@q{YaE)mgj2jL#hY*a}Plqa~-B?``uU3*{! z)qG%nm_R-O=0DDwSqEmI4Gm zy^$?|>1lvSY^hYmAd1xSt_2p@lSemzR7MRcZb25XMno#mOcYeq{wZscB^BDjpjrv% zT6l~Dtk^@Ejnp|Q%B+pbKr$r|8I6xTOifME3rO4_Cxp3(F=Ec0NeyR^gf(2&&a&9H zntRYei^e1=6Xs)hsx}n@Ajr*GTNgClxzPvG<84*rE_t*RbPh8V7o9%?bXsukYuy&i z9`?z&Fkm&v=1)Qy5{#EnGQ4GGkcf}Tl7bYRkZmI5`B z_}PAFfut9ij*d%Ud52B!)rA|?HqWY6Ah6uq(U?51Df+jH$4NChV!k)A@vS?M`iM>n zwBuwmM{H>N+7}eil(2MJhGn5BS<$wsxzMhdzL~2z3+z+~J$5CY6sQ`7|q2f}8F-ef88HaK6c zU#Tx~o}f3VKU03eK73&fmSzA+oVWbdLE76OC9aXB%6U{GUSZkZY+W?9jX%uB}9l1_&PUkTNzVTsW8XI;w?Xjf9j_H#Q|27IWM8Y;X zX$TImn5I)oV=cahWn@@?E!?X$nm@%^N9FESyAE|}qarBS0lBZ(3geDUit>M%mlNjR z3+Z8($DPR(B-jREL;q^o59@iz<-a?zOO13f_2IPiu@mMu4ai+9iJ`H(SbGIHLl^&L zvXi!=3lTthCyGP{G~jL_LLdhfI_goWW&<$9T`f8O^kT?9?(X3A3xXe;T9Fw00;wel zVltZ}rFU5oChF)?NEH}+WWvPZQ0fPyV@Wud>W(IGDv0U5p$$*WaPAjEL}rwmoK()# z9I!$INQ$29X%g;Yh(ZtnI8<36Ltt@c*C`=#*x#<8P_Y? zK+D*g>SQfj7IL;pniMWjOqxTo{XT)X_qziOax4m$nH0NUu(1lKKr8Av_(&-jjhu}ywXV`J84rF&F z8p4n|eICRj31a?1FMMfpjSfDOhn$qN_ComADd}nEG%FpT0}^g$C%F%b=q}i(&M_xT z6U3C02Y@)9L6L976N>3@Bi0$Zh=f!VeZs(aQR)(iU8>f7&3~9gampav&fz6BLj9yu zxER4TxdJTT$TG?J4gjsWrG?HkU^RRjG`*)G5;9E+40|_ZR9(y^1NzW)nJ$pTsJqCx z3*$avAR+uOm0LU%gZ~SdX~WUp*NI>N001R)MObuXVRU6WV{&C-bY%cCFflPLF)=MN zF;p@!IyE*rG&3tOGCD9Y`kI`E0000bbVXQnWMOn=I&E)cX=ZrVp00009a7bBm000id z000id0mpBsWB>pF24YJ`L;(K){{a7>y{D4^0H2RZL_t(|+U#8goD@ga@9LTLWt|lk z-NoHqf=k@LyNf|WaUUV2}HQK6M+PxSPV!A2^t`mz$JJ=JCX{?F>wE3|yWcZfp*$01Jo4?b}mhW~LKk9dqRLY(v;$B|z+ zxJN#72qE$XKFB{JxdboPg~>gsUM$|^c~YKKfaE90v$PSZaZ)oAW%&#HmA)pC%78qr=kw5U2Ez_Ezq{Tmq>r$R*^@q)$lw9m}=J z_YtQ3Bu$e!Q9G?04^nz8cR)WpPAZ~)mg`U-p+7QR#+n{-Ob6A1oMwj9MzQuQGpCwM znS8dNNTn&6Adp0OSb56|h42zph%r&tx{)Hlen)5La9 z-*2RR5>(0|HG2`j27VO;Ld4K%jtoj6AuPj2d=1izNAghVXtDAH{1X5+6if0%KtTW} zClQs{92R()fUrcsg4jI*MN)v&$n%8iu=0ZBnMcxBWO!4gPKhQEdBKQdaITDtBaO1J zN-0SiK#1avj8{WIk(n&0FG=!PnA&LnZY?OHP z@vA<`Ffq;U-1rB@@rEKQv(7b6pH1~VhkA_i2-3z6S4CZwcv z2n*^PQ|b}v4P(T>L2ib?lHqQ2Sh5(PgrTx^@-#v$Kg24pC#_453lec4d4NQ;kea<% zMh%jA1Ixh`vgHYjg{}({mB>s~ko$pD=>T&r;RH#uA(fXNS6{Tkc%;%u=DhHimtFuC zl;$wQ&afh%D2=iVo6Z@h^qD~%)-f8H2O~;~L>{WIR(W0_DXEKCGi^vqJ_@sB1rIB` zRMs!EL#ZTEiA|a*Mp(&(Ww0r8MI{?EB9)nNj95cDX@yv#r^*O}H1^fVQ%5OKBZBo( zi$xueFsDjo^)0BvRh_eGw zag-o-c#kp$A_9?!2bDqc5;N1xg~VnEwq-I?M5QdvdE}8_2qKgxAeoCWJVF+9s^H)$ zt*Nh&N`Iv(POET9J=E$7svd(dgEvJ85C|YevT}q8V1+_uuB!5U`aa22U{-BY2tt}Q z#3-DK5Tk0C0yadSQ^3Yhs-lxB4BuW@mP?lTsD9(OMMdc3K%I0g%=a?C99K6&lLS%9xYE_pZp}J$_hj@0U#Yg z>NGDwTLvP}ODNJ90`hm-G*-lxBKj5mOO~62`mq8(sRCY^a`|0RLX@Bp zV*wylyz=UM#*Bt&hBsd2?npHS5gixdI*Kr6G*3kFrpymg6-CvG(|`?YjYP@>B=(~k zsk9HWSYvoCW66@Yj5!BLL##rFI21;p>8j!st()=(dG-{#5)EpNbt9YFhye~#tvW_& zr23mWO>)PnC_|iv(Ga#SI|~$LUJ*ka(rcgM2SJfUNMHQoO)G4Z(~2_LDZma;7EE+1dDZiz zNHZi+qXc-wa2G{vP=!Q_Sr8H)(?7NWUJFna$;KZEAf0urI%jf+~Xv799Enus;Nxu z8AakzAD-gh)KY-LSD;R!{>h!-5mvc{*h|U1uHqW01C?b2W<3dry2{j-B#UySxXX!_ z$YBCA#py3A!W8o=$K^FPz2bA1X-gD(qUtDcNMlZ^Dh2gA$$(OI14hr1y^{)FFm-=1 z<`4725NBLi(EHF7ekU;@#7Y>&cvI2M=uh-@$^?yN9};=-imynv!c;p=4+wUFgk!Bj zbsn{Xf-_MgbuLGl%vHsOGA0f&t{BCcK}}p%$}*xK>-AMkN(hClvqR%c+_rD_M!@^{Se zUBWp?QSuS1q8hQYtypi;{|O5JR+uu66rZ?cVyZ4Xkr7BzPX0i>pR(-3TDnB4t56bb zyiAMI8lv8;SYhD>d8)7INsV)Zzf|`X09nuuOr~3L;XP4^NLz<-?&S+L)E0?2g8BA4_ zmA=w<4qX+fiAxAfqc*FIUR{8f%}Q2i6?QoNuF6x})!r?-2s zW(Ad)Ap%`epuc0q*pfXN8iy8#LS({a(Sc<`QtT+!@RV1Bh#DbCRte)S6lf`#`;*S- z{E&k5f-yU%z}CHVJ(KE;oMwd!Qwu{>3*{awoIqNe4UxvMfHXS1Jkn4IBULwN;vp1G zN?D|nX;P3WM1iV8BZO0_gJ(U53N2ttddzye>TqHG4+Pv8Q5T?qLkO`eu&Q%JP?oqf%mj>$0T$|W z91hCXr$Du9UgplS1d>6|tl}b(r*l|ik|FZG=xi&Dn^kWWRap6dBD)lP@(kyY8IYuQ zh%pn2H6!aJs;Vz9y>SXt6)k&F*O8<^NC=4o6I8R0@&h_$9LKOMdG@vL9I3}*O)^VX z#Fxy-5u?V-RfTBK1JZ~e*@O^C4T3JhMeY-UE>`&uv%DvxQes+kGL;1n(shLhpnlcl zmE|eM2J#T$6cRa+AOuPHg%WHfFGB&0IR1q0ZW#^g6DnW(B*W9dRs z5mbv1aV*>nG7WQ@U=M@6qBV%LHWDk)SPqU^IYuR$24+^$OkLH$hP7qE*e*vk2c&XT z0z8GZLxQ3;D>E6?Mgu78`D`=>UA+;DYyJL2C-ZpXye-X*l5ZKwYfd09B%}i!AYv*h z3cSSCLzu`v2}r=3DS5JyH<%qF6Jda<{f0FmLL4L7RVNp-f-zeV1a~X@B$X7m8PmNh%-=>>RlB?|Bb@H8BYfz! zbcRs8yJ^aproQR=%fvYb(~Kvj+8fySqB#<$}A>w zL98^$VU6;_5&&jYKsq^cOt7G*6GY&Llt3!+p&-kas7ioT5)_y66o(S#v{WO*QqcHD zWo{~{ktB-blmZ}mwIS-kRXuac>W@l=s_Q}xN>b<@F#)lLccK%I%IjeDSR-ZY^hK>e z!%Vyh)`!<|9J64?~0KooGv=CvDXaADW78C`hbE@)v%U-FZ?dfCv5}9hrhZ$+iAMpTu~rygv|`_21M@^QCR2@LLF%dzF~R6c zh4x9rYX7`OvDDKg)ikJ`Oc#`u7z?DLg3u&rm^@;+E>?lZb`WdhP8oc#9}%Yko*{H! z69I>f+)$%%A|}k=jQTM)<*wKy4qd15Qli($J=xAS$CyTORbmLSCiGs71kl9>DJvzI z316XW)tH*CT4yHZXc~d+wUV9!@kC32kx&Gp2(F;`oj^;}`NYq%lZ}uK()n%?@q2Sf zQ7Pq5i1)xR9<|3>LsezGNVd%B+7-)4H5(>)IWX5+JZebUP#!Wd_ZYE=yCDPjy0JVtOO2TGg_j z8*AN_NcHalq70oSK*X}8B*RHWPA~|F3I)Y~qP!A9f+W7+t2R2H)%}ph;6QAojuLOm z6BS7^+~jpCz#FmRkXEcS@gORVsz8uE8gdwf*71fo9oG(fQ3XuL;#iYTWrgzW%O)JN z^v%mF2JDzsXnA(%dMmktw=OD5&3nW}-E-0sD*qWt`L+B1MS$ zx)q#B;!bj$AOb$R=?^P=OfWG&ur~aW*;2;5W>(0vwxuQF4Dv$JS9xZAQ>mIRr8D7F zj0mFYE9MpLTz4U(eS@`aGh#`nBB?KY_=Pb-TkO)&*WVRtWM6DA?)gQzkyz5VpZ>jKs>=%a$fA%}2yaz@ebi~++zdwvL2~dE z;=(p(*$rD3ZW)JQe;;GxePc0G`5E>pyE}|pq55Ju-M)BLE43e*8eD2tOy5suz13*f zwvS+A0Ub3Ux*3o-@}%9roUHi;n;PmbUN9Zt)ZE|^Ug{>1~!TKltKj#->0u&Il zkY_{Ub_9nbA1}7}7y0BngOiKVMe<(FXA-e%KG6|IB%KnXsuPKEwulA|3UX`-R+hB{ z9Ku+1MMw?^DA1!zeoISB2g4)w(-c|Xus()W#ud_j7Oe4X4=S6HV&!t!ZTrIdpD<%G z>qo<}cZ7)EMVM|I+cD*3Cp~px(>i(4*C+dPv3A86Q#(ou&I7eiTx;@pbW+tyb#YkW z1Ovv*>Fjjktlm0`V&G0D&{P|AP8k*@kv58m({6V{9m}fJ%rx58ux4@OXJMmJf>2!I z=a|)9-NsBQzEB`5yf`E%>rOERcz8LAVmlFTnUs~1!)jlWn8J3U)z-RS1hU9gdDEG9 zqPdyM-k7O;rqx=@E~|!=>qS_{TnOWoltq8P%D zM)A0+51Cbj*zLK_{X7Owtg#l&f>s9$a~Db=XV|-E&3Z5nQ^vx7plQgRC&Q|TSV_C0 zQNY4>FU%dm5GNA8ZyK$Q^D>*Gls)jGP!jPI6k{aBKLNi#==WpMs={W@F0E^ev-`@i z=>u4JX?%BP_%m_Dx%1R%y)Ukx3Red6W;YRM<+^m|0CbBblX_?>EZx)_?hpZGQi0a7 zX7saJYqsjEH{~7JgiVKKi*f=<&XClJVY04e6t83SW(*KpSBRv{To`KuVFZJ=fJ`Fn zJ5Vu=u`c0K@r$^1Cyr+34puiTGXKQc7jOg~Cp(1@n=5;+^u3t8`V;%Qk@lYh!V{wH z2}a1PSA?hsT~6+Wen#h;DvT`GB9N9R@h6p6!>X_*`Ll&~$-Z5rO`hY97O{;oh9joe z4y6j6ePL@v{Y+jiYqrXBOpqT-0nC07!+lP#6n1k&fMd`|Z#%j)^bUnIlHL#ZW*+rt-zc zIFDM3M9SV(jG6RaM4doURPS^uPl)0dtA#16%4=(Vcis7y2OqeqM3yglcN4L!qFS;DqYxs*tiLO&69#YG`X~Te;%NJ-c^TR#a}< zxZ#5H&%6D$+ge&$wDM5%Pf+YOv11b_b?VgV1lUU_#*^Vt<&(8&=io7eA(C9*NKFzU zU@L>q)%wQC?xWj=u+p1-)a&thu_iqrvf|`O-76BCwMf?yOxC+P^_GCaYcSn2i3?$-A9_CNjUc3Ni1lBIAHiY;04_`!n*t17Gd_wRTA0}oPF z6HvEy&DzHw|5tW)HsJ8#M;?U&rsK-U$XLAis^!aKEI=)nh|aC1w`Lk~R+jAPyV??Zpc z;}1UcaBg1St+)QMp{@=(bMeKO0u-Zl?KtyayI1)*ySjM3rdnQ*IsiqDN|qHFmS-2 zzx?G+P${p!?%EGO{BZK*$)x;|BS%)O1V}#BwQJXR-hOBKvL%0g^lucOIb4C@d^|@11v^SibzUGtTh0wLksrDi~mFv>5#fJbDyFtq|!_)@TwFM1OgB

    U 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 + + + + +]> + + + +The &plasma; Handbook + + + + +Sebastian +Kügler + +sebas@kde.org + +Claus Christensen + + + + +2008–2010 +Sebastian Kügler + + +&FDLNotice; + +2013-06-19 +&kde; 4.11 + + + +&plasma;, the most visible pillar of &kde;, is the core interface to the desktop. + + + + +KDE +Plasma +Plasmoid +Widget +Containments +Desktop +Runner +Kicker + + + + + +Introduction + + +&plasma; is one of the key technologies of &kde; Software Compilation 4 (also known as the +“Pillars of &kde;”), and one of the most visible to users. As &plasma; +treats the user interface differently than a traditional desktop, there may be +confusion on what &plasma; is, what it does, and how to perform common tasks. + + + +This document attempts to address these problems by providing answers to the +most common questions. + + + + +Using &plasma; + + +&plasma; Components + + +&plasma; Widgets and Containments + + +The essence of &plasma; revolves around two basic concepts: + + + + +&plasma; Widgets + + +Applets, or small applications that live on the desktop. + + + + +Containments + + +Applets that act as the container for the &plasma; widgets + + + + + + +On a default desktop, there are two main elements: the Panel and the Desktop +itself. Both are containments in the &plasma; sense. + + + + + +Default &plasma; Desktop + +The &plasma; Desktop can be configured in countless ways. The screenshot seen below shows a fairly standard desktop. Some distributions apply extensive customizations, so your desktop may look different. + +Similarly, the graphical appearance of the interface elements can be styled. These screenshots uses the &kde; default style, Oxygen. + + + +A fairly standard &plasma; Desktop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The program starter. Usually this will be &kickoff;. +A couple of icons giving easy access to often used applications +The Pager widget +The Task Manager, which shows the titles of windows belonging to the applications currently running. No application had opened a window, when the screenshot was taken +The System Tray +The Digital Clock widget +The Panel Toolbox +The Desktop Toolbox (previously known as a Cashew) +A Folder View widget, showing the content of the Desktop folder + + + + + + +The Panel + + +The default panel holds a few &plasma; widgets: starting from the left, there is the +&kickoff; application launcher. You can use it to start applications, open recently +opened files and the usual logout/shutdown options. There is also a structure +that allows you to browse through your applications. The layout has been +optimized for the use case that is most common: starting an application. The +default tab is the Favorites tab that holds the most-used +entries. In the beginning, you'll probably find yourself using the +Applications tab more often. +Once you have found out what your most frequently started applications are, +right click on the items and select the +Add to Favorites to add them to your +Favorites (or directly into the panel or on the desktop. +Note that you need to unlock &plasma; by means of right +clicking on the desktop for any kind of modification). If you prefer the +traditional menu-style application launcher, change it by +right clicking on the menu button and selecting +Switch to Classic Menu Style. + + + +The taskbar is another widget on the panel. It shows an area for all open windows on +all desktops by default. You can make it show all open windows on the current +desktop only by checking Only show tasks from the +current desktop when you right click on the task manager, between +two windows. The size of the text on the taskbar items can be set +in &systemsettings; under the +Application AppearanceFonts +Taskbar. Right-clicking on the taskbar +brings the Settings dialog where you can choose several options to customize +your taskbar. + +Here is a screenshot of the taskbar settings dialog + + + + + + Taskbar settings dialog + + + + + + +Another default panel item is the System Tray, which +is used by traditional applications and widgets as a dock. Right clicking on the +System Tray allows you to open the settings dialog, +where you can set entries to display and their visibility. + + +System Tray settings dialog + + + + + + System Tray settings dialog + + + + +An icon located usually in the system tray is the Device Notifier. +Plug in a USB disk and a dialog will open that allows you to +open the device in &dolphin; or another associated application. + + + + + + + + + + + + + + +The Device Notifier is used for handling pluggable devices such as USB pendrives (also called flash drives or thumb drives), digital cameras, external USB hard drives, &etc; It also comes into play when a medium such as a &CD; or DVD is loaded into an optical drive. + +When you plug in an external device, or load a new medium into a drive, the Notifier window pops up (you can also open it explicitly by clicking on its Panel icon.) It stays open while the cursor is over it, otherwise it hides itself after a few seconds. + +The Notifier window shows a list of all the devices it currently knows about. Moving the mouse cursor over a device will highlight how many possible actions are associated with that device. + + + + + + + + + + + + + + +Clicking anywhere in the shaded box around the device name (but not on the eject/unmount icon if present) expands the entry to show the list of possible actions for that device. The set of actions depends on the device; it is configurable from the Device Notifier's context menu or from the &systemsettings; modules Device Actions and Removable Devices. Simply select one with the mouse or keyboard to launch that action. + +There is also a small icon to the right of each entry showing whether that device is currently accessible (or mounted) or not. Only when a device is not mounted is it safe to physically disconnect it from the computer. Clicking on the icon causes the device to be unmounted and/or the medium to be ejected if it is currently mounted, and will mount it if it is not. Note that unmounting/ejecting might fail if the device still has open files on it, ⪚ if a large file copy hasn't finished. In most cases you can just wait a while and try again. When an unmounting has succeeded, a success icon will be shown on the Device Notifier's icon. + + +The System Tray normally holds some more entries like +&klipper;, &kmix; &etc; + +Some of the default entries in the System Tray are hidden +to save space in the bar. To display these entries click on the small white triangle + +, then use +the &LMB; to launch a widget or the &RMB; to open its settings dialog. + + +The right-most &plasma; widget in the default panel holds the Digital +Clock. +This clock can display the time in different timezones as well as have its size +changed. The clock will adjust its font size to the area it is given by the +surrounding containment (that is the panel in this case). If you choose to +display the date, this date will be rendered using the Small +font option from the &systemsettings; Font +dialog. The time will take the rest of the space. So in the end, you'll choose +yourself the amount of information displayed, and if that fits. If you want to +display more information, make the panel larger or put the clock on the desktop +where it can grow freely. + + + +An optional item on your panel is the Pager. +It allows you to switch between your virtual desktops. +If you change the layout of the Pager +through the Number of rows option, +which will also affect the layout and animations that are shown in &kwin;’s +Desktop Grid effect. +For larger pagers, selecting Display windows icons +typically makes sense. + + + + + + + + + + +The Panel Toolboxes + +If your desktop is unlocked (you can do that by +right clicking on the desktop, or when no +application has the focus, with &Alt;D, L), a small &plasma; +logo will appear in the bottom right corner in the panel (it is commonly named the +“cashew”). Click on this cashew, and the panel controller opens. + + +Panel Settings + + + + + + Panel Settings + + + + +The panel controller allows you to reposition, resize and realign the panel. The +&plasma; widgets living in this panel will adjust their size automatically. +&plasma; widgets have basic knowledge about sizing, provided by the containment. They +are programmed to take advantage of that size, and inform the applet about how +much space they possibly need. In the end, the containment gives a possible size +to the applets, the applets obey. + + + + +Adding Applets + + +Unlock the desktop and you'll be able to add and remove &plasma; widgets from panel +or desktop. You add &plasma; widgets by simply dragging them where you want them. +Right click on an widget to remove it. + + +Add Widgets + + + + + + Add Widgets + + + + +The Get New Widgets button allows you to add widgets +you've previously downloaded and download new &plasma; widgets. +Currently it supports native &plasmagik; packages +and some &Mac; OS X dashboard widgets. Widgets you install this way can then be +accessed just like regular, preinstalled widgets. + + + + +The Desktop + + +The desktop is in fact another containment. One that does not put size +constraints on the applets. Applets can be moved and sized freely. On the +unlocked desktop, &plasma; widgets will show a frame when you move the mouse over +them. This applet handle allows you to move, resize, relocate and realign the +panel. It also allows you to drag &plasma; widgets on the desktop. The buttons in the +corner are used to resize, rotate configure and remove the applet. When +rotated, a &plasma; widget will act magnetic towards 12 o'clock, so it is easy to get +them back into sensible position. By default, most applets keep their aspect +ratio when they are being resized. If you want to freely resize an applet, +hold the &Ctrl; key pressed while resizing. + + + +Right clicking on the desktop also offers you to configure aspects such as the +wallpaper and the layout used, and the mouse actions. It offers to download new +wallpapers through &knewstuff;. + + + +Desktop Settings + + + + + + Desktop Settings + + + + +To change the &plasma; theme or download a new one through &knewstuff; +open the Workspace Appearance Desktop +Theme page in the &systemsettings;. + + +With open applications, it quickly gets hard to see the &plasma; widgets on your +desktop. The Dashboard gets those &plasma; widgets +in front of you, much like the Show desktop functionality +you are used to from traditional desktops. + + + + + +&krunner; + + +&krunner; is a versatile mini command-line. You can use it to start applications, +open web pages, access bookmarks, search through your desktop data, calculate +short equations, and many more.Pressing &Alt;F2 opens the &krunner; dialog. +You just start typing and &krunner; will start searching matches as soon as +you've entered more than two characters. You can open the settings dialog to +learn about &krunner;’s functionality, provided by plugins. You can +navigate through the matches using the tab and arrow keys. + + + +If you want to know what is going on on your system, there is the Show +System Activity button, giving you quick access to a list of windows +and processes, with options to monitor their output and kill processes. + + + + + +Activities + + +The desktop toolbox, accessed via the upper right corner has a button for +displaying your activities, of which &plasma; allows you to have more than one. +Basically, that is multiple desktop containments hosting multiple sets of &plasma; widgets. +Display the Activities bar, select one of the predefined activities +or choose Create Activity +to create a new containment, select your new containment and customize suiting your taste. +&plasma;’s activities and &kwin;’s desktop grid are similar in that respect, but there +is a fundamental difference. While virtual desktop are used to group and organize windows, +&plasma;’s activities are used to group and organize &plasma; widgets. This way, you can +switch between activities and have relevant &plasma; widgets supporting the task you are +currently trying to accomplish. You can create a Free time activity, with +comic strips, a puzzle and other &plasma; widgets, and a Work activity, +with relevant RSS feeds, calculator and calendar, for example. + + + +To delete an activity, press the Stop Activity button on +Activities bar (press &Alt;D then &Alt;A to open this bar) then click +the red 'X' (or press &Alt;D +then &Alt;R) and confirm the +deletion. + + + + + + +Shortcuts + + +Most of &plasma;’s functionality is also accessible through keyboard +shortcuts. The various combinations should be pressed in sequence, that +is for example &Alt;D, A +means: Press &Alt; and D, release and press A. + +Currently, the following default shortcuts can be used: + + + + +&Alt;D, A +Add Widgets + + + +&Alt;D, R +Remove Widget + + + +&Alt;D, L +Lock/Unlock Widgets + + + + +&Alt;D, N +Next Widget + + + +&Alt;D, P +Previous Widget + + + +&Alt;D, S +Widget settings + + + +&Alt;D, &Alt;A +Activities + + + +&Alt;D, &Alt;R +Remove this Activity + + + +&Alt;D, &Alt;S +Activities Settings + + + +Meta +Next Activity + + + +Meta&Shift; +Previous Activity + + + +&Ctrl;F12 +Show Dashboard + + + +&Alt;D, T +Run the Associated Application + + + + + +To change shortcuts, click with the &LMB; on the desktop Toolbox +(the cashew usually at the top right of the desktop) and select Shortcut Settings. + + + + + + +Credits and License + + +&plasma; + + +Program copyright 2008 &Aaron.J.Seigo; &Aaron.J.Seigo.mail; + + + +Documentation Copyright © 2008–2010 Sebastian Kügler sebas@kde.org + + + + +&underFDL; + + + +&documentation.index; + + + diff --git a/doc/plasma-desktop/panel-settings.png b/doc/plasma-desktop/panel-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..49fe1dc48caa6b56ffd6e8fb27ec3eea53b6a891 GIT binary patch literal 35520 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%0Ao}nL) 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 literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/plasma-desktop-annotated.png b/doc/plasma-desktop/plasma-desktop-annotated.png new file mode 100644 index 0000000000000000000000000000000000000000..8ab73438f9f93000ad8bdac85c0e8a2525f1bc50 GIT binary patch literal 387050 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

    ~0fx$EK`I1kQ& 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�L*S+KI&S3gBiAnLwD*X*PaP(zHW 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 eF*Q0eH!CnQIxsLxBVX_U0000#L>! literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/system-tray-settings.png b/doc/plasma-desktop/system-tray-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ff1c3a59337853d425b17ba2a9b145b56b32cd GIT binary patch literal 44856 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 literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/system-tray-up-arrow.png b/doc/plasma-desktop/system-tray-up-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..6de1abb999695eb6d91c80367cd723e97b4c3f56 GIT binary patch literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^;vmccBp8l5cGmzY&H|6fVg?4j!ywFfJby(BNU*HH zF&#*QRWtB4aqj_gn3BBRT^Rni_n+AhdGatf+YT^S;NUe81_3j>s?Qh}UnQdAaK2tEb)1&&{#ek^OmDZTsra94S21$?&!TD(=<%vb94CUqJdYO6I#mR{U Zse1WE>9gP2NC6cwc)I$ztaD0e0s#IardI#} literal 0 HcmV?d00001 diff --git a/doc/plasma-desktop/taskbar-settings.png b/doc/plasma-desktop/taskbar-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..47c61e979372ffe9a664b01d1de0cbd190f0291b GIT binary patch literal 47842 zcmYhi1yGyM*9J-{PH}g4C{m<_0>z!;60EoccXvwB;!bggpuw%UI|O%kce&~B|J}Ja zGnvdJn|*ipob#OL$c8B?N}-_;qrkwxpvg#!tH8j(dceTEn?Qnvexnj|qyYUuwwKm+ zf`LKr{`Y>@Z&z&c?@L#E5%d3dG|a~|gLg16O=B|RB5Ll7$8F}$IFPmC;pV+njJxi( zBk!+nZF^|QWa+D3>{OUm{u5pp$j|QsxG58YF-6Y^jY)#M&f0Y9XIaadHC+e>(fH0^ zWQ>PtEV+q!ba=holjav|i)<~0Ur$mOi07ix6(2b3+s7m*F_GY44N)1qiQL=JyI-GZ zO4o%d`qC>e@k)av(B^U-`B9#bs*%BYj9jz{DUzY8^53*D6wvc~Qq0IUqVs0_@kOa0 zL%FhN-(63?hNg?Z(F&CFc3*QmihsF&U;Yw}>Fe{j1(ci7C2U|uxBhEwp?Psq`{}UT z6OZ>EN!{+D^l5=dGY|Dq7d7{0eWpgPjAclU#U}SdacNcX(4|$Wnnm$pUf+jA;?gI~ zc;#6s1&TPKQZLLq%9Ff8#4vI$v`wLWpMe5wK@$XNJojyW6MyXAu)j(3G(xe(0*cV{ z@WsN4$cx`wp;^Ej2JjoJq1^-*tD}h*&seF`ygTfZbcv^mB2MGxKAOzWX$nmeO7pTf z$N`5YkpsNkD|5iV?>y_;{MN)s{?xm^Uv#l3ME^=g=%ZTnE|VXr@FR9}B!}L7&rFNu zi{4aL-P3P@+|`o1n49k*u3edBt2h?+MmJ*~Km(U+^_cp0=UIqmPMdmp+4Y}sm{ZjN zA4N~0PmdI|_ZF5yKP0pG?-{LxV#F!bRI{wQD*boM46hR>b00)!iE>|7Ejxn1KP@^c z+6?qfDH_i{pSD!)=QKEUf(aeb9u>lUgM#cLt``}@3~A;djW@h*%?MSMGRHQw7i>lP z5mwC`y$$1nY`m6b(ROcMk>3<3D2XF_f}2KoNsr9&2*x5d^9K4%yhiGUY0a^~{%7JAcbXhoE*_vz%<_%P3nqV8qZf4YHQBr>j>uoFE(g zenOS#nu;@uRf4e`2=HEVS?b8C=xwG$wi!Lp;Q!?e9BQO@Udq;3qU+=_*G1v9Eemj9 ziv@i-!!FSrZ$BXuS1roq-~{8OC2E0se8Gy<6%|RnH3@7$iO*#ksgEWABkdx*iW%m~ z!zTQ+xlK{5-#SXVYHIo#8oFvo3hv4|n8a3xx$s!HDDcaH&$*(?+Lp+z`1Y5mA;e)y zZfuMi`8SBH`Tzhd_J;ku=)20+x*m~So+CgEOV;q9IcKLS-4E^nn5mfe4~4lp>>^t- z!hKa0l}NQHQaY1+zNLKdZrK%F#gB^5w$Ca8gFh<>`CPJ=k)vN4%F)lIQ=z z(etvKiTMzJt3!SX8!7L(U}-X7Q)cz}UA@A#WYJ_g*tOt^lSH2U-{@09aNG^g$fv>~@YGLkJC^+Tfc^HzG4pdr& z!a)E`KZl%{zXP9m(^PVPOgI^SOyJa?(42?)Guz0kHUG_88%sy`vIaa^(SGU8T(Lf& zBUJW{Hau#(QTW#oszGAov&*HNDyV{yg$*0|$JP0Z2ZllAZo3_7J{4lS#C0nvqj8Sy zQyGH?=Fwaiupt`5p6yJ9*Ho7Tw3U_!qV|3|AD8^FhFwrK(IS4xV`*T7h%+$%}%xVhD7Z#6TFXMLCcnEV>l`QYfnPd1WE>;O6GM#D?-wcdm4O zOV?pwp>HxlreYGz89);Y{k$D>M z(osUFREa}c!9D|M%0ow@`?kBg~QpnV{yu^^c{6 zyU`enGI%Xw(?fO4BDpW(J%j z9wfhu)*|urOv*J`r;xX?Nt&PEU%rc%lqxG{oOs<#G~v=|+i{p_WJ;~!q=TElV6dv! z&)E55|YIdT!!jRdh{y2#Gaa9oekD2xv|Axcim|J z@oAn#c+%Sw9lxtacymR+yC-(xBVrp{k$1`6bKEI?cX*l__E!tuKyzwb?{x zHW^ONLp@IUw!UXL^&s5agB0^xLC3q&nG1;h~yiTvI|(*&S0Gdt$Xo>kqQ51?uw$k z$7uON72o>lfJZNPj`zsQVeuv2VATGFbhAlDuH#|+D!7ZEqquPc)-f92XGR_`85Aa&>}WfK(p#>{;FV;q^5{@R&N-t zRXiVFdJ8775?D=))Pdyc5h-Oz+B$SRE5S|`BK5%1r(xl+OZ9`?pQVz{Y%^}gCaZ^*3&j=5%<~iQr(gYUrPSJbcT1n> zTiIi}P&(t$QQ@ogE|Wof4Ty359M@gojJZVw*w~i~lUK0K#!*J~HfN+|)whwn&~>aC zTC{Ft0p5Q=;MnZZ`&}F1vC+Xw%K03jFdm{nTq$L=l;*RTWw11NlT(XEP+C8?^UOtd zB>3lPv^t`}AoLUSp^m5Ln0lAFA<&m2{&1^=sT1=d}>X) zt6l1?psATm>LblI6vvjvr_j$~E4Xq-+NxRGo~q&C`5H$c8w6!_uKMnF9u58XoJ z{s`jRyXQ#BhJ9Y|SGzOu>eHM^ z%RukX61ilRf?9j-b$PzJGKix~LqlUGpXqotesnJ=Bm1l0HqJ4_A}R`jL8C+sq+9Pi z*aaW4JB}04+pHbqA2+X{;se5)!)Zw(@P5l1Pdbfwv%3p0T)ERoaL@QS-B72!Uf0(v zE~1Bz(&%ox+DN}iubEBKQd2fOZI>W+f zbkX~9B@SH*>g(%W>KcF`m-_la@W%Qz>K7M&2*_Pys=Nu88F`BEF~ZK+^P^uoWLfZo z2tBQ5@=yiP#~{nil$RBJ?4T?sfKR;@L-6SbE~415CU_h#CRaszayp z)LvYcwD+=CRX8q)0^O%LE*gFhAl6;#Yz?T0&k6Lgo~)=9A(*p^QX$O5^sr;+3;=3= zWwD*g7);A%OWRr@rwi$Dw@9uIVxDo{;={WoO(;AykrBk(ju&T7C`s2@5?BNf#{$WY z0GP6lqOA^jFE^S%@7A?W<#m#io<=Q>jB21otO#;!LX?4;L8MEmg~ojyr;M0cAoO5uBy{AW8q*j_KW4wi1vOt zcddj+JIhliDuIAy@VX+0g@go8lkLwVjA8*rPm0A=Rj zE$2rWze^Zbru5j4)oyfxps0jEPm#{Bp7kZ;U)Rv5mO_(gL+h?$eq<$3*%4rYxBZVH1>94$i=$2+C zh-8f8^NNR`rGiuGe$Iy!0-~(`Z#fo8kS1^t*FD zNgXj6*OdM>Ve8aVJ^P{G3*ga;q0e0|eSroJsDVqoWG5B04TE=2{}@m3>Ji#jB?#vt-|IPq^!yI;v%$jP^+Du8K7{e|<4rrCV}o zuY!-XM!K_?Z&BvLp@2?8663_;^cw=&k%kH@c4wALi<`HAM<6O(zk-4S=Gvh~93}y( zT@;Dc0375{0~Tb;MQDE?^Ro>P3C``cX}0M1yv4DtNq^Yfyal{??SRv~?ERdTzAR!`VQQ{0RN6=?zQ6JM7COQdZ_S4YM0Yo-NL zl+w|G-$=mqC4(rEfDZA)oyNXd$$SI81#JIb!3o7<;TUgQOVauHXQHnz(^HSHK001f z5$m@qjK_{&;azJ2+%tc^boZI{+B(FA96c}6qC#2%qtD!xc7Gt=q!>Wvi$Uy-Euxxk zR!F8dEEXGCALyD4Dm-hwE=(2jbE$UWQ^f#TdC(S0W zR8-@JtA$M3NOU{3drO#P?h}#RAI@_GJ@+Zq%A}S24P;~;jkIO33@NxqrYhjZNREqa z5wl^`l-6Y9u$_Gd(6KA3Cw(6;Mgp6htgN{2B$*P!cjWN1_rm7@2C~)%_6Vuz4+X{R;@fq&DH2PfixFt8gb4cVD&gW%tZ2EY3a3TGhGmqd+`x3aa&7akq&3txPsnMj zD>}{|<5#1N8Is4<8SU%pD<%_V?7c2ui;q4xfDv6db+uA1k2@2vnw#T$zQMOC{z#Ig z3sDxtOJHf}tlSQ#d(c`e)~ZcXSMu}>m9LJjV&!Fq=Z?H?&43X$2$B@&ysHq&JK4J8 zWlu&psSU8G{)>C%So7j@qXCO>czC$!pykQpv6m?~jG#@}FiyEd3aHPjWXJQ_HZeC0 zdew*%A_Gp<;EF?$7^cGwySg!78tFiksD}Pb+wi_Fes;Y#j~J6u=eZUdTl$4M zV^T=AJVQ&f$bI@~YNuPgMhCQF8jZhI7o3y#k}ajV+%$AKm6Oro((=F9agotj%kq?Hr6Yew{HC&b$m_z{ zG)4{aR>kNIhkL$n)Vg~76@i899*t_QK!i32!`WZmH(v|k2t_@iOYIl@x0t(4xT$lR+I z@RVVz3Y0R3AhwmXH7OTpl%?}DEd97@ZsuQH;{#^VTK4>zwy~T15Se{oJ_lEEGAcfP zS>M1*6j?esHTfi7Nxu%XJmOxiyEREW@BJXvh&#u(blKkaJ{_XG)ka>& z{UHAnHhp$^adEZfho-r?SNg3hM^GY(VBg}@+`FP|Hz&PJd*W5TJ9MIV0@I}nsi0Mt zcDuf@pxwIbk3pGmHlf~jigNM9Zp7-ImdiwQbAc$Ye-#Ny)tco$r4d?pw6zrla*tE< zX!EO7dvwHwRJ{~vg*p@Hm}-BpuwIatw6M1q*FrMPBf}>p#3t=A;(&%Z3NLCf+^?(% zf}cN6T+6}+2EnFAeho5Y^bGwop`@WQlD&t3h!7l_I)PYD%Kjd7^OKXcdq97JpMZbup+9YBUCQnr{#8Bb!y(NM({TN3}?VBkSsSG{sF`5 zd0)iYgpiFzkU@Y(fQ5~p`g*eaDHdzP1=GFh$#{O<9ePa&V~wl0TF@Q&9}ufT|jtelz^(HAT-NJre^V2&6b8||8`oyq5q zXf*7+{D%iyp_m1h#5QU5lhGf1F82-P)o_FU6ydQgjIRbT6L~aED#unye;;0J!Hz=B zrKaqm#;Q1#0(R;s$8P*&37aT~yS#F=B%b77tx=1@Cr5CS`}Jo58EZpN2Vfl;6RZ4e z*3z~2b}&SI%V{^?KVxVk)IIe25Qul1QPs*xCqa##o|+VgOG0*V^02saLf0xv?D+YC z)w+QZLrT5$-IERdRf77#+j7i_JpF3@mD4V z^z#|MKAeqYq&GI2#?in>>F;sv>_V@Ire4s(L9l}CnT1bU#&$1Uaa&lw|ib@%frZg#C-mkrvywvZ1- z>eR>?I$HDR?fn^Y4gU;LYUN&;lP<*#+v$03!=>v&TKmQ3)Z_4JA?ECu`tIp|iq zHGLM=^doe-%y4%j-vtL3Bi!Ma^S{|%8!KKrDSBF$gw3Yrw&o+@CP?-EO zi!n)pHFLhLtz~y}TT3%P|0*9J-=frq1^#zSe9G(fMJ`UD%Dz&yfsknn{3r5{D?W; zVHF-?tiQN=z<#|R$`oLT!!ViMG74&x0EZz6T75`SYu12o!EGy}y!nWCqf*W8@-F_( zB#?=bcpyJTM%@N+#CmM%h0ldt%`8I}Cec4JSDR@F++T^J^K2!8B$uyMy^^cdf>7f= ze5kCQ14KrCzd%ggySX2w>y>WATwOl+H{2_6fy4pL-;|9bjR~55e(VPC5;gaMeeX?Us zR57gx|JV$v)yf$ zhYTs%+}#@j&o@@AtoXFFoq&n2E9!I0Q}Xt|6MK%wpRtzBOg9x-nE7;+N!j8y^)!FV zg31ce4=VU}m6flje{}Y#8ctd=#1$8~am4hU!4%Q{~n(z5X#o>k+T14 zsLIE8@NyVE*{BHDfg91E{lN9qQkA&l$wr$Z$pcr5i1Ml2O7tT(_q&v3GY zw*C~Ln8YK<<>O-+L(|mM9}^Paz0QryL42W#C4-m2+kF-K6ZQIHu3=JPr_tFSDSn@0E9r-k6PZ#9K*P z7Rv#x-q1J*`KNCEB{c}V>Qe5>G@raFO+5EyoUN`?mPRUu=Bbx*b)BOV+(Av zkwcEA#Z%3)kE3&#_p{{TE=j0$pNEq^xDFGy)UR6JO<8RLNOzN#aCiA-n{UxwEABu% zRF#%DY3;E?C{F;~cd8W1adE#-@=eV9O^QD9q^n?;N=%kYnDKbD;H2tSpy;1$XfBCq zNwL%~i}vy}$GG?o-!|5trBX1sv5hsp;P3LwH>0DvlI`kQQL)E*DoC~M{!>RLfs~q` zK$%LkCD@yYq3DTxn;~wT6qS0WixBlv#R8D}Co>+LChXxvqw_=Q4u1Y%aFEdxTa1h6 zFm_XYzJ=1Ub4PHKBD)@j>EV0S!fnGKtIXUw=_ydQ^D!9z$BpINS4h{&)!J;=!Vo;la{UMK` z0SlbD zv7XU&0I^1F7#yV9%!|+xeGLkl1^!!GN?K4sA&G7LIF0t6v8*R=iIwU+tAuLGl3+pN zz({GrOyTa98cmVPRB3^kORz54DdZK!FxIHT-sV>h5K&<9z0-DW>zv>uaK)+Z@%vrc zeV3A79ppSrKR48~_de89L3lAjdtv!~`%j}JWv}hzuG)^C?=bN~Xx6*cKTv+7l2DRJ zk9;Lr6voUVk{hooNu#bb*!&Im_fz>Ug;^rj!SwQ0#VmaX!J`31^@EfiOK;NGZL6tF z+&}i2Zw-l&{=-#lHHd)SmVr9SrFHZ%_TVj~%ffm8UeSw>3&Bup9&X|dLXr5A@ zHek)n`%uDhpq37{YSU(6Bg-lA%zm-T!o+97M48hX7RP7KK;^XL)n*h;lc<_hEt;&UvcfVKmlq)bH&%zdA182=@0Yvru z`XG%b@G^17;*8u^XS@jIpKdl)6I>83C(Bj+)A6jYaQa_;;C_UOoTGR>9aqm*vS$hU z8ZI2g6MU!W@P38EZy07NpBsHHLulChz5*S)cQR(}6XWjRAms{S< z=#$W#DifSUb z8v}|O36SZOQ+KzhzEt5GUSA`ApuPSpim@nQ7%LM2g${{1jB+u z*F9*z^7N#5iw^eW$ri?7^Ia6iYK5j?F8EXPgsJyiY^3IEiO?TGW@xzK#-}j9YKq+} z)86-}yo6}h6agbU4CaLOj8BR~)B3HQwS?@0^~hUuJ|^d&*e)~5>5|~@-*L35sJ#Uk zyv6E-+UsWrW~Y%CYDmH%YCQ&_%ze1DHbaV*4Mzu2xm8)Bsd81*3DpmdqH{K6RvlGq zIdF~6L~Ey~;acIPDurbNEGtE*toh2?wq>^=alW@KD&@!!l%t_=RHl#kMA+w)I?AQ5 zT1pZ2uGwkXHMyei*@yzWBYoKLs|vb*C{I;c;=~WlbI~oW@A~q%3C~Z`y8)<`KQZ$V zQ8C2V~#Iy z&*91d-2uZ-#<|pDfv`;21US7c0}Xk=BQ_VCutVea%b=@n4d-eTvJW!pQJu0s)Ppu- zF23>HG|z3@AuawexPmQQ|A9lyOM#Zo%Lz}B{v0JLaIk>wq#7J|%V_kZtYzPagh*L8 zp9jZVK$@eG@`9{>H^m_1aFXK2L!%58l*X^7*ds+p2AB>T(uJ2=LQp>sE{>Jcujk~rM$ z9D8{PxcgJTw2-yI)t*jO>oX%TDxG3)5DTJ-9txJoGbEQ>PYxjV6 z)KqIpC!3o9pzc#Z$-blGC9MtC2zF{s`@*gawWeq9&V&^p)04NZ^Z^yxA1#Lj7??5Zw2r(TC`^AXf`y_Q-7kAgzaXs0ywvn1r}zM zid`K`ql}3btu<&hnL!~+iQ@z+a425Q9mLWQd|vM#11%Y(0EMF#TKW_f!>gI)Wyd8N z#ys7VXQ`;7DhRmGz^tp%N6meIU_8`#@qN9ut{ve!)hC~P=3yS|V?acg5o&^UPNGad zOm)w6{SUsq1<@vWV=gUYr7}sWng%5{w^Fbe;Uc758kC^Nk~k#feSdzj)sL}TI5wtO zqIP}f!$cBv;36!{@*suA>z))7&D-ZzEC<9vc@aAgpt$O0cXp}m>=Jmawo!MIa z!_IK3qi~(MR&R=fbao!_l4{9xopIc_FI^t6UPbu7-11S*%hQx1}2m8Q&_(WN`p+Wf4~BvwJN?;pwF95P>RP6I0z;3Lf<6sb&<_L_muvgNV@b&>U0 zVx_5I%F4@Gx%u!22=?}z#$NWU{VOr*0$d$z^h!dY#U#IhM3*mLh}7Bik*}MZAE%}q zNlGg18XuS`!D>6uQ)NsqINtIptRZ)9$VRl5-eI3wRUcPV5Agi`K5Y`FD!^M5@we!LJ>y*%U0 zlgs#j z+r?^!BO~&}Q5vc=ob)U#EDQ{qtVz1)rR`YCSM4`1OMLq8w*bC21PW6J+xeQ@UOhW9 zv{TX1(Y7Rox3}n8g9f&*gS}{DelzabX>}m9?0YXMXdMy0tL3$ShnlJb0#19D0ey_| zeKbs8WXAq#Y#aD(#A&5(b3V&%vD)AjB{|1 zDSKmcGtK~3cGV2GMBU1(Nn<)x9%}^Lx(KqCDTIXNaxzqXDJNq6rVzvCRqeXjaZLcW8qbkLfxfX5&x zAHh6am0RHnN|>T462$nk$y9&vMeXY?dHg#=cHwD|G_1KzT^-t*32^2*2?GPT^}xmYd^48Ar^Yk z`Z2i0R(Zir^|P;bmsY^nwwl?8aTv9D56I!x?dHOesT|cl+=I}S;u=TKk?~k{H&aLmG!QeUQSOAS$9jtmM@Z6Bu}Hp2!@eI z=79lu5c%M4F=u@e+sj9Yj9D#z_SMZsL18o$Lr)DvCCb^PYZw6(yLpUZb7qrTNY$U- z*rrY7X|mLNfte>$Q_ie!e`sKg~K+>xCPgWX`9kAcm77h&*x zXZl&{_}Scl`Unst>%9KW;;}-d>4md$`&~^9O`EM?(An37yGrpeo5O)vq}VHjW$>a- zZqJO}LUkSx$O9^nG^v^chmX}AqBAg5*A222_Jc9glai83XQRG+X=24MYhHZ*1h(c) z@88nYgj6j&=zb)?Zz9s!5{ZY}A+!r6xT-Yc?ZY=7OI;GuZ`F=u_QImEoyRK%gPO_sHpTBA-h0^OfDPr z|44|oLzU;`NDO~g`*6|Q!`w=}B|cth>Yj@q@eFXRy%ZP675;nnHi>mQ*8_D1!sibR zN>v~8LJb+mc2nwRmG*PfaQ7TjmGbwIMX-M;qnx#^IKRYIicr4|9mP6_+1eRaIY zgj0UmU94(voO6WK>|`>jpC~GN%WR?gKo*a*m$Ga-kc>3Gyb=9a8VA46H^dR*HQafJ zUE3XL>xVEp$dqTI)bELl>>_=b)IW%EepAf|N*q4f0SrIIXkU(P54kchfEq7668->f z{O0iSlVuBpU#_TQly{(_nq>#MpcARuJ8>?k*Ex!JFvZJfygx5y4doiKzr*#5Rtp3@OVC^OaIEFbz~y*(hzg4e)^Fxm?ELh|L&8~#97Qdg>*#*c*>1wCP<1ncRM^7}? zS5%C?f<`O;+iI|GL~s;$*f&BL5vv@3DXcQD-_;z86JR>P`*e6Gn?L!2^~Y`TI8-Wv z(KE{=iOKx~BO~Y-zw07^h9PfFH_HqSUH?{uvkM4MjQ9raX7^HI{D8B#zDO$L<$U19 zz|dNCp-mbgX>Mw2T2xRVB`&VTt$`E<9DjXzwoweZ$_gOe2Ef4v*keO}p8sb$zk$6c z%5-O$83Vca20!n2TkfyizP>sg?c_xGEewOrZH4X%)jz)x`CA=2u!1%NL&k$* z44c9-zV_7Nb1)t+f@5O4{2&S7VNK}5)uBR*^^4OLQTfCJ21O}y6Mn!q%8V|spwB>3 zBX3I~TW+HZCKk1lVB`Qe8R*yeFv8NZ{P3Ij|3)HU<{g2d1IwD(%8Q``do%@q4b(;e z>97y(`~ z5?q(|CSX`EU4Isz)rv^`-ihS&r=_l3(I>QlVPlx4CTB7&^bsQtEqVI%-l=E6*U;`A z#|Q6rr4qG2t*i;=rf_f^A{chtWe3dZF^b@B9BlEd$y ze$>h7iW>)tlN^NdW*;+MZr32>UuL1+eEqs7k%xU*r&}PypTFaMNV`pSF-g ztR7>Su!)W_M%^4G%Gf)QH@2Z@sdx0f%@=xJu!d5PzIzPvBoM&%V*aHDg+5N#V8H)` z^y}~8V$bEATPuBVeEhHfo-nov2fV4~c1i95?i}=64^}w|7*5~)q7@Sy_&sULsy|_6wev@<{r^R1I z8tA#q%2zL6Xddr%>4LOGzvBGu;!3Vq;c}Qt;LMX6H>iIc_h*fZ1Garw*@W6_w6 z8o=5SfOPpZ1lV+|Z`16EH4vOCYBMp5>BB*I7frQ=-$TS2pO@Ir`Q7G5sHrH@!MDS+ zm}jC@Eq>#+k{_dJaj;w3S9k|!cRE)EWiG0(>XUyT{7U147(R6<# zX|>4)tg0!mZ=3Dnw#=5~Zvfa^Tg~0#jNb7FPL(C2OpWqCAmE4mL{8{!Lt~MENG8`c z?v-UmA>%LvF}#Lt5^meg`=MOEoy&wkZoHz6Q=88TQaX<1nCbS|^w8{zM$^iMQ@{9e zwnx@x##ju2ZrpFMZ~Zn}o3iH%BJf2Yqe2CEQT=k!Pu8U3Jhs>0xswp%`j2Puc_o3i zH{q|)@D0G;B@0}ghj_!)@>*<3wYH4 z^oLBs_R3~ot7+>cf&PslJi_!A_eW`Q((%gBUxT+07|)U7$@^z=r_kEW!{Bc` z$_{L7pNwfw`T6?xu?)5+Yn;cfJYP`s86qh{335bsp`BswPsbNxRTO2(O z^O2##?85)c4qAE_$8|o~W8PIy2`#=342)7OFhcR}^ZSXw5Y!L4a%dyqScy?~ZD#YW zB6BK)uFgxy34iHuDld>csf6WQ8*ShHMOxpBhT1zJzd&BfpW2EpqSz(Id?WFZIxBk8X(8yRMO-r`v0n;qlZEQ$=SY47=$#Y|n%+9o>d6 zmt6NFWJ~o%b_AnYQvcI1glj#Ps(CP$#OQb`GsAYMmyi>FWpFmmc7u0!gVt`_Ot?$S z?-s=jxQ7Ucbr)Cl98ngB4))f0VrYD!A_dPTDggxfD%mf@^p6)Y7x3>CJPU+>cHvj{ z?&3}afn{KCHjJL4yFKMLt3i!cQS*T+J$s4(13echyJ!#;Oi!Q>WKbt(NO=0e4{59i&O#ZMorJ+ zR6}AwES0$mRjv}gdE}9VBm;SIpneS#VSanDs;jUl5+OML{r`tl_Bp*EG&~-`96ri_ z0Jo&~pR+DIXwe6j0JF9kUp%7NQ%n0j(2$DYnUP8lkkS6i%iSny{H0dFHYa43cx>bQXumHp$57RjBu!b=@c-xVKEUb| zt^pvf&d$zxmND{5+W+~H0NsfHLG8V`u3XeF%I(F!yNi^5hc^-5KFEl-!U~0Ej_0St z?ursQ=VH1Rje~PwO{pB&pi^>+Pr9ph+Syt?|M0Z3vI^!>!p{5{O!ltfCo=B8W>KUb zOev+9@ty4;1sy;d$stf-a&hW|X*O+w6a(4@A>=X^7z@Pum4nRoNv}c!%*_XZFb}?4 zDJ3S({>pEOgxH)!Jpc}x1kW511Q5z1HD(n5vPaT7I!bT>qc|QOSqb|-BkdS6IUi!) z=8l66VYdNLmto|;QAHR*FcPXM0E+K7M1;Tp+W?~mC`*V})hs$bJ`TRD!YxG)ZbKqq ze)R2dEpEnt{d2<2>Ehy|&4>DWDFKrBj2^W1gPg0M$7hK4GQ*qR2Z~+Mj%@R4R5Xa* zk-8D~Cb|ORdZ_xi5xox&5Au0oqh=A})b4Z{y?a-vC@5O2Nq<=fp#G1IjV(yJ;lCYZ z4LIC%#~$jU8kVV0(G`I-qM_4d1H0kFMTOkL+odkvVC?TR&+)Rl>p%@hScz8tP zRu&fSFONJ?l4TVYJSp&HfzL59F>`Yo+W>LlYbxU}h<7J~zT5Vmve>Pn0L>4$1MCC+ zt@l|Jihi}0#?sls(gd&&3k-I?g-MUWSb zFajSIOD@rTK`omcuOa=EA zeow{4Be!bJR$RiQkFy(aXVI@TIC*p>p{0}-ba^H$CYXY{rpvkE_Z{oeHadJ226u zXl7=`HL_WgdJiwr8pv0<((wwtZ2H@z1(Qfj=8|;fvl8V{$#8F_g}DPrM}P2VWKo`-~gVeI+8xs#bz&RnE2)O z!E{_4_CSwWfVfE6#>R$d4rU|?1%=;67yL8pfD}mLx)ykMw%~I)KN*>jA20R$TUr$% zFAEJ%>bPMM9i36C6#6kV&+6oEk2%lzMJUNzELi7@<9R1E33GS4hH{K6C_MZ~25*Q-OZK6g{-12ln1&KkM~JAq&+9SKyoQ=q@ki)}f}!y-Etd@1 z7Zf6>0N#OSUwlt6T~CIS*+mMnXXTPV@^Et(&szPmNC)GO0beudgPG?`AlhPj~u>%A(%Ij(6N6CDxm@0@)m5Of1&fY@^#-h-Qa zzbRs^A>Ajv8L6Kr5sj2ozifj-iivOSpHn7>@!8Wjd^1WaNE&&$8NacDEY-^LJP8^+0!+zt+)LpTT&&g)Qs!2eZ9d5h*q!q z8ay%1l-_sC`fqn;4&xBa# zP8Fet<)93wGFG8~lM;e#?sP~MyAP-r1VI;si0&i5V+_vG*4Bo)IFy%?`g;7!m6a6| z5)wQ~oSqtJ&a$Vkk|Tu{doWMxH>Cv>!YL83MD^bl&){+pWKsv`>9G(fzhL?QOnOTu!*yxVV6`vM8b?-vf>A_yX8B7@1jE;^X7< z^70m}>ywj{RZ4n(*7_S^9yhnN5a8jxJYS7N#xQOgX_(9Ua!NJp$|JVP+)LRC`wKUP95!@391PGb{!GpUK2*DEE z2KT{&yK8U{?hbHX)C_JcP-nW ztFc4{eo#=Bp^c3n;%MmUfj#_#*jxJ zd&oOqnGV;%&hDAM7{X*sQ;Zl!NUCP#n1st&5&VZ>({RQqWvx&7bXZPt2h$Ks zr%I|l2hq;2yex%Egds8gNClAM=|-V5?DInlMjjrX3|=}venOUdgxIX(TiCo4XPf>lMz zkoHOWHt?(pppl-W-~cVJ`5 z9e#8ujisTuxJsr#5O{hKIw1%lih<;4v;>k344BCK+`FD|kyh7L8hV>GYn1acv%c@o zHpn(#X#8t8KW(ngE<|80_!Xa8BBFP&?+=sR?{rdYa`h z^__`|v{dyWY3sYz#!vj*^r-!=52x_!K--t$IFK)tHK!? zG~JFT`^X=7ioXPijoULzvOzA+ymChJ;B^>}A+f*)fRX$2HZNKNmTqutyH6WV>o;20 zA?TNp-T1Nt&2kYfo>6+gxmnv=s!4B3ig3>+( z%C9ippy~WTYHTX)9U}FXnd=Mg8Y9`859|rxoT$Fvr_YINeQ0o)_h*u^aAMvcld%3y zHc#Q-fUkpm#RhtgKv;voR5i+Fgtt0lGD~4|?Zt#O-vBVmXIwbC!e$PISv3We@g2_o2>oRa=fL8zTg1~^S^x7 zSK5VMuJf@QS#AEsSMYX@Jl<50xHV5Xt(xr!u zGoUp;gpdyR49yEjoUL>0lpA) z*MIUy(goQ%%g`@Ww917k-Iiv_GM+;#`gtL&9m z8;bw}-nZl_D4^)F{hc&;p}dz)1gtgbhZQwXnf^<+yUm3p0M3*)Lxyl%iHGO<{|9I6 zZOnz-IWb`Y^8yf}$CfA5*5?i5d42?d^b3N0&Nq4*}+5F2Q z3iGT5zwYJ7f8aq~I<>+}qinGc3iH40H} zKUkR!JU$+Ny7M?%tQ#NG%H5NNL9}Xc`w{JrrghdZ&Y!%wVZyOLi#6bMzqPNG0jVUl z1oG&cmH&%es2pKp$E?paQkYefP&95gAiD)Tow2ED=jom)7?Xta#pqlCHWiS}kQsH2 z<@|{1*%0OiK-w5>JpE*e&Sq5skPI_^Ue*q#js5NBV&4!#*x+!*@J%m)uvwGCeZcrd z46=GBb2tefv(eN*WE!Scvn_JtyW<;4JjO&OJCuxJZPi|1;3AV)VXqe+NZ8%s>YSDq z&dvmXG2WX==9w?}0}VpU`D7OUe5@lh&3{h3aU0l2!kr(;u|(b>sW{!x0k*OIjTM%D zw3zR1e-QN*)sDC;w^G0rlk2>Z*YV-8K|aFfYN#dR@$A;_o7Uq4$2Wmmk6}Sxo@&bu zTttyQ<`y2OxBVJl93TufGf`a#i?_S|lgGGIg1QwxcUMB2(?36!YTP!})y+)10!jJD znU_B1_?AdvI4%uNYY6}G=BJR@i##w;&9-u}exg@@Zz4~*XZz|G@j4FPJ0a)W7;3CL znbc*Jozqk61%g#wz2!-}c}}xm#e!na+>J5`oG<%}3m_Jjma>x4eglmBcb4}Ug6?i^ ze2so=+f#;S%+u#NOYW~>?ZvO}E>~eMUNSX?-LBe15q+7CJE1HCk{oM70)pdU*Zb?y zX(;;z**`GX=~<`5{RQIJ3B)h5H~4S7He{cPLZ4T!)z#IR@^n*LBkGJ`GHbn<@+m{6 z5hDc{aQ+7T?$=hk*+D?wLwbU1$dmEo+jeDUW;@U@lOdRXhuRv0f$Y$#odV?i7?zTf z-@jb!N)4xv>(HtU0p#iXqwo{&e>@k{wMH=C*?1a|t!*sl6+}}_PENJY9m%9lbU{(K z2D?zizl!ZLe{AmvLpLvav~Y&!G2W@e(KK1? z_j0KkJVrz5Gz6g)z<*o4&v+69iDM9X!+S{+P7&@O4C67jGPEthrOWxaWT7d2t$mF! z2ViPYlP;Gi#KveC0Fpi*en}4wS=NLT@|h0qDyraP1e{IA7iFNC+3sx)=HiMzi)VpC zYigP;4RNKW;r<@NuxDtgYt_K+ePj#q`-UMrHp7xD;`rM&2#7Y*NQ`M+ zI%5fStj{jNM+T?e>x#_Bu0TM2O5k54dZokIn)Qmfra?b8GQzCqMvL^l+Q!+z7 zpbYOHOlm`6iLW+(w>sW&`9M%^)g!#IE5gfzZbsyU|jEK?-Ij+QTq zu(!7t1hAi5H&!pySQzr)`=05ZWvzy^%CGxfz0QF&jGek!}?_p+G&viyZ)1?Rt}}z1nhh4omN< z8R^;MS>$K*pcV`;1S0E9<9Tyw)P-a@4-6nZwr0 z+Nq+upC6deXXm@RC5g9tThU*E;Oek??ZZ<;cCvif^31<&Z@u2(sd;={nUL_I-yE%Q zo~m=jkE?Uo3Oh3zZp{TSrY*%YS+hUV7URq5=m(5tAeD&-*Jxv-Q(Qc>_?ODfX+POpEIFTUuK?F( z_?!d8YUBLE00i6Hgqwamy%iumgMN)hd)Wl~&<0*5Ge_s;Yn~@TLuFV%#_}@-XT{F?mfX2W(zE=uf>~;iVxUS_ z73s5+S?E zrFJRryk@a_Ec3o$QY#Z^FS2@hYCoT$&j zGf%%_=IM*HwEGt8;9)CZJS2I)Ed9k=-8JhqH6`< z0iVd30hY&J<0yG@26!?_Jo@A>?jM5Y9_ufAfX44*-K^%~xyn3%UMAsi#u1G`aM@lv zfbW{u;`OmrP(jLeYg+p8%iP|1H#LPvy8)o{AZpEM{R7`5yg}CZJca-yjbLvG0;(T9 zo78}ku4u$7WDw!@)<;Nz65GV2LR@5)MSdxy(EAh!VL-O(O}kN^AhHN$PPm=#N~aoT zIpX{4cpeqkADj1u;!110lz-sfbZM?GX}*OI``4!ZX0w)_^5OBk^ZG)yUNese(u@P; zb>~sJdUzAhui4V9EWkOf*eW)(3Y}VU=62G@FNRwlsGy=Ke0W&6|ahlgaL5 zE4%LKOwFzdxp;)B+AJ@`Zq>mS61EU_^e&#UT!syh~0_CpV3^_1yBuPP~?~n4gh1Mgve* zKEtd7s=z`K9#2Gf!znRFrN$of-)|2};Ruvd+ai0mg0d>W4D-@UXY%V^0abo3ixzj( z&Vvp*SxUV4m8U!FrKzDB=h~~gR6HIbw`~`Q!@7(8^w3_B^sCD{fM^Q1aiLdz#7aZF3rkXX%_6E-fOIuV<9cMRT!B@A3jaX3K zcvuuVV_ZpH-Vas`ewZ9Y3r=_YXKVI&B}??GF1d)$f7FL)9;%LbYspHZYzLHx2(-oM zuTe+raAwgL9CZ~8d`elT+hcjs(op$`fkj-O(7dWY(k|kj#nHIv z%5HnkUGt_W6Y_*`0ppjFhP>-in{+EHp@&S~f@ zzy5DDZdiBssmv4AdY(r+Fc{_{K3m6rLymIv}AWr!{ghdweG`|KSVS5%G3Br&z( zRn~V|-o7MvR>$4Q^zsJR?tMp&&AFPjYNxRIYv*ld7Dj$8OJFzWuJIor|b#6-17tlJ{&%vBRyFWcuBDlIMNkD8oouKYZrI#_6IQ1+rw zVs|OY?yNoskp&o{+-!HdpE-X2-@2_UTb(_T-8 zH{2{0OKj=orH21{AhW*zTZY`@BYuGTzHV)y@Qi8BGCQqaeC}FrT{+LYXZWVFu+U

    utbw7&(s8yR!>9Iu^Pnm061 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 FKLF=xb7BAh literal 0 HcmV?d00001 diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt new file mode 100644 index 0000000000..204e72c080 --- /dev/null +++ b/kcms/CMakeLists.txt @@ -0,0 +1,49 @@ +project(kcms) + +remove_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_STRICT_ITERATORS -DQT_NO_CAST_FROM_BYTEARRAY -DQT_NO_KEYWORDS) + +find_package(Freetype) +set_package_properties(Freetype PROPERTIES DESCRIPTION "A font rendering engine" + URL "http://www.freetype.org" + TYPE OPTIONAL + PURPOSE "Needed to build kfontinst, a simple font installer." + ) + + +set(libkxftconfig_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/fonts/kxftconfig.cpp ) + +if(X11_Xkb_FOUND) + add_subdirectory( keyboard ) +endif() + +if(NOT WIN32) +add_subdirectory( bell ) + +if (LIBUSB_FOUND) + add_subdirectory( input ) +endif() + +add_subdirectory( access ) +add_subdirectory( dateandtime ) +add_subdirectory( autostart ) +endif() + +add_subdirectory( launch ) +add_subdirectory( colors ) +add_subdirectory( krdb ) +add_subdirectory( style ) +add_subdirectory( desktoptheme ) +add_subdirectory( standard_actions ) +add_subdirectory( keys ) + +add_subdirectory( hardware ) +add_subdirectory( desktoppaths ) + +if( FREETYPE_FOUND ) + if( WIN32 OR FONTCONFIG_FOUND ) + add_subdirectory( fonts ) + endif() +endif() +if(FONTCONFIG_FOUND AND FREETYPE_FOUND AND NOT WIN32) + add_subdirectory( kfontinst ) +endif() diff --git a/kcms/PURPOSE b/kcms/PURPOSE new file mode 100644 index 0000000000..ef03e579ef --- /dev/null +++ b/kcms/PURPOSE @@ -0,0 +1,10 @@ +System Settings is: +-Desktop Configuration +-User System Configuration + +System Settings is not: +-Application Configuration +-System Administration/Configuration +-Tools/Utilities + +On other environments the already provided equivalent should be used. In KDE the other environment equivalents should not be needed. diff --git a/kcms/access/CMakeLists.txt b/kcms/access/CMakeLists.txt new file mode 100644 index 0000000000..a7903eeab3 --- /dev/null +++ b/kcms/access/CMakeLists.txt @@ -0,0 +1,58 @@ + + + +########### next target ############### +find_package(Phonon4Qt5 REQUIRED NO_MODULE) +include_directories(${PHONON_INCLUDE_DIR}) + +set(kcm_access_PART_SRCS kcmaccess.cpp ) + + +add_library(kcm_access MODULE ${kcm_access_PART_SRCS}) + + +target_link_libraries(kcm_access + Qt5::X11Extras + KF5::KCMUtils + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::NotifyConfig + KF5::WindowSystem + KF5::KDE4Support + ${X11_LIBRARIES} +) + +install(TARGETS kcm_access DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### next target ############### + +set(kaccess_KDEINIT_SRCS kaccess.cpp main.cpp ) + + +kf5_add_kdeinit_executable( kaccess ${kaccess_KDEINIT_SRCS}) + +target_link_libraries(kdeinit_kaccess + Qt5::Widgets + Qt5::X11Extras + KF5::ConfigCore + KF5::Completion + KF5::I18n + KF5::IconThemes + KF5::Notifications + KF5::WidgetsAddons + KF5::WindowSystem + Phonon::phonon4qt5 + KF5::KDE4Support + ${X11_LIBRARIES} +) + +install(TARGETS kdeinit_kaccess ${INSTALL_TARGETS_DEFAULT_ARGS} ) +install(TARGETS kaccess ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +########### install files ############### + +install( FILES kcmaccess.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES kaccess.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES kaccess.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kaccess/ ) diff --git a/kcms/access/Messages.sh b/kcms/access/Messages.sh new file mode 100644 index 0000000000..3834cc09a8 --- /dev/null +++ b/kcms/access/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +### TODO: why do we need 2 POT files for a single directory? +$XGETTEXT kaccess.cpp main.cpp rc.cpp -o $podir/kaccess.pot +$XGETTEXT kcmaccess.cpp rc.cpp -o $podir/kcmaccess.pot diff --git a/kcms/access/kaccess.cpp b/kcms/access/kaccess.cpp new file mode 100644 index 0000000000..87cd688c11 --- /dev/null +++ b/kcms/access/kaccess.cpp @@ -0,0 +1,921 @@ +#include + +#include "kaccess.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define XK_MISCELLANY +#define XK_XKB_KEYS +#include + +#include +#include + +struct ModifierKey { + const unsigned int mask; + const KeySym keysym; + const char *name; + const char *lockedText; + const char *latchedText; + const char *unlatchedText; +}; + +static ModifierKey modifierKeys[] = { + { ShiftMask, 0, "Shift", + I18N_NOOP("The Shift key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Shift key is now active."), + I18N_NOOP("The Shift key is now inactive.") }, + { ControlMask, 0, "Control", + I18N_NOOP("The Control key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Control key is now active."), + I18N_NOOP("The Control key is now inactive.") }, + { 0, XK_Alt_L, "Alt", + I18N_NOOP("The Alt key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Alt key is now active."), + I18N_NOOP("The Alt key is now inactive.") }, + { 0, 0, "Win", + I18N_NOOP("The Win key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Win key is now active."), + I18N_NOOP("The Win key is now inactive.") }, + { 0, XK_Meta_L, "Meta", + I18N_NOOP("The Meta key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Meta key is now active."), + I18N_NOOP("The Meta key is now inactive.") }, + { 0, XK_Super_L, "Super", + I18N_NOOP("The Super key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Super key is now active."), + I18N_NOOP("The Super key is now inactive.") }, + { 0, XK_Hyper_L, "Hyper", + I18N_NOOP("The Hyper key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Hyper key is now active."), + I18N_NOOP("The Hyper key is now inactive.") }, + { 0, 0, "Alt Graph", + I18N_NOOP("The Alt Graph key has been locked and is now active for all of the following keypresses."), + I18N_NOOP("The Alt Graph key is now active."), + I18N_NOOP("The Alt Graph key is now inactive.") }, + { 0, XK_Num_Lock, "Num Lock", + I18N_NOOP("The Num Lock key has been activated."), + "", + I18N_NOOP("The Num Lock key is now inactive.") }, + { LockMask, 0, "Caps Lock", + I18N_NOOP("The Caps Lock key has been activated."), + "", + I18N_NOOP("The Caps Lock key is now inactive.") }, + { 0, XK_Scroll_Lock, "Scroll Lock", + I18N_NOOP("The Scroll Lock key has been activated."), + "", + I18N_NOOP("The Scroll Lock key is now inactive.") }, + { 0, 0, "", "", "", "" } +}; + + +/********************************************************************/ + + +KAccessApp::KAccessApp(bool allowStyles, bool GUIenabled) + : KUniqueApplication(allowStyles, GUIenabled), + overlay(0), _player(0) +{ + _activeWindow = KWindowSystem::activeWindow(); + connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(activeWindowChanged(WId))); + + features = 0; + requestedFeatures = 0; + dialog = 0; + + initMasks(); + XkbStateRec state_return; + XkbGetState (QX11Info::display(), XkbUseCoreKbd, &state_return); + unsigned char latched = XkbStateMods (&state_return); + unsigned char locked = XkbModLocks (&state_return); + state = ((int)locked)<<8 | latched; +} + +int KAccessApp::newInstance() +{ + KGlobal::config()->reparseConfiguration(); + readSettings(); + return 0; +} + +void KAccessApp::readSettings() +{ + KSharedConfig::Ptr _config = KGlobal::config(); + KConfigGroup cg(_config, "Bell"); + + // bell --------------------------------------------------------------- + _systemBell = cg.readEntry("SystemBell", true); + _artsBell = cg.readEntry("ArtsBell", false); + _currentPlayerSource = cg.readPathEntry("ArtsBellFile", QString()); + _visibleBell = cg.readEntry("VisibleBell", false); + _visibleBellInvert = cg.readEntry("VisibleBellInvert", false); + _visibleBellColor = cg.readEntry("VisibleBellColor", QColor(Qt::red)); + _visibleBellPause = cg.readEntry("VisibleBellPause", 500); + + // select bell events if we need them + int state = (_artsBell || _visibleBell) ? XkbBellNotifyMask : 0; + XkbSelectEvents(QX11Info::display(), XkbUseCoreKbd, XkbBellNotifyMask, state); + + // deactivate system bell if not needed + if (!_systemBell) + XkbChangeEnabledControls(QX11Info::display(), XkbUseCoreKbd, XkbAudibleBellMask, 0); + else + XkbChangeEnabledControls(QX11Info::display(), XkbUseCoreKbd, XkbAudibleBellMask, XkbAudibleBellMask); + + // keyboard ------------------------------------------------------------- + KConfigGroup keyboardGroup(_config,"Keyboard"); + + // get keyboard state + XkbDescPtr xkb = XkbGetMap(QX11Info::display(), 0, XkbUseCoreKbd); + if (!xkb) + return; + if (XkbGetControls(QX11Info::display(), XkbAllControlsMask, xkb) != Success) + return; + + // sticky keys + if (keyboardGroup.readEntry("StickyKeys", false)) + { + if (keyboardGroup.readEntry("StickyKeysLatch", true)) + xkb->ctrls->ax_options |= XkbAX_LatchToLockMask; + else + xkb->ctrls->ax_options &= ~XkbAX_LatchToLockMask; + if (keyboardGroup.readEntry("StickyKeysAutoOff", false)) + xkb->ctrls->ax_options |= XkbAX_TwoKeysMask; + else + xkb->ctrls->ax_options &= ~XkbAX_TwoKeysMask; + if (keyboardGroup.readEntry("StickyKeysBeep", false)) + xkb->ctrls->ax_options |= XkbAX_StickyKeysFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_StickyKeysFBMask; + xkb->ctrls->enabled_ctrls |= XkbStickyKeysMask; + } + else + xkb->ctrls->enabled_ctrls &= ~XkbStickyKeysMask; + + // toggle keys + if (keyboardGroup.readEntry("ToggleKeysBeep", false)) + xkb->ctrls->ax_options |= XkbAX_IndicatorFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_IndicatorFBMask; + + // slow keys + if (keyboardGroup.readEntry("SlowKeys", false)) { + if (keyboardGroup.readEntry("SlowKeysPressBeep", false)) + xkb->ctrls->ax_options |= XkbAX_SKPressFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_SKPressFBMask; + if (keyboardGroup.readEntry("SlowKeysAcceptBeep", false)) + xkb->ctrls->ax_options |= XkbAX_SKAcceptFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_SKAcceptFBMask; + if (keyboardGroup.readEntry("SlowKeysRejectBeep", false)) + xkb->ctrls->ax_options |= XkbAX_SKRejectFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_SKRejectFBMask; + xkb->ctrls->enabled_ctrls |= XkbSlowKeysMask; + } + else + xkb->ctrls->enabled_ctrls &= ~XkbSlowKeysMask; + xkb->ctrls->slow_keys_delay = keyboardGroup.readEntry("SlowKeysDelay", 500); + + // bounce keys + if (keyboardGroup.readEntry("BounceKeys", false)) { + if (keyboardGroup.readEntry("BounceKeysRejectBeep", false)) + xkb->ctrls->ax_options |= XkbAX_BKRejectFBMask; + else + xkb->ctrls->ax_options &= ~XkbAX_BKRejectFBMask; + xkb->ctrls->enabled_ctrls |= XkbBounceKeysMask; + } + else + xkb->ctrls->enabled_ctrls &= ~XkbBounceKeysMask; + xkb->ctrls->debounce_delay = keyboardGroup.readEntry("BounceKeysDelay", 500); + + // gestures for enabling the other features + _gestures = keyboardGroup.readEntry("Gestures", false); + if (_gestures) + xkb->ctrls->enabled_ctrls |= XkbAccessXKeysMask; + else + xkb->ctrls->enabled_ctrls &= ~XkbAccessXKeysMask; + + // timeout + if (keyboardGroup.readEntry("AccessXTimeout", false)) + { + xkb->ctrls->ax_timeout = keyboardGroup.readEntry("AccessXTimeoutDelay", 30)*60; + xkb->ctrls->axt_opts_mask = 0; + xkb->ctrls->axt_opts_values = 0; + xkb->ctrls->axt_ctrls_mask = XkbStickyKeysMask | XkbSlowKeysMask; + xkb->ctrls->axt_ctrls_values = 0; + xkb->ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; + } + else + xkb->ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; + + // gestures for enabling the other features + if (keyboardGroup.readEntry("AccessXBeep", true)) + xkb->ctrls->ax_options |= XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask; + else + xkb->ctrls->ax_options &= ~(XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask); + + _gestureConfirmation = keyboardGroup.readEntry("GestureConfirmation", false); + + _kNotifyModifiers = keyboardGroup.readEntry("kNotifyModifiers", false); + _kNotifyAccessX = keyboardGroup.readEntry("kNotifyAccessX", false); + + // mouse-by-keyboard ---------------------------------------------- + + KConfigGroup mouseGroup(_config,"Mouse"); + + if (mouseGroup.readEntry("MouseKeys", false)) + { + xkb->ctrls->mk_delay = mouseGroup.readEntry("MKDelay", 160); + + // Default for initial velocity: 200 pixels/sec + int interval = mouseGroup.readEntry("MKInterval", 5); + xkb->ctrls->mk_interval = interval; + + // Default time to reach maximum speed: 5000 msec + xkb->ctrls->mk_time_to_max = mouseGroup.readEntry("MKTimeToMax", + (5000+interval/2)/interval); + + // Default maximum speed: 1000 pixels/sec + // (The old default maximum speed from KDE <= 3.4 + // (100000 pixels/sec) was way too fast) + xkb->ctrls->mk_max_speed = mouseGroup.readEntry("MKMaxSpeed", interval); + + xkb->ctrls->mk_curve = mouseGroup.readEntry("MKCurve", 0); + xkb->ctrls->mk_dflt_btn = mouseGroup.readEntry("MKDefaultButton", 0); + + xkb->ctrls->enabled_ctrls |= XkbMouseKeysMask; + } + else + xkb->ctrls->enabled_ctrls &= ~XkbMouseKeysMask; + + features = xkb->ctrls->enabled_ctrls & (XkbSlowKeysMask | XkbBounceKeysMask | XkbStickyKeysMask | XkbMouseKeysMask); + if (dialog == 0) + requestedFeatures = features; + // set state + XkbSetControls(QX11Info::display(), XkbControlsEnabledMask | XkbMouseKeysAccelMask | XkbStickyKeysMask | XkbSlowKeysMask | XkbBounceKeysMask | XkbAccessXKeysMask | XkbAccessXTimeoutMask, xkb); + + // select AccessX events + XkbSelectEvents(QX11Info::display(), XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask); + + // do we need to stay running to perform notifications? + if (!_artsBell && !_visibleBell && !(_gestures && _gestureConfirmation) + && !_kNotifyModifiers && !_kNotifyAccessX) { + + // We will exit, but the features need to stay configured + uint ctrls = XkbStickyKeysMask | XkbSlowKeysMask | XkbBounceKeysMask | XkbMouseKeysMask | XkbAudibleBellMask | XkbControlsNotifyMask; + uint values = xkb->ctrls->enabled_ctrls & ctrls; + XkbSetAutoResetControls(QX11Info::display(), ctrls, &ctrls, &values); + exit(0); + } else { + // reset them after program exit + uint ctrls = XkbStickyKeysMask | XkbSlowKeysMask | XkbBounceKeysMask | XkbMouseKeysMask | XkbAudibleBellMask | XkbControlsNotifyMask; + uint values = XkbAudibleBellMask; + XkbSetAutoResetControls(QX11Info::display(), ctrls, &ctrls, &values); + } + + delete overlay; + overlay = 0; +} + +static int maskToBit (int mask) { + for (int i = 0; i < 8; i++) + if (mask & (1 << i)) + return i; + return -1; +} + +void KAccessApp::initMasks() { + for (int i = 0; i < 8; i++) + keys [i] = -1; + state = 0; + + for (int i = 0; strcmp (modifierKeys[i].name, "") != 0; i++) { + int mask = modifierKeys[i].mask; + if (mask == 0) { + if (modifierKeys[i].keysym != 0) { + mask = XkbKeysymToModifiers (QX11Info::display(), modifierKeys[i].keysym); + } else { + if (!strcmp(modifierKeys[i].name, "Win")) { + mask = KKeyServer::modXMeta(); + } else { + mask = XkbKeysymToModifiers (QX11Info::display(), XK_Mode_switch) + | XkbKeysymToModifiers (QX11Info::display(), XK_ISO_Level3_Shift) + | XkbKeysymToModifiers (QX11Info::display(), XK_ISO_Level3_Latch) + | XkbKeysymToModifiers (QX11Info::display(), XK_ISO_Level3_Lock); + } + } + } + + + int bit = maskToBit (mask); + if (bit != -1 && keys[bit] == -1) + keys[bit] = i; + } +} + +#warning x11EventFilter needs porting to QAbstractNativeEventFilter +#if 0 +bool KAccessApp::x11EventFilter(XEvent *event) +{ + // handle XKB events + if (event->type == xkb_opcode) + { + XkbAnyEvent *ev = (XkbAnyEvent*) event; + + switch (ev->xkb_type) { + case XkbStateNotify: + xkbStateNotify(); + break; + case XkbBellNotify: + xkbBellNotify((XkbBellNotifyEvent*)event); + break; + case XkbControlsNotify: + xkbControlsNotify((XkbControlsNotifyEvent*)event); + break; + } + return true; + } + + // process other events as usual + return KApplication::x11EventFilter(event); +} +#endif + + +void VisualBell::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + QTimer::singleShot(_pause, this, SLOT(hide())); +} + + +void KAccessApp::activeWindowChanged(WId wid) +{ + _activeWindow = wid; +} + + +void KAccessApp::xkbStateNotify () { + XkbStateRec state_return; + XkbGetState (QX11Info::display(), XkbUseCoreKbd, &state_return); + unsigned char latched = XkbStateMods (&state_return); + unsigned char locked = XkbModLocks (&state_return); + int mods = ((int)locked)<<8 | latched; + + if (state != mods) { + if (_kNotifyModifiers) + for (int i = 0; i < 8; i++) { + if (keys[i] != -1) { + if ( !strcmp(modifierKeys[keys[i]].latchedText, "") + && ( (((mods >> i) & 0x101) != 0) != (((state >> i) & 0x101) != 0) )) + { + if ((mods >> i) & 1) { + KNotification::event ("lockkey-locked", i18n(modifierKeys[keys[i]].lockedText)); + } + else { + KNotification::event ("lockkey-unlocked", i18n(modifierKeys[keys[i]].unlatchedText)); + } + } + else if (strcmp(modifierKeys[keys[i]].latchedText, "") + && ( ((mods >> i) & 0x101) != ((state >> i) & 0x101) )) + { + if ((mods >> i) & 0x100) { + KNotification::event ("modifierkey-locked", i18n(modifierKeys[keys[i]].lockedText)); + } + else if ((mods >> i) & 1) { + KNotification::event ( "modifierkey-latched", i18n(modifierKeys[keys[i]].latchedText)); + } + else { + KNotification::event ("modifierkey-unlatched", i18n(modifierKeys[keys[i]].unlatchedText)); + } + } + } + } + state = mods; + } +} + +void KAccessApp::xkbBellNotify(XkbBellNotifyEvent *event) +{ + // bail out if we should not really ring + if (event->event_only) + return; + + // flash the visible bell + if (_visibleBell) + { + // create overlay widget + if (!overlay) + overlay = new VisualBell(_visibleBellPause); + + WId id = _activeWindow; + + NETRect frame, window; + NETWinInfo net(QX11Info::connection(), id, desktop()->winId(), 0); + + net.kdeGeometry(frame, window); + + overlay->setGeometry(window.pos.x, window.pos.y, window.size.width, window.size.height); + + if (_visibleBellInvert) + { + QPixmap screen = QPixmap::grabWindow(id, 0, 0, window.size.width, window.size.height); +#ifdef __GNUC__ +#warning is this the best way to invert a pixmap? +#endif +// QPixmap invert(window.size.width, window.size.height); + QImage i = screen.toImage(); + i.invertPixels(); + QPalette pal = overlay->palette(); + pal.setBrush(overlay->backgroundRole(), QBrush(QPixmap::fromImage(i))); + overlay->setPalette(pal); +/* + QPainter p(&invert); + p.setRasterOp(QPainter::NotCopyROP); + p.drawPixmap(0, 0, screen); + overlay->setBackgroundPixmap(invert); +*/ + } + else + { + QPalette pal = overlay->palette(); + pal.setColor(overlay->backgroundRole(), _visibleBellColor); + overlay->setPalette(pal); + } + + // flash the overlay widget + overlay->raise(); + overlay->show(); + flush(); + } + + // ask Phonon to ring a nice bell + if (_artsBell) { + if (!_player) { // as creating the player is expensive, delay the creation + _player = Phonon::createPlayer(Phonon::AccessibilityCategory); + _player->setParent(this); + _player->setCurrentSource(_currentPlayerSource); + } + _player->play(); + } +} + +QString mouseKeysShortcut (Display *display) { + // Calculate the keycode + KeySym sym = XK_MouseKeys_Enable; + KeyCode code = XKeysymToKeycode(display, sym); + if (code == 0) { + sym = XK_Pointer_EnableKeys; + code = XKeysymToKeycode(display, sym); + if (code == 0) + return ""; // No shortcut available? + } + + // Calculate the modifiers by searching the keysym in the X keyboard mapping + XkbDescPtr xkbdesc = XkbGetMap(display, XkbKeyTypesMask | XkbKeySymsMask, XkbUseCoreKbd); + + if (!xkbdesc) + return ""; // Failed to obtain the mapping from server + + bool found = false; + unsigned char modifiers = 0; + int groups = XkbKeyNumGroups(xkbdesc, code); + for (int grp = 0; grp < groups && !found; grp++) + { + int levels = XkbKeyGroupWidth(xkbdesc, code, grp); + for (int level = 0; level < levels && !found; level++) + { + if (sym == XkbKeySymEntry(xkbdesc, code, level, grp)) + { + // keysym found => determine modifiers + int typeIdx = xkbdesc->map->key_sym_map[code].kt_index[grp]; + XkbKeyTypePtr type = &(xkbdesc->map->types[typeIdx]); + for (int i = 0; i < type->map_count && !found; i++) + { + if (type->map[i].active && (type->map[i].level == level)) + { + modifiers = type->map[i].mods.mask; + found = true; + } + } + } + } + } + XkbFreeClientMap (xkbdesc, 0, true); + + if (!found) + return ""; // Somehow the keycode -> keysym mapping is flawed + + XEvent ev; + ev.type = KeyPress; + ev.xkey.display = display; + ev.xkey.keycode = code; + ev.xkey.state = 0; + int key; + KKeyServer::xEventToQt(&ev, &key); + QString keyname = QKeySequence(key).toString(); + + unsigned int AltMask = KKeyServer::modXAlt(); + unsigned int WinMask = KKeyServer::modXMeta(); + unsigned int NumMask = KKeyServer::modXNumLock(); + unsigned int ScrollMask= KKeyServer::modXScrollLock(); + + unsigned int MetaMask = XkbKeysymToModifiers (display, XK_Meta_L); + unsigned int SuperMask = XkbKeysymToModifiers (display, XK_Super_L); + unsigned int HyperMask = XkbKeysymToModifiers (display, XK_Hyper_L); + unsigned int AltGrMask = XkbKeysymToModifiers (display, XK_Mode_switch) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Shift) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Latch) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Lock); + + unsigned int mods = ShiftMask | ControlMask | AltMask | WinMask + | LockMask | NumMask | ScrollMask; + + AltGrMask &= ~mods; + MetaMask &= ~(mods | AltGrMask); + SuperMask &= ~(mods | AltGrMask | MetaMask); + HyperMask &= ~(mods | AltGrMask | MetaMask | SuperMask); + + if ((modifiers & AltGrMask) != 0) + keyname = i18n("AltGraph") + '+' + keyname; + if ((modifiers & HyperMask) != 0) + keyname = i18n("Hyper") + '+' + keyname; + if ((modifiers & SuperMask) != 0) + keyname = i18n("Super") + '+' + keyname; + if ((modifiers & WinMask) != 0) + keyname = i18n("Meta") + '+' + keyname; + if ((modifiers & WinMask) != 0) + keyname = QKeySequence(Qt::META).toString() + '+' + keyname; + if ((modifiers & AltMask) != 0) + keyname = QKeySequence(Qt::ALT).toString() + '+' + keyname; + if ((modifiers & ControlMask) != 0) + keyname = QKeySequence(Qt::CTRL).toString() + '+' + keyname; + if ((modifiers & ShiftMask) != 0) + keyname = QKeySequence(Qt::SHIFT).toString() + '+' + keyname; + + return keyname; +} + +void KAccessApp::createDialogContents() { + if (dialog == 0) { + dialog = new KDialog( 0 ); + dialog->setCaption( i18n("Warning") ); + dialog->setButtons( KDialog::Yes | KDialog::No ); + dialog->setButtonGuiItem( KDialog::Yes, KStandardGuiItem::yes() ); + dialog->setButtonGuiItem( KDialog::No, KStandardGuiItem::no() ); + dialog->setDefaultButton( KDialog::No ); + dialog->setEscapeButton( KDialog::Close ); + dialog->setObjectName( "AccessXWarning" ); + dialog->setModal( true ); + + KVBox *topcontents = new KVBox (dialog); + topcontents->setSpacing(KDialog::spacingHint()*2); +#ifdef __GNUC__ +#warning "kde4 fixme" +#endif + //topcontents->setMargin(KDialog::marginHint()); + + QWidget *contents = new QWidget(topcontents); + QHBoxLayout * lay = new QHBoxLayout(contents); + lay->setSpacing(KDialog::spacingHint()); + + QLabel *label1 = new QLabel( contents); + QPixmap pixmap = KIconLoader::global()->loadIcon("dialog-warning", KIconLoader::NoGroup, KIconLoader::SizeMedium, KIconLoader::DefaultState, QStringList(), 0, true); + if (pixmap.isNull()) + pixmap = QMessageBox::standardIcon(QMessageBox::Warning); + label1->setPixmap(pixmap); + + lay->addWidget( label1, 0, Qt::AlignCenter ); + lay->addSpacing(KDialog::spacingHint()); + + QVBoxLayout * vlay = new QVBoxLayout(); + lay->addItem( vlay ); + + featuresLabel = new QLabel( "", contents ); + featuresLabel->setAlignment( Qt::AlignVCenter ); + featuresLabel->setWordWrap( true ); + vlay->addWidget( featuresLabel ); + vlay->addStretch(); + + QHBoxLayout * hlay = new QHBoxLayout(); + vlay->addItem(hlay); + + QLabel *showModeLabel = new QLabel( i18n("&When a gesture was used:"), contents ); + hlay->addWidget( showModeLabel ); + + showModeCombobox = new KComboBox (contents); + hlay->addWidget( showModeCombobox ); + showModeLabel->setBuddy(showModeCombobox); + showModeCombobox->insertItem ( 0, i18n("Change Settings Without Asking")); + showModeCombobox->insertItem ( 1, i18n("Show This Confirmation Dialog")); + showModeCombobox->insertItem ( 2, i18n("Deactivate All AccessX Features & Gestures")); + showModeCombobox->setCurrentIndex (1); + + dialog->setMainWidget(topcontents); + + connect (dialog, SIGNAL(yesClicked()), this, SLOT(yesClicked())); + connect (dialog, SIGNAL(noClicked()), this, SLOT(noClicked())); + connect (dialog, SIGNAL(closeClicked()), this, SLOT(dialogClosed())); + } +} + +void KAccessApp::xkbControlsNotify(XkbControlsNotifyEvent *event) +{ + unsigned int newFeatures = event->enabled_ctrls & (XkbSlowKeysMask | XkbBounceKeysMask | XkbStickyKeysMask | XkbMouseKeysMask); + + if (newFeatures != features) { + unsigned int enabled = newFeatures & ~features; + unsigned int disabled = features & ~newFeatures; + + if (!_gestureConfirmation) { + requestedFeatures = enabled | (requestedFeatures & ~disabled); + notifyChanges(); + features = newFeatures; + } + else { + // set the AccessX features back to what they were. We will + // apply the changes later if the user allows us to do that. + readSettings(); + + requestedFeatures = enabled | (requestedFeatures & ~disabled); + + enabled = requestedFeatures & ~features; + disabled = features & ~requestedFeatures; + + QStringList enabledFeatures; + QStringList disabledFeatures; + + if (enabled & XkbStickyKeysMask) + enabledFeatures << i18n("Sticky keys"); + else if (disabled & XkbStickyKeysMask) + disabledFeatures << i18n("Sticky keys"); + + if (enabled & XkbSlowKeysMask) + enabledFeatures << i18n("Slow keys"); + else if (disabled & XkbSlowKeysMask) + disabledFeatures << i18n("Slow keys"); + + if (enabled & XkbBounceKeysMask) + enabledFeatures << i18n("Bounce keys"); + else if (disabled & XkbBounceKeysMask) + disabledFeatures << i18n("Bounce keys"); + + if (enabled & XkbMouseKeysMask) + enabledFeatures << i18n("Mouse keys"); + else if (disabled & XkbMouseKeysMask) + disabledFeatures << i18n("Mouse keys"); + + QString question; + switch (enabledFeatures.count()) { + case 0: switch (disabledFeatures.count()) { + case 1: question = i18n("Do you really want to deactivate \"%1\"?", + disabledFeatures[0]); + break; + case 2: question = i18n("Do you really want to deactivate \"%1\" and \"%2\"?", + disabledFeatures[0], disabledFeatures[1]); + break; + case 3: question = i18n("Do you really want to deactivate \"%1\", \"%2\" and \"%3\"?", + disabledFeatures[0], disabledFeatures[1], + disabledFeatures[2]); + break; + case 4: question = i18n("Do you really want to deactivate \"%1\", \"%2\", \"%3\" and \"%4\"?", + disabledFeatures[0], disabledFeatures[1], + disabledFeatures[2], disabledFeatures[3]); + break; + } + break; + case 1: switch (disabledFeatures.count()) { + case 0: question = i18n("Do you really want to activate \"%1\"?", + enabledFeatures[0]); + break; + case 1: question = i18n("Do you really want to activate \"%1\" and to deactivate \"%2\"?", + enabledFeatures[0], disabledFeatures[0]); + break; + case 2: question = i18n("Do you really want to activate \"%1\" and to deactivate \"%2\" and \"%3\"?", + enabledFeatures[0], disabledFeatures[0], + disabledFeatures[1]); + break; + case 3: question = i18n("Do you really want to activate \"%1\" and to deactivate \"%2\", \"%3\" and \"%4\"?", + enabledFeatures[0], disabledFeatures[0], + disabledFeatures[1], disabledFeatures[2]); + break; + } + break; + case 2: switch (disabledFeatures.count()) { + case 0: question = i18n("Do you really want to activate \"%1\" and \"%2\"?", + enabledFeatures[0], enabledFeatures[1]); + break; + case 1: question = i18n("Do you really want to activate \"%1\" and \"%2\" and to deactivate \"%3\"?", + enabledFeatures[0], enabledFeatures[1], + disabledFeatures[0]); + break; + case 2: question = i18n("Do you really want to activate \"%1\", and \"%2\" and to deactivate \"%3\" and \"%4\"?", + enabledFeatures[0], enabledFeatures[1], + enabledFeatures[0], disabledFeatures[1]); + break; + } + break; + case 3: switch (disabledFeatures.count()) { + case 0: question = i18n("Do you really want to activate \"%1\", \"%2\" and \"%3\"?", + enabledFeatures[0], enabledFeatures[1], + enabledFeatures[2]); + break; + case 1: question = i18n("Do you really want to activate \"%1\", \"%2\" and \"%3\" and to deactivate \"%4\"?", + enabledFeatures[0], enabledFeatures[1], + enabledFeatures[2], disabledFeatures[0]); + break; + } + break; + case 4: question = i18n("Do you really want to activate \"%1\", \"%2\", \"%3\" and \"%4\"?", + enabledFeatures[0], enabledFeatures[1], + enabledFeatures[2], enabledFeatures[3]); + break; + } + QString explanation; + if (enabledFeatures.count()+disabledFeatures.count() == 1) { + explanation = i18n("An application has requested to change this setting."); + + if (_gestures) { + if ((enabled | disabled) == XkbSlowKeysMask) + explanation = i18n("You held down the Shift key for 8 seconds or an application has requested to change this setting."); + else if ((enabled | disabled) == XkbStickyKeysMask) + explanation = i18n("You pressed the Shift key 5 consecutive times or an application has requested to change this setting."); + else if ((enabled | disabled) == XkbMouseKeysMask) { + QString shortcut = mouseKeysShortcut(QX11Info::display()); + if (!shortcut.isEmpty() && !shortcut.isNull()) + explanation = i18n("You pressed %1 or an application has requested to change this setting.", shortcut); + } + } + } + else { + if (_gestures) + explanation = i18n("An application has requested to change these settings, or you used a combination of several keyboard gestures."); + else + explanation = i18n("An application has requested to change these settings."); + } + + createDialogContents(); + featuresLabel->setText ( question+"\n\n"+explanation + +" "+i18n("These AccessX settings are needed for some users with motion impairments and can be configured in the KDE System Settings. You can also turn them on and off with standardized keyboard gestures.\n\nIf you do not need them, you can select \"Deactivate all AccessX features and gestures\".") ); + + KWindowSystem::setState( dialog->winId(), NET::KeepAbove ); + kapp->updateUserTimestamp(); + dialog->show(); + } + } +} + +void KAccessApp::notifyChanges() { + if (!_kNotifyAccessX) + return; + + unsigned int enabled = requestedFeatures & ~features; + unsigned int disabled = features & ~requestedFeatures; + + if (enabled & XkbSlowKeysMask) + KNotification::event ("slowkeys", i18n("Slow keys has been enabled. From now on, you need to press each key for a certain length of time before it gets accepted.")); + else if (disabled & XkbSlowKeysMask) + KNotification::event ("slowkeys", i18n("Slow keys has been disabled.")); + + if (enabled & XkbBounceKeysMask) + KNotification::event ("bouncekeys", i18n("Bounce keys has been enabled. From now on, each key will be blocked for a certain length of time after it was used.")); + else if (disabled & XkbBounceKeysMask) + KNotification::event ("bouncekeys", i18n("Bounce keys has been disabled.")); + + if (enabled & XkbStickyKeysMask) + KNotification::event ("stickykeys", i18n("Sticky keys has been enabled. From now on, modifier keys will stay latched after you have released them.")); + else if (disabled & XkbStickyKeysMask) + KNotification::event ("stickykeys", i18n("Sticky keys has been disabled.")); + + if (enabled & XkbMouseKeysMask) + KNotification::event ("mousekeys", i18n("Mouse keys has been enabled. From now on, you can use the number pad of your keyboard in order to control the mouse.")); + else if (disabled & XkbMouseKeysMask) + KNotification::event ("mousekeys", i18n("Mouse keys has been disabled.")); +} + +void KAccessApp::applyChanges() { + notifyChanges(); + unsigned int enabled = requestedFeatures & ~features; + unsigned int disabled = features & ~requestedFeatures; + + KConfigGroup config(KGlobal::config(), "Keyboard"); + + if (enabled & XkbSlowKeysMask) + config.writeEntry("SlowKeys", true); + else if (disabled & XkbSlowKeysMask) + config.writeEntry("SlowKeys", false); + + if (enabled & XkbBounceKeysMask) + config.writeEntry("BounceKeys", true); + else if (disabled & XkbBounceKeysMask) + config.writeEntry("BounceKeys", false); + + if (enabled & XkbStickyKeysMask) + config.writeEntry("StickyKeys", true); + else if (disabled & XkbStickyKeysMask) + config.writeEntry("StickyKeys", false); + + KConfigGroup mousegrp(KGlobal::config(),"Mouse"); + + if (enabled & XkbMouseKeysMask) + mousegrp.writeEntry("MouseKeys", true); + else if (disabled & XkbMouseKeysMask) + mousegrp.writeEntry("MouseKeys", false); + mousegrp.sync(); + config.sync(); +} + +void KAccessApp::yesClicked() { + if (dialog != 0) + dialog->deleteLater(); + dialog = 0; + + KConfigGroup config(KGlobal::config(), "Keyboard"); + switch (showModeCombobox->currentIndex()) { + case 0: + config.writeEntry("Gestures", true); + config.writeEntry("GestureConfirmation", false); + break; + default: + config.writeEntry("Gestures", true); + config.writeEntry("GestureConfirmation", true); + break; + case 2: + requestedFeatures = 0; + config.writeEntry("Gestures", false); + config.writeEntry("GestureConfirmation", true); + } + config.sync(); + + if (features != requestedFeatures) { + notifyChanges(); + applyChanges(); + } + readSettings(); +} + +void KAccessApp::noClicked() { + if (dialog != 0) + dialog->deleteLater(); + dialog = 0; + requestedFeatures = features; + + KConfigGroup config(KGlobal::config(), "Keyboard"); + switch (showModeCombobox->currentIndex()) { + case 0: + config.writeEntry("Gestures", true); + config.writeEntry("GestureConfirmation", false); + break; + default: + config.writeEntry("Gestures", true); + config.writeEntry("GestureConfirmation", true); + break; + case 2: + requestedFeatures = 0; + config.writeEntry("Gestures", false); + config.writeEntry("GestureConfirmation", true); + } + config.sync(); + + if (features != requestedFeatures) + applyChanges(); + readSettings(); +} + +void KAccessApp::dialogClosed() { + if (dialog != 0) + dialog->deleteLater(); + dialog = 0; + + requestedFeatures = features; +} + +void KAccessApp::setXkbOpcode(int opcode) { + xkb_opcode = opcode; +} + +#include "kaccess.moc" diff --git a/kcms/access/kaccess.desktop b/kcms/access/kaccess.desktop new file mode 100644 index 0000000000..3e0262ea73 --- /dev/null +++ b/kcms/access/kaccess.desktop @@ -0,0 +1,97 @@ +[Desktop Entry] +Type=Service +Name=KDE Accessibility Tool +Name[af]=KDE toeganklikheid program +Name[ar]=أداة كدي للإتاحة +Name[ast]=Ferramienta d'accesibilidad de KDE +Name[be]=Інструмент даступнасці KDE +Name[be@latin]=Pryłada dastupnaści KDE +Name[bg]=Равностоен достъп +Name[bn]=কে.ডি.ই. সহায়ক প্রযুক্তি টুল +Name[br]=Ostilh haezadusted KDE +Name[bs]=KDE alat za pristupačnost +Name[ca]=Eina d'accessibilitat KDE +Name[ca@valencia]=Eina d'accessibilitat KDE +Name[cs]=Nástroj pro zpřístupnění prostředí KDE +Name[csb]=Pòmòce przëstãpù KDE +Name[cy]=Erfyn Hygyrchedd KDE +Name[da]=KDE Tilgængelighedsværktøj +Name[de]=KDE-Zugangshilfen +Name[el]=Εργαλείο προσιτότητας του KDE +Name[en_GB]=KDE Accessibility Tool +Name[eo]=KDE-ilo por alirebleco +Name[es]=Herramienta de accesibilidad de KDE +Name[et]=KDE hõlbustustööriist +Name[eu]=KDEren erabilerraztasun-tresna +Name[fa]=ابزار دستیابی‌پذیری KDE +Name[fi]=KDE:n esteettömyystyökalu +Name[fr]=Outil d'accessibilité de KDE +Name[fy]=KDE Tagonklikens +Name[ga]=Uirlis Inrochtaineachta KDE +Name[gl]=Utilidade de accesibilidade de KDE +Name[gu]=KDE ઉપયોગિતા સાધન +Name[he]=כלי הנגישות של KDE +Name[hi]=केडीई पहुँच औज़ार +Name[hne]=केडीई पहुंच औजार +Name[hr]=KDE pristupačnost +Name[hsb]=KDE pomocnik za přistupnosć +Name[hu]=KDE kezelési segédeszköz +Name[ia]=Instrumento de Accessibilitate de KDE +Name[id]=Alat Aksesibilitas KDE +Name[is]=KDE aðgengistól +Name[it]=Strumento per l'accessibilità di KDE +Name[ja]=KDE アクセシビリティ支援ツール +Name[ka]=KDE-ს სპეცეციალური შესაძლებლობების ხელსაწყოები +Name[kk]=KDE арнайы мүмкіндіктер құралы +Name[km]=ឧបករណ៍​មធ្យោបាយ​ងាយស្រួល​របស់ KDE +Name[kn]=ಕೆಡಿಇ ನಿಲುಕಣೆ (ಅಕ್ಸೆಸಿಬಲಿಟಿ) ಸಲಕರಣೆ +Name[ko]=KDE 접근성 도구 +Name[ku]=KDE Amûra Xwegihandinê +Name[lt]=KDE pritaikymo neįgaliesiems įrankis +Name[lv]=KDE pieejamības rīks +Name[mai]=केडीई पहुँच अओजार +Name[mk]=Алатка за пристапливост во KDE +Name[ml]=കെഡിഇ സാമീപ്യതാ ഉപകരണം +Name[mr]=केडीई सुलभता साधन +Name[ms]=Alat Keaksesan KDE +Name[nb]=Tilgjengelighetsverktøy for KDE +Name[nds]=KDE-Togangwarktüüch +Name[ne]=केडीई पहुँचयोग्य उपकरण +Name[nl]=KDE Toegankelijkheid +Name[nn]=Tilgjengeverktøy for KDE +Name[oc]=Esplech d'accessibilitat de KDE +Name[or]=KDE ଅଭିଗମ୍ୟତା ଉପକରଣ +Name[pa]=KDE ਸਹਾਇਕ ਟੂਲ +Name[pl]=Narzędzie ułatwień dostępu KDE +Name[pt]=Ferramenta de Acessibilidade do KDE +Name[pt_BR]=Ferramenta de Acessibilidade do KDE +Name[ro]=Utilitar de accesibilitate pentru KDE +Name[ru]=Специальные возможности +Name[se]=KDE reaidu álkkibut geavaheami várás +Name[si]=KDE ප්‍රවේශන මෙවලම +Name[sk]=Nástroj na sprístupnenie KDE +Name[sl]=Orodje za dostopnost KDE +Name[sr]=КДЕ‑ова алатка за приступачност +Name[sr@ijekavian]=КДЕ‑ова алатка за приступачност +Name[sr@ijekavianlatin]=KDE‑ova alatka za pristupačnost +Name[sr@latin]=KDE‑ova alatka za pristupačnost +Name[sv]=Handikappverktyg för KDE +Name[ta]=KDE அணுகும் கருவி +Name[te]=KDE అందుబాటు సాధనం +Name[tg]=Имкониятҳои KDE +Name[th]=เครื่องมือปรับการช่วยการใช้งานของ KDE +Name[tr]=KDE Erişilebilirlik Aracı +Name[ug]=ك د ئې(KDE) ياردەمچى ئىقتىدار قوراللىرى +Name[uk]=Утиліта керування доступності KDE +Name[uz]=KDE qulaylik vositasi +Name[uz@cyrillic]=KDE қулайлик воситаси +Name[vi]=Công cụ hỗ trợ truy cập của KDE +Name[wa]=Usteye d' accessibilité di KDE +Name[x-test]=xxKDE Accessibility Toolxx +Name[zh_CN]=KDE 辅助工具 +Name[zh_TW]=KDE 無障礙工具 +Exec=kaccess +X-DBUS-StartupType=None +X-KDE-Library=kcm_access +X-KDE-ParentApp=kcontrol +X-DocPath=kcontrol/kcmaccess/index.html diff --git a/kcms/access/kaccess.h b/kcms/access/kaccess.h new file mode 100644 index 0000000000..716bfcf338 --- /dev/null +++ b/kcms/access/kaccess.h @@ -0,0 +1,118 @@ +#ifndef __K_ACCESS_H__ +#define __K_ACCESS_H__ + + +#include +#include +//Added by qt3to4: +#include +#include + + +#include +#include + +#include + +#include +#define explicit int_explicit // avoid compiler name clash in XKBlib.h +#include +#undef explicit +#include + +class KDialog; +class QLabel; +class KComboBox; + +class KAccessApp : public KUniqueApplication +{ + Q_OBJECT + +public: + + explicit KAccessApp(bool allowStyles=true, bool GUIenabled=true); + +#if 0 + bool x11EventFilter(XEvent *event); +#endif + + int newInstance(); + + void setXkbOpcode(int opcode); + +protected: + + void readSettings(); + + void xkbStateNotify(); + void xkbBellNotify(XkbBellNotifyEvent *event); + void xkbControlsNotify(XkbControlsNotifyEvent *event); + + +private Q_SLOTS: + + void activeWindowChanged(WId wid); + void notifyChanges(); + void applyChanges(); + void yesClicked(); + void noClicked(); + void dialogClosed(); + + +private: + void createDialogContents(); + void initMasks(); + + int xkb_opcode; + unsigned int features; + unsigned int requestedFeatures; + + bool _systemBell, _artsBell, _visibleBell, _visibleBellInvert; + QColor _visibleBellColor; + int _visibleBellPause; + + bool _gestures, _gestureConfirmation; + bool _kNotifyModifiers, _kNotifyAccessX; + + QWidget *overlay; + + Phonon::MediaObject *_player; + QString _currentPlayerSource; + + WId _activeWindow; + + KDialog *dialog; + QLabel *featuresLabel; + KComboBox *showModeCombobox; + + int keys[8]; + int state; +}; + + +class VisualBell : public QWidget +{ + Q_OBJECT + +public: + + VisualBell(int pause) + : QWidget(( QWidget* )0, Qt::X11BypassWindowManagerHint), _pause(pause) + {} + + +protected: + + void paintEvent(QPaintEvent *); + + +private: + + int _pause; + +}; + + + + +#endif diff --git a/kcms/access/kaccess.notifyrc b/kcms/access/kaccess.notifyrc new file mode 100644 index 0000000000..9a228f7bfa --- /dev/null +++ b/kcms/access/kaccess.notifyrc @@ -0,0 +1,1532 @@ +[Global] +IconName=preferences-desktop-accessibility +Comment=Accessibility +Comment[af]=Toeganklikheid +Comment[ar]=الإتاحة +Comment[as]=অভিগম্যতা +Comment[ast]=Accesibilidá +Comment[be]=Даступнасць +Comment[be@latin]=Dastupnaść +Comment[bg]=Равностоен достъп +Comment[bn]=সহায়ক প্রযুক্তি +Comment[bn_IN]=বিশেষ ব্যবহারের সহায়তা +Comment[br]=Haezadusted +Comment[bs]=Pristupačnost +Comment[ca]=Accessibilitat +Comment[ca@valencia]=Accessibilitat +Comment[cs]=Zpřístupnění +Comment[csb]=Pòmòce przëstãpù +Comment[cy]=Hygyrchedd +Comment[da]=Tilgængelighed +Comment[de]=Zugangshilfen +Comment[el]=Προσβασιμότητα +Comment[en_GB]=Accessibility +Comment[eo]=Alirebleco +Comment[es]=Accesibilidad +Comment[et]=Hõlbustus +Comment[eu]=Erabilerraztasuna +Comment[fa]=دستیابی‌پذیری +Comment[fi]=Esteettömyys +Comment[fr]=Accessibilité +Comment[fy]=Tagonklikens +Comment[ga]=Inrochtaineacht +Comment[gl]=Accesibilidade +Comment[gu]=ઉપયોગિતા +Comment[he]=נגישות +Comment[hi]=पहुँच +Comment[hne]=पहुंच +Comment[hr]=Pristupačnost +Comment[hsb]=Přistupnosć +Comment[hu]=Kezelési segítség +Comment[ia]=Accessibilitate +Comment[id]=Aksesibilitas +Comment[is]=Auðveldað aðgengi +Comment[it]=Accessibilità +Comment[ja]=アクセシビリティ +Comment[kk]=Арнайы мүмкіндіктер +Comment[km]=មធ្យោបាយ​ងាយស្រួល +Comment[kn]=ನಿಲುಕಣೆ (ಆಕ್ಸೆಸಿಬಿಲಿಟಿ) +Comment[ko]=내게 필요한 설정 +Comment[ku]=Gihîştin +Comment[lt]=Pritaikymas neįgaliesiems +Comment[lv]=Pieejamība +Comment[mai]=अभिगम्यता +Comment[mk]=Пристапливост +Comment[ml]=സാമീപ്യത +Comment[mr]=सुलभता +Comment[ms]=Kebolehcapaian +Comment[nb]=Tilgjengelighet +Comment[nds]=Toganghülp +Comment[ne]=पहुँचता +Comment[nl]=Toegankelijkheid +Comment[nn]=Tilgjenge +Comment[oc]=Accessibilitat +Comment[or]=ଅଭିଗମ୍ୟତା +Comment[pa]=ਸਹੂਲਤਾਂ +Comment[pl]=Ułatwienia dostępu +Comment[pt]=Acessibilidade +Comment[pt_BR]=Acessibilidade +Comment[ro]=Accesibilitate +Comment[ru]=Специальные возможности +Comment[se]=Álkkibut geavaheapmi +Comment[si]=ප්‍රවේශණය +Comment[sk]=Prístupnosť +Comment[sl]=Dostopnost +Comment[sr]=Приступачност +Comment[sr@ijekavian]=Приступачност +Comment[sr@ijekavianlatin]=Pristupačnost +Comment[sr@latin]=Pristupačnost +Comment[sv]=Handikappstöd +Comment[ta]=அணுகுத்தன்மை +Comment[te]=అందుబాటు +Comment[tg]=Имкониятҳо +Comment[th]=ช่วยการใช้งานให้ง่ายขึ้น +Comment[tr]=Erişilebilirlik +Comment[ug]=ياردەم ئىقتىدارى +Comment[uk]=Доступність +Comment[uz]=Qulayliklar +Comment[uz@cyrillic]=Қулайликлар +Comment[vi]=Hỗ trợ truy cập +Comment[wa]=Accessibilité +Comment[x-test]=xxAccessibilityxx +Comment[zh_CN]=辅助 +Comment[zh_TW]=無障礙輔助 + +[Event/modifierkey-latched] +Name=A modifier key has become active +Name[af]='n Verandering sleutel was geaktiveer +Name[ar]=تم تفعيل مفتاح مغيِّر +Name[ast]=Activosé una tecla modificadora +Name[be@latin]=Klavišny madyfikatar prycisnuty +Name[bg]=Включен е клавиш-модификатор +Name[bn]=একটি মডিফায়ার কী সক্রিয় হয়েছে +Name[bs]=Modifikatorski taster je aktiviran +Name[ca]=Alguna tecla modificadora ha esdevingut activa +Name[ca@valencia]=Alguna tecla modificadora ha esdevingut activa +Name[cs]=Modifikátor klávesnice je aktivní +Name[csb]=Klawisza zjinaczi òsta aktiwòwónô +Name[da]=En ændringstast er blevet aktiv +Name[de]=Eine Modifikator-Taste ist aktiviert worden +Name[el]=Ένα πλήκτρο τροποποιητή έγινε ενεργό +Name[en_GB]=A modifier key has become active +Name[eo]=Modifigita klavo aktiviĝis +Name[es]=Se ha activado una tecla modificadora +Name[et]=Muuteklahv muutus aktiivseks +Name[eu]=Tekla aldatzaile bat aktibatu da +Name[fi]=Muunnosnäppäin on aktivoitunut +Name[fr]=Une touche de modification est devenue active +Name[fy]=In modifkaasjetoets wurdt aktyf +Name[ga]=Tá eochair mhionathraithe gníomhach anois +Name[gl]=Activouse unha tecla modificadora +Name[gu]=બદલવાની કળ સક્રિય બની છે +Name[he]=מקש משנה מצב הפך לפעיל +Name[hi]=कोई मॉडिफ़ायर कुंजी सक्रिय हो गया है +Name[hne]=कोई माडिफायर कुंजी सक्रिय हो गे हे +Name[hr]=Tipka modifikatora je aktivirana +Name[hsb]=Modifikowaca tasta je so aktiwizowała. +Name[hu]=Egy módosító billentyű aktívvá vált +Name[ia]=Un clave de modificator ha devenite active +Name[id]=Sebuah tombol pengubah telah menjadi aktif +Name[is]=Breytilykill er nú virkur +Name[it]=Un tasto modificatore è stato attivato +Name[ja]=修飾キーがアクティブになりました +Name[kk]=Түрлендіргіш перне белсендірілді +Name[km]=គ្រាប់​ចុច​កែប្រែ​ក្លាយ​ជា​សកម្ម +Name[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿ ಸಕ್ರಿಯಗೊಂಡಿದೆ +Name[ko]=수정자 키가 활성화됨 +Name[ku]=Bişkojkeke Guherker hat çalakirin +Name[lt]=Modifikavimo klavišas tapo aktyvus +Name[lv]=Modifikatora taustiņš tika aktivizēts +Name[mk]=Некое копче за модификација стана активно +Name[ml]=ഒരു മോഡിഫയര്‍ കീ സജീവമായിരിക്കുന്നു +Name[mr]=परिवर्तक कि सक्रिय झाली आहे +Name[nb]=En valgtast er slått på +Name[nds]=En Sünnertast is nu aktiev +Name[ne]=परिमार्जक कुञ्जी सक्रिय भएको छ +Name[nl]=Een modificatietoets is geactiveerd +Name[nn]=Ein valtast er no aktiv +Name[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି ସକ୍ରିୟ ହୋଇଯାଇଛି +Name[pa]=ਮੋਡੀਫਾਇਰ ਸਵਿੱਚ ਐਕਟਿਵ ਕੀਤੀ ਗਈ +Name[pl]=Klawisz modyfikujący został włączony +Name[pt]=Ficou activa uma tecla modificadora +Name[pt_BR]=Uma tecla modificadora se tornou ativa +Name[ro]=Un modificator de taste a devenit activ +Name[ru]=Нажата клавиша-модификатор +Name[se]=Válljenboallu lea šaddan aktiiva +Name[si]=වෙනස්කිරීම් යතුර සක්‍රීයයි +Name[sk]=Modifikačný kláves je aktívny +Name[sl]=Spremenilna tipka se je omogočila +Name[sr]=Модификаторски тастер је активиран +Name[sr@ijekavian]=Модификаторски тастер је активиран +Name[sr@ijekavianlatin]=Modifikatorski taster je aktiviran +Name[sr@latin]=Modifikatorski taster je aktiviran +Name[sv]=En väljartangent har aktiverats +Name[ta]=A modifier key has become active +Name[te]=సవరింపు కీ క్రియాశీలం కాబోతోంది +Name[tg]=Нажата клавиша модификатора +Name[th]=ปุ่มพิมพ์ประกอบถูกเปิดการทำงาน +Name[tr]=Bir değiştirici tuş etkinleştirildi +Name[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا ئاكتىپلاندى +Name[uk]=Клавіша модифікатора стала активною +Name[wa]=Ene modifieuse tape a divnou active +Name[x-test]=xxA modifier key has become activexx +Name[zh_CN]=修饰键已经激活 +Name[zh_TW]=組合鍵已啟動 +Comment=A modifier key (e.g. Shift or Ctrl) has changed its state and is now active +Comment[af]='n Veranderingsleutel (bv. Shift of Control) se toestand het verander en is nou aktief +Comment[ar]=مفتاح مغيِّر (شفت او كنترول) غيّر حالته وأصبح مفعلاً +Comment[ast]=Una tecla modificadora (Mayús o Ctrl) camudó l'estáu y ta activa +Comment[be@latin]=Klavišny madyfikatar (naprykład, „Shift” ci „Ctrl”) źmianiŭ svajo stanovišča j ciapier prycisnuty. +Comment[bg]=Клавиш-модификатор (напр. Shift или Ctrl) промени състоянието си и е активен +Comment[bn]=একটি মডিফায়ার কী (e.g. Shift বা Ctrl) অবস্থা পরিবর্তন করে এখন সক্রিয় হয়েছে +Comment[bs]=Modifikatorski taster (npr. Shift ili Ctrl) promijenio je stanje i sada je aktivan +Comment[ca]=Ha canviat l'estat d'una tecla modificadora (p.ex. Majúscules o Control) i ara està activa +Comment[ca@valencia]=Ha canviat l'estat d'una tecla modificadora (p.ex. Majúscules o Control) i ara està activa +Comment[cs]=Modifikátor klávesnice (Shift nebo Ctrl) změnil stav a je právě aktivní +Comment[csb]=Klawisza zjinaczi (Shift abò Control) zmienia swój sztatus ë je aktiwòwónô +Comment[da]=En ændringstast (f.eks. Skift eller Ctrl) har ændret sin tilstand og er nu aktiv +Comment[de]=Eine Modifikator-Taste (Umschalt oder Strg) hat ihren Status verändert und ist nun aktiv +Comment[el]=Ένα πλήκτρο τροποποιητή (π.χ., Shift ή Ctrl) άλλαξε την κατάστασή του και είναι τώρα ενεργό +Comment[en_GB]=A modifier key (e.g. Shift or Ctrl) has changed its state and is now active +Comment[eo]=Modifa klavo (ekz. majuskliga klavo aŭ stirklavo) ŝanĝis sian staton kaj nun estas aktiva +Comment[es]=Una tecla modificadora (Mayús o Ctrl) ha cambiado su estado y está activa +Comment[et]=Muuteklahv (nt. Shift või Ctrl) muutis oma olekut ning on nüüd aktiivne +Comment[eu]=Tekla aldatzaile bat (adibidez, Maius edo Ktrl) egoeraz aldatu da, eta orain aktibo dago +Comment[fi]=Muunnosnäppäin (esim. Shift tai Ctrl) on vaihtanut tilaa ja on nyt aktiivinen +Comment[fr]=Une touche de modification (ex : « Maj. » ou « Ctrl. ») a changé d'état et est maintenant active +Comment[fy]=De tastân fan in modifikaasjetoets (lykas Shift of Control) is feroare en is no aktyf +Comment[ga]=Athraíodh staid eochrach mionathraithe (m.sh. Shift nó Ctrl) agus tá sí gníomhach anois +Comment[gl]=Unha tecla modificadora (por ex. Maiús ou Ctrl) cambiou de estado e agora está activa +Comment[gu]=બદલવાની કળે (દા.ત., શીફ્ટ અથવા કંટ્રોલ) હવે તેની સ્થિતિ બદલી છે અને હવે સક્રિય છે +Comment[he]=מקש משנה מצב (למשל Shift או Ctrl) שינה את מצבו וכרגע פעיל +Comment[hne]=कोई माडिफायर कुंजी (जइसन कि शिफ्ट या कंट्रोल) हर अपन स्थिति ल बदल दे हे अउ अब वो हर सक्रिय हो गे हे +Comment[hr]=Tipka modifikatora (npr. SHIFT ili CTRL) promijenila je svoje stanje i aktivna je +Comment[hsb]=Modifikowaca tasta (na př. Wulkopis abo Strg) je status změniła a je nětko aktiwna. +Comment[hu]=Egy módosító billentyű (pl. a Shift vagy a Ctrl) aktívvá vált +Comment[ia]=Un clave modificator (p.ex. Shift o Ctrl) ha cambiate su stato e ora es active +Comment[id]=Sebuah tombol pengubah (misalnya Shift atau Ctrl) telah diubah keadaannya dan sekarang aktif +Comment[is]=Breytilykill (t.d. Shift eða Ctrl) hefur breytt um stöðu og er nú virkur +Comment[it]=Un tasto modificatore (come Shift o Ctrl) ha cambiato stato ed è ora attivo +Comment[ja]=修飾キー (Shift や Ctrl) の状態が変更され、アクティブになりました +Comment[kk]=Түрлендіргіш перне (мыс. Shift не Ctrl) күйін ауыстырып енді белсенді +Comment[km]=គ្រាប់ចុច​កែប្រែ (ឧ. ប្ដូរ (Shift) ឬ​ជំនួស (Control)) បាន​ផ្លាស់ប្ដូរ​សភាព​របស់​វា ឥឡូវ​នេះ​សកម្ម +Comment[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿ (ಉ.ದಾ Shift ಅಥವಾ Ctrl) ನ ಸ್ಥಿತಿಯು ಬದಲಾಗಿದ್ದು ಈಗ ಸಕ್ರಿಯಗೊಂಡಿದೆ +Comment[ko]=Shift나 Control 키 같은 수정자 키의 상태가 바뀌었고 현재 사용 가능함 +Comment[ku]=Bişkojkeke Guherker (mînak Shift an jî Ctrl) ciyê xwe guherand û niha çalak e +Comment[lt]=Klavišo – modifikatoriaus (pvz., Lyg2(Shift) arba Vald(Ctrl)) būsena pakito ir jis dabar – aktyvus +Comment[lv]=Modifikatora taustiņš (piem. Shift vai Control) ir mainījis stāvokli un tagad ir aktīvs +Comment[mk]=Некое копче за модификација (пр. Shift или Ctrl) си ја смени состојбата и сега е активно +Comment[ml]=ഒരു മോഡിഫയര്‍ കീ (ഉദാ. ഷിഫ്ട് അല്ലെങ്കില്‍ കണ്ട്രോള്‍) അവസ്ഥ മാറി സജീവമായിരിക്കുന്നു +Comment[mr]=परिवर्तक कि (उ.दा. Shift किंवा Ctrl) याने स्तर बदलविले आहे व आता सक्रिय आहे +Comment[nb]=En valgtast (f.eks. Shift eller Ctrl) har endret status og er nå slått på +Comment[nds]=En Sünnertast (Ümschalt oder Stüern (Strg) a.B.) hett sien Tostand ännert un is nu aktiev +Comment[nl]=Een modificatietoets (bijv. Shift of Ctrl) is nu actief +Comment[nn]=Ein valtast (som «Shift» eller «Ctrl») har endra status, og er no aktiv +Comment[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି (ଯେପରିକି Shift କିମ୍ବା Ctrl) ସେମାନଙ୍କର ସ୍ଥିତି ପରିବର୍ତ୍ତନ କରିଅଛି ଏବଂ ବର୍ତ୍ତମାନ ସକ୍ରିୟ ଅଛି +Comment[pl]=Klawisz modyfikujący (np. Shift lub Ctrl) zmienił stan i jest teraz włączony +Comment[pt]=Uma tecla modificadora (p.ex., o Shift ou o Control) mudou o seu estado e ficou agora activa +Comment[pt_BR]=Uma tecla modificadora (p.ex. Shift ou Ctrl) teve seu estado alterado e agora está ativa +Comment[ro]=Un modificator de taste (cum ar fi Shift sau Ctrl) și-a schimbat starea și este acum activ +Comment[ru]=Клавиша-модификатор (например, Shift или Ctrl) изменила состояние и сейчас активна +Comment[si]=වෙනස් කරීමේ යතුරේ (උදා. Shift හෝ Ctrl) තත්වය වෙනස් වී ඇති අතර එය දැන් සක්‍රීයයි +Comment[sk]=Modifikačný kláves (napr. Shift alebo Ctrl) zmenil svoj stav a je teraz aktívny. +Comment[sl]=Spremenilna tipka (npr. Shift ali Ctrl) je spremenila stanje in je sedaj dejavna +Comment[sr]=Модификаторски тастер (нпр. Shift или Ctrl) променио је стање и сада је активан +Comment[sr@ijekavian]=Модификаторски тастер (нпр. Shift или Ctrl) промијенио је стање и сада је активан +Comment[sr@ijekavianlatin]=Modifikatorski taster (npr. Shift ili Ctrl) promijenio je stanje i sada je aktivan +Comment[sr@latin]=Modifikatorski taster (npr. Shift ili Ctrl) promenio je stanje i sada je aktivan +Comment[sv]=En väljartangent (t.ex. Skift eller Ctrl) har ändrat tillstånd och är nu aktiv +Comment[ta]=A modifier key (e.g. Shift or Ctrl) has changed its state and is now active +Comment[te]=సవరింపు కీ (ఉ.దా. Shift లేదా Ctrl) దానియొక్క స్థితి మార్చుకుంది మరియు ఇప్పుడు క్రియాశీలంగా ఉంది +Comment[tg]=Клавиша модификатора (например, Shift или Ctrl) изменила состояние и сейчас активна +Comment[th]=ปุ่มพิมพ์ประกอบ (เช่น Shift หรือ Ctrl) มีการเปลี่ยนสถานะของตัวมัน และตอนนี้กำลังทำงานอยู่ +Comment[tr]=Bir değiştirici tuşun (Shift veya Ctrl gibi) durumu değiştirildi ve etkinleştirildi +Comment[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا (مەسىلەن، Shift ياكى Ctrl) ئۇنىڭ ھالىتىنى ئۆزگەرتىپ ھازىر ئاكتىپلاشتۇرۇلدى +Comment[uk]=Клавіша модифікатора (наприклад Shift або Ctrl) змінила свій стан і тепер активна +Comment[wa]=Ene modifieuse tape (metans MAJ oudonbén CTRL) a candjî si estat eyet est asteure active +Comment[x-test]=xxA modifier key (e.g. Shift or Ctrl) has changed its state and is now activexx +Comment[zh_CN]=修饰键(如 Shift 或 Ctrl)更改了其状态,现已激活 +Comment[zh_TW]=一個組合鍵(如 Shift 或 Ctrl 等)已改變了它的狀態成為啟動 +Sound=KDE-Sys-Special.ogg + +nopresentation=236 + +[Event/modifierkey-unlatched] +Name=A modifier key has become inactive +Name[af]='n Verandering sleutel was gedeaktiveer +Name[ar]=تم إلغاء مفتاح مغيِّر +Name[ast]=Desactivóse una tecla modificadora +Name[be@latin]=Klavišny madyfikatar adcisnuty +Name[bg]=Изключен е клавиш-модификатор +Name[bn]=একটি মডিফায়ার কী নিষ্ক্রীয় হয়েছে +Name[bs]=Modifikatorski taster je deaktiviran +Name[ca]=Alguna tecla modificadora ha esdevingut inactiva +Name[ca@valencia]=Alguna tecla modificadora ha esdevingut inactiva +Name[cs]=Modifikátor klávesnice je neaktivní +Name[csb]=Klawisza zjiaczi òsta deaktiwòwónô +Name[da]=En ændringstast er blevet deaktiveret +Name[de]=Eine Modifikator-Taste ist deaktiviert worden +Name[el]=Ένα πλήκτρο τροποποιητή έγινε ανενεργό +Name[en_GB]=A modifier key has become inactive +Name[eo]=Modifigita klavo malaktiviĝis +Name[es]=Se ha desactivado una tecla modificadora +Name[et]=Muuteklahv muutus mitteaktiivseks +Name[eu]=Tekla aldatzaile bat inaktibatu da +Name[fi]=Muunnosnäppäin ei ole enää aktiivinen +Name[fr]=Une touche de modification est devenue inactive +Name[fy]=In modifikaasjetoets wurdt ynaktief +Name[ga]=Tá eochair mhionathraithe neamhghníomhach anois +Name[gl]=Desactivouse unha tecla modificadora +Name[gu]=બદલવાની કળ નિષ્ક્રિય બની છે +Name[he]=מקש משנה מצב הפך ללא פעיל +Name[hi]=कोई मॉडिफ़ायर कुंजी अक्रिय हो गया है +Name[hne]=कोई माडिफायर कुंजी हर अक्रिय हो गे हे +Name[hr]=Tipka modifikatora je deaktivirana +Name[hsb]=Modifikowaca tasta je so stała njeaktiwna +Name[hu]=Egy módosító billentyű inaktívvá vált +Name[ia]=Un clave modificator ha devenite inactive +Name[id]=Sebuah tombol pengubah telah menjadi tidak aktif +Name[is]=Breytilykill er nú óvirkur +Name[it]=Un tasto modificatore è stato disattivato +Name[ja]=修飾キーが非アクティブになりました +Name[kk]=Түрлендіргіш перне белсенсіздірілді +Name[km]=គ្រាប់​ចុច​កែប្រែ​បាន​ក្លាយ​ជា​អសកម្ម +Name[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ +Name[ko]=수정자 키가 비활성화됨 +Name[ku]=Bişkojkeke Guherker hat neçalakirin +Name[lt]=Klavišas – modifikatorius tapo neaktyvus +Name[lv]=Modifikatora taustiņš tika deaktivizēts +Name[mk]=Некое копче за модификација стана неактивно +Name[ml]=ഒരു മോഡിഫയര്‍ കീ നിര്‍ജീവമായിരിക്കുന്നു +Name[mr]=परिवर्तक कि निष्क्रिय झाली आहे +Name[nb]=En valgtast er slått av +Name[nds]=En Sünnertast is nich mehr aktiev +Name[ne]=परिमार्जक कुञ्जी निष्क्रिय भएको छ +Name[nl]=Een modificatietoets is inactief geworden +Name[nn]=Ein valtast er no inaktiv +Name[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି ନିଷ୍କ୍ରିୟ ହୋଇଯାଇଛି +Name[pa]=ਮੋਡੀਫਾਇਰ ਸਵਿੱਚ ਇਨ-ਐਕਟਿਵ ਕੀਤੀ ਗਈ +Name[pl]=Klawisz modyfikujący został wyłączony +Name[pt]=Ficou inactiva uma tecla modificadora +Name[pt_BR]=Uma tecla modificadora se tornou inativa +Name[ro]=Un modificator de taste a devenit inactiv +Name[ru]=Клавиша модификатора отпущена +Name[se]=Válljenboallu ii leat šat aktiiva +Name[si]=වෙනස්කිරීම් යතුර අක්‍රීයයි +Name[sk]=Modifikačný kláves je neaktívny +Name[sl]=Spremenilna tipka se je onemogočila +Name[sr]=Модификаторски тастер је деактивиран +Name[sr@ijekavian]=Модификаторски тастер је деактивиран +Name[sr@ijekavianlatin]=Modifikatorski taster je deaktiviran +Name[sr@latin]=Modifikatorski taster je deaktiviran +Name[sv]=En väljartangent har inaktiverats +Name[ta]=A modifier key has become inactive +Name[te]=సవరింపు కీ క్రియాహీనం కాబోతోంది +Name[tg]=Клавиша модификатора не активна +Name[th]=ปุ่มพิมพ์ประกอบถูกปิดการทำงาน +Name[tr]=Bir değiştirici tuş pasifleştirildi +Name[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا پاسسىپلاشتۇرۇلدى +Name[uk]=Клавіша модифікатора стала неактивною +Name[wa]=Ene modifieuse tape a divnou nén active +Name[x-test]=xxA modifier key has become inactivexx +Name[zh_CN]=修饰键现已停用 +Name[zh_TW]=組合鍵已放開 +Comment=A modifier key (e.g. Shift or Ctrl) has changed its state and is now inactive +Comment[af]='n Veranderingsleutel (bv. Shift of Contorl) se toestand het verander en is nou onaktief +Comment[ar]=مفتاح مغيِّر (شفت او كنترول) غيّر حالته وأصبح ملغى +Comment[ast]=Una tecla modificadora (Shift o Ctrl) camudó l'estáu y nun ta activa +Comment[be@latin]=Klavišny madyfikatar (naprykład, „Shift” ci „Ctrl”) źmianiŭ svajo stanovišča j ciapier adcisnuty. +Comment[bg]=Клавиш-модификатор (напр. Shift или Ctrl) промени състоянието си и е изключен +Comment[bn]=একটি মডিফায়ার কী (e.g. Shift বা Ctrl) অবস্থা পরিবর্তন করে এখন নিষ্ক্রীয় হয়েছে +Comment[bs]=Modifikatorski taster (npr. Shift ili Ctrl) je promijenio stanje i nije više aktivan +Comment[ca]=Ha canviat l'estat d'una tecla modificadora (p.ex. Majúscules o Control) i ara està inactiva +Comment[ca@valencia]=Ha canviat l'estat d'una tecla modificadora (p.ex. Majúscules o Control) i ara està inactiva +Comment[cs]=Modifikátor klávesnice (Shift nebo Ctrl) změnil stav a je právě neaktivní +Comment[csb]=Klawisza zjinaczi (Shift abò Control) zmienia swój sztatus ë nie je ju aktiwnô +Comment[da]=En ændringstast (f.eks. Skift eller Ctrl) har ændret sin tilstand og er nu inaktiv +Comment[de]=Eine Modifikator-Taste (Umschalt oder Strg) hat ihren Status verändert und ist nun inaktiv +Comment[el]=Ένα πλήκτρο τροποποιητή (π.χ., Shift ή Ctrl) άλλαξε την κατάστασή του και είναι τώρα ανενεργό +Comment[en_GB]=A modifier key (e.g. Shift or Ctrl) has changed its state and is now inactive +Comment[eo]=Modifa klavo (ekz. majuskliga klavo aŭ stirklavo) ŝanĝis sian staton kaj nun estas malaktiva +Comment[es]=Una tecla modificadora (Mayus o Ctrl) ha cambiado su estado y no está activa +Comment[et]=Muuteklahv (nt. Shift või Ctrl) muutis oma olekut ning on nüüd mitteaktiivne +Comment[eu]=Tekla aldatzaile bat (adibidez, Maius edo Ktrl) egoeraz aldatu da, eta orain inaktibo dago +Comment[fi]=Muunnosnäppäin (esim. Shift tai Ctrl) on vaihtanut tilaa eikä ole enää aktiivinen +Comment[fr]=Une touche de modification (ex : « Maj. » ou « Ctrl. ») a changé d'état et est maintenant inactive +Comment[fy]=De tastân fan in modifikaasjetoets (lykas Shift of Control) is feroare en is no ynaktyf +Comment[ga]=Athraíodh staid eochrach mionathraithe (m.sh. Shift nó Ctrl) agus tá sí neamhghníomhach anois +Comment[gl]=Unha tecla modificadora (por ex. Maiús ou Ctrl) cambiou de estado e agora está inactiva +Comment[gu]=બદલવાની કળે (દા.ત., શીફ્ટ અથવા કંટ્રોલ) હવે તેની સ્થિતિ બદલી છે અને હવે નિષ્ક્રિય છે +Comment[he]=מקש משנה מצב (למשל Shift או Ctrl) שינה את מצבו וכרגע לא פעיל +Comment[hne]=कोई माडिफायर कुंजी (जइसन कि शिफ्ट या कंट्रोल) हर अपन स्थिति ल बदल दे हे अउ अब वो हर अक्रिय हो गे हे +Comment[hr]=Tipka modifikatora (npr. SHIFT ili CTRL) promijenila je svoje stanje i više nije aktivna +Comment[hsb]=Modifikowaca tasta (na př. Wulkopis abo Strg) je swój status změniła a je nětko njeaktiwna +Comment[hu]=Egy módosító billentyű (pl. a Shift vagy a Ctrl) inaktívvá vált +Comment[ia]=Un clave modificator (p.ex.Shift o Ctrl) ha cambiate su stato e ora es inactive +Comment[id]=Sebuah tombol pengubah (misalnya Shift atau Ctrl) tekah diubah keadaannya dan sekarang tidak aktif +Comment[is]=Breytilykill (t.d. Shift eða Ctrl) hefur breytt um stöðu og er nú óvirkur +Comment[it]=Un tasto modificatore (come Shift o Ctrl) ha cambiato stato ed è ora inattivo +Comment[ja]=修飾キー (Shift や Ctrl) の状態が変更され、非アクティブになりました +Comment[kk]=Түрлендіргіш перне (мыс. Shift не Ctrl) күйін ауыстырып енді белсенді емес +Comment[km]=គ្រាប់​ចុច​កែប្រែ (ឧ. ប្ដូរ (Shift) ឬ បញ្ជា (Control)) បាន​ផ្លាស់ប្ដូរ​សភាព​របស់​វា ហើយ​ឥឡូវ​នេះ​អសកម្ម +Comment[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿ (ಉ.ದಾ Shift ಅಥವಾ Ctrl) ನ ಸ್ಥಿತಿಯು ಬದಲಾಗಿದ್ದು ಈಗ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ +Comment[ko]=Shift나 Control 키 같은 수정자 키의 상태가 바뀌었고 현재 사용 불가능함 +Comment[ku]=Bişkojkeke Guherker (mînak Shift an jî Ctrl) ciyê xwe guherand û niha neçalak e +Comment[lt]=Klavišo – modifikatoriaus (pvz., Lyg2(Shift) arba Vald(Ctrl)) būsena pakito ir jis dabar – neaktyvus +Comment[lv]=Modifikatora taustiņš (piem. Shift vai Control) ir mainījis stāvokli un tagad ir neaktīvs +Comment[mk]=Некое копче за модификација (пр. Shift или Ctrl) си ја смени состојбата и сега е неактивно +Comment[ml]=ഒരു മോഡിഫയര്‍ കീ (ഉദാ. ഷിഫ്ട് അല്ലെങ്കില്‍ കണ്ട്രോള്‍) അവസ്ഥ മാറി നിര്‍ജീവമായിരിക്കുന്നു +Comment[mr]=परिवर्तक कि (उ.दा. Shift किंवा Ctrl) याने स्तर बदलविले आहे व आता निष्क्रिय आहे +Comment[nb]=En valgtast (f.eks. Shift eller Ctrl) har endret status og er nå slått av +Comment[nds]=En Sünnertast (Ümschalt oder Stüern (Strg) a.B.) hett sien Tostand ännert un is nu nich mehr aktiev +Comment[nl]=Een modificatietoets (bijv. Shift of Ctrl) is nu inactief +Comment[nn]=Ein valtast (som «Shift» eller «Ctrl») har endra status, og er no inaktiv +Comment[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି (ଯେପରିକି Shift କିମ୍ବା Ctrl) ସେମାନଙ୍କର ସ୍ଥିତି ପରିବର୍ତ୍ତନ କରିଛନ୍ତି ଏବଂ ବର୍ତ୍ତମାନ ନିଷ୍କ୍ରିୟ ହୋଇଯାଇଛନ୍ତି +Comment[pl]=Klawisz modyfikujący (np. Shift lub Ctrl) zmienił stan i jest teraz wyłączony +Comment[pt]=Uma tecla modificadora (p.ex., o Shift ou o Control) mudou o seu estado e ficou agora inactiva +Comment[pt_BR]=Uma tecla modificadora (p.ex. Shift ou Ctrl) teve seu estado alterado e agora está inativa +Comment[ro]=Un modificator de taste (cum ar fi Shift sau Ctrl) și-a schimbat starea și este acum inactiv +Comment[ru]=Клавиша-модификатор (например, Shift или Ctrl) изменила своё состояние и сейчас неактивна +Comment[si]=වෙනස් කරීමේ යතුරේ (උදා. Shift හෝ Ctrl) තත්වය වෙනස් වී ඇති අතර එය දැන් අක්‍රීයයි +Comment[sk]=Modifikačný kláves (napr. Shift alebo Ctrl) zmenil svoj stav a je teraz neaktívny. +Comment[sl]=Spremenilna tipka (npr. Shift ali Ctrl) je spremenila stanje in je sedaj nedejavna +Comment[sr]=Модификаторски тастер (нпр. Shift или Ctrl) је променио стање и није више активан +Comment[sr@ijekavian]=Модификаторски тастер (нпр. Shift или Ctrl) је промијенио стање и није више активан +Comment[sr@ijekavianlatin]=Modifikatorski taster (npr. Shift ili Ctrl) je promijenio stanje i nije više aktivan +Comment[sr@latin]=Modifikatorski taster (npr. Shift ili Ctrl) je promenio stanje i nije više aktivan +Comment[sv]=En väljartangent (t.ex. Skift eller Ctrl) har ändrat tillstånd och är nu inaktiv +Comment[ta]=A modifier key (e.g. Shift or Ctrl) has changed its state and is now inactive +Comment[te]=సవరింపు కీ (ఉ.దా. Shift లేదా Ctrl) దాని స్థితి మార్చుకుంది మరియు ఇప్పుడు క్రియాహీనంగా ఉంది +Comment[tg]=Клавиша модификатора (например, Shift или Ctrl) изменила своё состояние и сейчас не активна +Comment[th]=ปุ่มพิมพ์ประกอบ (เช่น Shift หรือ Ctrl) มีการเปลี่ยนสถานะของตัวมัน และตอนนี้ได้ปิดการทำงาน +Comment[tr]=Bir değiştirici tuşun (Shift veya Ctrl gibi) durumu değiştirildi ve pasifleştirildi +Comment[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا (مەسىلەن، Shift ياكى Ctrl) ئۇنىڭ ھالىتىنى ئۆزگەرتىپ ھازىر پاسسىپلاشتۇرۇلدى +Comment[uk]=Клавіша модифікатора (наприклад Shift або Ctrl) змінила свій стан і тепер неактивна +Comment[wa]=Ene modifieuse tape (metans MAJ oudonbén CTRL) a candjî si estat eyet n' est asteure pus active +Comment[x-test]=xxA modifier key (e.g. Shift or Ctrl) has changed its state and is now inactivexx +Comment[zh_CN]=修饰键(如 Shift 或 Ctrl)更改了其状态,现已停用 +Comment[zh_TW]=一個組合鍵(如 Shift 或 Ctrl 等)已改變了它的狀態成為放開 +Sound=KDE-Sys-Special.ogg + +nopresentation=236 + +[Event/modifierkey-locked] +Name=A modifier key has been locked +Name[af]='n Verandering sleutel was gesluit +Name[ar]=تم قفل مفتاح مغيِّر +Name[ast]=Bloquióse una tecla modificadora +Name[be@latin]=Klavišny madyfikatar zamacavany +Name[bg]=Клавиш-модификатор е заключен +Name[bn]=একটি মডিফায়ার কী লক করা হয়েছে +Name[bs]=Modifikatorski taster je zaključan +Name[ca]=S'ha fixat alguna tecla modificadora +Name[ca@valencia]=S'ha fixat alguna tecla modificadora +Name[cs]=Modifikátor klávesnice je zamčený +Name[csb]=Klawisza zjinaczi òsta zablokòwónô +Name[da]=En ændringstast er blevet låst +Name[de]=Eine Modifikator-Taste ist gesperrt worden +Name[el]=Ένα πλήκτρο τροποποιητή κλειδώθηκε +Name[en_GB]=A modifier key has been locked +Name[eo]=Modifigita klavo ŝlosiĝis +Name[es]=Se ha bloqueado una tecla modificadora +Name[et]=Muuteklahv on lukustatud +Name[eu]=Tekla aldatzaile bat blokeatu da +Name[fi]=Muunnosnäppäin on lukittu +Name[fr]=Une touche de modification a été verrouillée +Name[fy]=In modifikaasjetoets is beskoattele +Name[ga]=Tá eochair mhionathraithe faoi ghlas anois +Name[gl]=Trancouse unha tecla modificadora +Name[gu]=બદલવાની કળને તાળું મારવામાં આવ્યું છે +Name[he]=מקש משנה מצב ננעל +Name[hi]=कोई मॉडिफ़ायर कुंजी तालाबंद हो गया है +Name[hne]=कोई माडिफायर कुंजी हर तालाबंद हो गे हे +Name[hr]=Tipka modifikatora je zaključana +Name[hsb]=Modifikowaca tasta bu stajnje zaswěćena +Name[hu]=Egy módosító billentyű zárolódott +Name[ia]=Un clave modificator ha essite blocate +Name[id]=Sebuah tombol pengubah telah dikunci +Name[is]=Breytilykli hefur verið læst +Name[it]=Un tasto modificatore è stato bloccato +Name[ja]=修飾キーがロックされました +Name[kk]=Түрлендіргіш перне басылды +Name[km]=គ្រាប់​ចុច​កែប្រែ​បាន​ត្រូវ​ចាក់​សោ +Name[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿಯನ್ನು ಬಂಧಿಸಲಾಗಿದೆ (ಲಾಕ್) +Name[ko]=수정자 키가 잠김 +Name[ku]=Bişkojkeke Guherker hat kilîtkirin +Name[lt]=Klavišas – modifikatorius buvo užrakintas +Name[lv]=Modifikatora taustiņš tika fiskēts +Name[mk]=Некое копче за модификација е заклучено +Name[ml]=ഒരു മോഡിഫയര്‍ കീ പൂട്ടിയിരിക്കുന്നു +Name[mr]=परिवर्तक कि कुलूपबंद केली गेली आहे +Name[nb]=En valgtast er blitt låst +Name[nds]=En Sünnertast wöör fastsett +Name[ne]=परिमार्जक कुञ्जी ताल्चा लगाइएको छ +Name[nl]=Een modificatietoets is vergrendeld +Name[nn]=Ein valtast er no låst +Name[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି ଅପରିବର୍ତ୍ତିତ ହୋଇଯାଇଛି +Name[pa]=ਮੋਡੀਫਾਇਰ ਸਵਿੱਚ ਲਾਕ ਕੀਤੀ ਗਈ +Name[pl]=Klawisz modyfikujący został zablokowany +Name[pt]=Uma tecla modificadora ficou bloqueada +Name[pt_BR]=Uma tecla modificadora foi bloqueada +Name[ro]=Un modificator de taste a fost blocat +Name[ru]=Клавиша-модификатор зафиксирована +Name[se]=Válljenboallu lea dál lohkkaduvvon +Name[si]=වෙනස්කිරීම් යතුර අගුළු දමා ඇත +Name[sk]=Modifikačný kláves je zamknutý +Name[sl]=Spremenilna tipka se je zaklenila +Name[sr]=Модификаторски тастер је закључан +Name[sr@ijekavian]=Модификаторски тастер је закључан +Name[sr@ijekavianlatin]=Modifikatorski taster je zaključan +Name[sr@latin]=Modifikatorski taster je zaključan +Name[sv]=En väljartangent har låsts +Name[ta]=A modifier key has been locked +Name[te]=సవరింపు కీ అప్రవేశంగా ఉంది +Name[tg]=Клавиша модификатора зафиксирована +Name[th]=ปุ่มพิมพ์ประกอบถูกล็อคอยู่ +Name[tr]=Bir değiştirici tuş kilitlendi +Name[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا قۇلۇپلاندى +Name[uk]=Клавішу модифікатора було заблоковано +Name[wa]=Ene modifieuse tape a stî eclawêye +Name[x-test]=xxA modifier key has been lockedxx +Name[zh_CN]=修饰键现已锁定 +Name[zh_TW]=組合鍵已鎖定 +Comment=A modifier key (e.g. Shift or Ctrl) has been locked and is now active for all of the following keypresses +Comment[af]='n Veranderingsleutel (bv. Shift of Control) is gesluit en is nou aktief vir al die volgende sleuteldrukke +Comment[ar]=تم قفل مفتاح مغيِّر (شفت أو كنترول) وأصبح مفعّلاً لكل الكتابات التالية +Comment[ast]=Bloquióse una tecla modificadora (Mayús o Ctrl) y afectará a toles tecles calcaes +Comment[be@latin]=Klavišny madyfikatar (naprykład, „Shift” ci „Ctrl”) zamacavaŭsia j ciapier prycisnuty dla ŭsich nastupnych klavišaŭ. +Comment[bg]=Клавиш-модификатор (напр. Shift или Ctrl) е заключен и е активен за всички последващи натискания на клавиши +Comment[bn]=একটি মডিফায়ার কী (e.g. Shift বা Ctrl) লক করা হয়েছে এবং পরবর্তী সবকটি কী-র (key) জন্য সক্রিয় থাকবে +Comment[bs]=Modifikatorski taster (npr. Shift ili Ctrl) upravo je zaključan i od sada aktivan za sve pritiske na tastere +Comment[ca]=S'ha fixat alguna tecla modificadora (p.ex. Majúscules o Control) i ara està activa per a totes les tecles que es premin a continuació +Comment[ca@valencia]=S'ha fixat alguna tecla modificadora (p.ex. Majúscules o Control) i ara està activa per a totes les tecles que es premen a continuació +Comment[cs]=Modifikátor klávesnice (např. Shift nebo Ctrl) je zamčený a je nyní aktivní pro všechny následující stisknuté klávesy +Comment[csb]=Klawisza zjinaczi (Shift abò Control) òsta zablokòwónô ë je terô dlô pòsobnegò wcësniącô klawiszów aktiwnô +Comment[da]=En ændringstast (f.eks. Skift eller Ctrl) er blevet låst og er nu aktiv for alle følgende tastetryk +Comment[de]=Eine Modifikator-Taste (Umschalt oder Strg) ist festgesetzt worden und ist nun für alle folgenden Tastendrücke aktiv +Comment[el]=Ένα πλήκτρο τροποποιητή (π.χ., Shift ή Ctrl) κλειδώθηκε και τώρα είναι ενεργό για όλα τα ακόλουθα πατήματα πλήκτρων +Comment[en_GB]=A modifier key (e.g. Shift or Ctrl) has been locked and is now active for all of the following keypresses +Comment[eo]=Modifa klavo (ekz. majuskliga klavo aŭ stirklavo) ŝlosiĝis kaj nun estas aktiva por la sekvaj klavpremoj +Comment[es]=Se ha bloqueado una tecla modificadora (Mayús o Ctrl) y afectará a todas las teclas que se pulsen +Comment[et]=Muuteklahv (nt. Shift või Ctrl) on lukustatud ja on nüüd aktiivne kõikide järgnevate klahvivajutuste jaoks +Comment[eu]=Tekla aldatzaile bat (adibidez, Maius edo Ktrl) blokeatu da, eta orain aktibo dago sakatzen diren tekla guztietarako +Comment[fi]=Muunnosnäppäin (esim. Shift tai Ctrl) on lukittu ja on nyt aktiivinen kaikille seuraaville näppäinpainalluksille +Comment[fr]=Une touche de modification (ex : « Maj. » ou « Ctrl. ») a été verrouillée et est maintenant active pour tous les appuis suivants de touches +Comment[fy]=In modifikaasjetoets (lykas Shift of Control) is beskoattele en is no aktyf foar de neikommende toetsoanslaggen +Comment[ga]=Cuireadh eochair mhionathraithe (m.sh., Shift nó Ctrl) faoi ghlas tá sí gníomhach anois le haghaidh na n-eochairbhrúnna seo a leanas +Comment[gl]=Unha tecla modificadora (por ex. Maiús ou Ctrl) foi trancada e agora está activa +Comment[gu]=બદલવાની કળને (દા.ત., શીફ્ટ અથવા કંટ્રોલ) હવે તાળું મારવામાં આવ્યું છે અને હવે તે નીચેની કળ દબાવવા માટે સક્રિય છે +Comment[he]=מקש משנה מצב (למשל Shift או Ctrl) ננעל וכרגע פעיל עבור לחיצות המקשים הבאות +Comment[hne]=कोई माडिफायर कुंजी (जइसन कि शिफ्ट या कंट्रोल) हर तालाबंद हो गे हे अउ अब वो हर नीचे के सब्बो कुंजीदबाव मं सक्रिय रहिही +Comment[hr]=Tipka modifikatora (npr. SHIFT ili CTRL) zaključana je i aktivna je tijekom svih sljedećih pritisaka tipki +Comment[hsb]=Modifikowaca tasta (na př. Wulkopis abo Strg) bu stajnje zaswěćena a je nětko za wšě přichodne tasty aktiwna +Comment[hu]=Egy módosító billentyű (pl. a Shift vagy a Ctrl) zárolódott, és ezután minden billentyűlenyomásnál aktív lesz +Comment[ia]=Un clave modificator (p.ex.Shift o CTRL) ha essite blocate e ora es active pro tote le sequente keypresses +Comment[id]=Sebuah tombol pengubah (misalnya Shift atau Ctrl) telah dikunci dan sekarang aktif untuk semua penekanan tombol berikut +Comment[is]=Breytilykli (t.d. Shift eða Ctrl) hefur verið læst og er nú virkur fyrir eftirfarandi lyklaborðsaðgerðir +Comment[it]=Un tasto modificatore (come Shift o Ctrl) è stato bloccato ed è ora attivo per tutte le battute successive +Comment[ja]=修飾キー (Shift や Ctrl) がロックされ、続くキー押下のすべてに対してアクティブになりました +Comment[kk]=Түрлендіргіш перне (мыс. Shift не Ctrl) басылып енді барлық басылмақ пернелер үшін белсенді +Comment[km]=គ្រាប់​ចុច​កែប្រែ (ឧ. ប្ដូរ (Shift) ឬ​បញ្ជា (Control)) ត្រូវ​បាន​ចាក់​សោ ហើយ​ឥឡូវ​នេះ​សកម្ម​សម្រាប់​ការ​ចុច​គ្រាប់​ចុច​ខាង​ក្រោម +Comment[kn]=ಒಂದು ಪರಿವರ್ತಕ (ಮಾಡಿಫಯರ್) ಕೀಲಿಯನ್ನು (ಉ.ದಾ Shift ಅಥವಾ Ctrl) ಬಂಧಿಸಲಾಗಿದ್ದು (ಲಾಕ್), ಮುಂದಿನ ಎಲ್ಲಾ ಕೀಲಿಮಣೆ ಒತ್ತುಗಳಿಗೆ ಈಗ ಸಕ್ರಿಯವಾಗಿದೆ +Comment[ko]=Shift나 Control 키 같은 수정자 키의 상태가 바뀌었고 현재 모든 키 입력에 대해서 활성화됨 +Comment[ku]=Bişkojka guhêrker (wekî Shift an jî Ctrl) hate qufl kirin û niha ji bo çalak kirina hemû bişkojkên jêr çalak e +Comment[lt]=Klavišas – modifikatorius (pvz., Lyg2(Shift) arba Vald(Ctrl)) buvo užrakintas ir dabar visiems būsimiems klavišų paspaudimams yra aktyvus +Comment[lv]=Modifikatora taustiņš (piem. Shift vai Control) tika fiksēts un ir aktīvs visiem nākamajiem taustiņu nospiedieniem +Comment[mk]=Некое копче за модификација (пр. Shift или Ctrl) беше заклучено и сега е активно за сите наредни притиснати копчиња +Comment[ml]=ഒരു മോഡിഫയര്‍ കീ (ഉദാ. ഷിഫ്ട് അല്ലെങ്കില്‍ കണ്ട്രോള്‍) പൂട്ടിയിരിക്കുന്നു. നിലവില്‍ താഴെ പറയുന്ന കീപ്രെസ്സുകള്‍ക്കു് ഇതു് സജീവമാണു് +Comment[mr]=परिवर्तक कि (उ.दा. Shift किंवा Ctrl) कुलूपबंद झाली आहे व खालील किप्रेस् करिता सक्रिय झाली आहे +Comment[nb]=En valgtast (f.eks. Shift eller Ctrl) har blitt låst og er nå skrudd på for alle etterfølgende tastetrykk +Comment[nds]=En Sünnertast (Ümschalt oder Stüern (Strg) a.B.) wöör fastsett un is nu för all nakamen Tasten aktiev +Comment[nl]=Een modificatietoets (bijv. Shift of Ctrl) is vergrendeld en nu actief voor alle volgende toetsaanslagen +Comment[nn]=Ein valtast (som «Shift» eller «Ctrl») er vorten låst, og er no aktiv for alle etterfølgjande tastetrykk +Comment[or]=ଗୋଟିଏ ପରିବର୍ତ୍ତକ କି (ଯେପରିକି Shift କିମ୍ବା Ctrl) ଅପରିବର୍ତ୍ତିତ ହୋଇଯାଇଛି ଏବଂ ବର୍ତ୍ତମାନ ନିମ୍ନଲିଖିତ ସମସ୍ତ କି ଚାପ ପାଇଁ ସକ୍ରିୟ ହୋଇଛି +Comment[pl]=Klawisz modyfikujący (np. Shift lub Ctrl) został zablokowany i będzie włączony przy następnych naciśnięciach klawiszy +Comment[pt]=Uma tecla modificadora (p.ex., o Shift ou o Control) foi bloqueada e ficou agora activa para todas as combinações de teclas seguintes +Comment[pt_BR]=Uma tecla modificadora (p.ex. Shift ou Ctrl) foi bloqueada e agora está ativa, para todos os pressionamentos de tecla seguintes +Comment[ro]=Un modificator de taste (cum ar fi Shift sau Ctrl) a fost blocat și este acum activ pentru următoarele apăsări de taste +Comment[ru]=Клавиша-модификатор (например, Shift или Ctrl) зафиксирована и активна при нажатии любых других клавиш +Comment[si]=වෙනස් කිරීමේ යතුර (උදා. Shift හෝ Ctrl) අගුළු දමා ඇති අතර පහත සියළුම යතුරු එබීම් සඳහා එය සක්‍රීයයි +Comment[sk]=Modifikačný kláves (napr. Shift alebo Ctrl) je zamknutý a je teraz aktívny pre všetky nasledujúce stlačenia kláves +Comment[sl]=Spremenilna tipka (npr. Shift ali Ctrl) se je zaklenila in je sedaj dejavna za vse prihodnje pritiske tipk +Comment[sr]=Модификаторски тастер (нпр. Shift или Ctrl) управо је закључан и од сада активан за све притиске на тастере +Comment[sr@ijekavian]=Модификаторски тастер (нпр. Shift или Ctrl) управо је закључан и од сада активан за све притиске на тастере +Comment[sr@ijekavianlatin]=Modifikatorski taster (npr. Shift ili Ctrl) upravo je zaključan i od sada aktivan za sve pritiske na tastere +Comment[sr@latin]=Modifikatorski taster (npr. Shift ili Ctrl) upravo je zaključan i od sada aktivan za sve pritiske na tastere +Comment[sv]=En väljartangent (t.ex. Skift eller Ctrl) har låsts och är nu aktiv för alla följande tangentnertryckningar +Comment[ta]=A modifier key (e.g. Shift or Ctrl) has been locked and is now active for all of the following keypresses +Comment[te]=సవరింపు కీ (ఉ.దా. Shift లేదా Ctrl) అప్రవేశం చేయబడింది మరియు ఇప్పుడు క్రింది అన్ని కీవత్తులకు క్రియాశీలంగా ఉంది +Comment[tg]=Клавиша модификатора (например, Shift или Ctrl) зафиксирована и активна при нажатии любых других клавиш +Comment[th]=ปุ่มพิมพ์ประกอบ (เช่น Shift หรือ Cntrl) ถูกล็อคอยู่ และขณะนี้อยู่ในสถานะทำงาน สำหรับใช้ร่วมกับการกดแป้นต่อจากนี้ +Comment[tr]=Bir değiştirici tuş (Shift ya da Ctrl gibi) kilitlendi ve bundan sonraki tüm tuş basma eylemleri için etkinleştirildi +Comment[ug]=بىر ئۆزگەرتكۈچى كۇنۇپكا (مەسىلەن، Shift ياكى Ctrl) قۇلۇپلاندى، بۇندىن كېيىنكى كۇنۇپكا بېسىشقا ئىشلىتىلىدۇ +Comment[uk]=Клавішу модифікатора (наприклад Shift або Ctrl) було зафіксовано і тепер вона активна для всіх наступних натискань клавіш +Comment[wa]=Ene modifieuse tape (metans MAJ oudonbén CTRL) a stî eclawêye eyet est asteure active po tos les tapes tchôkeyes ki shuront +Comment[x-test]=xxA modifier key (e.g. Shift or Ctrl) has been locked and is now active for all of the following keypressesxx +Comment[zh_CN]=修饰键(如 Shift 或 Ctrl)已被锁定,现在将适用于后续按键 +Comment[zh_TW]=一個組合鍵(如 Shift 或 Ctrl 等)已被鎖定,現在再按任何鍵都視為快捷鍵組合 +Sound=KDE-Sys-Special.ogg + +nopresentation=236 + +[Event/lockkey-locked] +Name=A lock key has been activated +Name[af]='n Sluitsleutel is geaktiveer +Name[ar]=تم تفعيل مفتاح قفل +Name[ast]=Activóse una tecla de bloquéu +Name[be@latin]=Klaviša macavańnia prycisnutaja +Name[bg]=Включен е клавиш за превключване на режим +Name[bn]=একটি লক কী (lock key) সক্রিয় হয়েছে +Name[bs]=Zaključavajući taster je aktiviran +Name[ca]=S'ha activat alguna tecla de fixació +Name[ca@valencia]=S'ha activat alguna tecla de fixació +Name[cs]=Klávesa pro přepnutí stavu byla aktivována +Name[csb]=Klawisza blokadë òsta aktiwòwónô +Name[da]=En låsetast er blevet aktiveret +Name[de]=Eine Sperrtaste ist aktiviert worden +Name[el]=Ένα πλήκτρο κλειδώματος έχει ενεργοποιηθεί +Name[en_GB]=A lock key has been activated +Name[eo]=Baskula klavo aktiviĝis +Name[es]=Se ha activado una tecla de bloqueo +Name[et]=Lukustusklahv on aktiveeritud +Name[eu]=Blokeo-tekla bat aktibatu da +Name[fi]=Lukitusnäppäin on aktivoitu +Name[fr]=Une touche de verrouillage a été activée +Name[fy]=In beskoatteltoets is aktivearre +Name[ga]=Tá eochair ghlasála gníomhach anois +Name[gl]=Activouse unha tecla de bloqueo +Name[gu]=તાળાં કળ સક્રિય કરવામાં આવી છે +Name[he]=מקש נועל הפך לפעיל +Name[hi]=कोई तालाबंद कुंजी सक्रिय किया जा चुका है +Name[hne]=कोई ताला कुंजी सक्रिय हो गे हे +Name[hr]=Tipka zaključavanja je aktivirana +Name[hsb]=Tasta za stajne zaswěćene je nětko aktiwna +Name[hu]=Egy zároló billentyű aktívvá vált +Name[ia]=Un clave de bloco ha essite activate +Name[id]=Sebuah tombol pengunci telah diaktifkan +Name[is]=Læsilykill hefur verið virkjaður +Name[it]=Un tasto di blocco è stato attivato +Name[ja]=ロックキーがアクティブになりました +Name[ka]=დაბლოკვის ღილაკი გააქტივებულია +Name[kk]=Қосқыш перне белсендірілді +Name[km]=គ្រាប់​ចុច​ចាក់​សោ​បាន​ត្រូវ​ធ្វើ​ឲ្យ​សកម្ម +Name[kn]=ಒಂದು ಭಂಧನ ಕೀಲಿಯನ್ನು (ಲಾಕ್) ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=잠금 키가 활성화됨 +Name[ku]=Bişkojkeke Mifteyê hat çalakirin +Name[lt]=Užrakto klavišas buvo aktyvuotas +Name[lv]=Slēga taustiņš tika aktivizēts +Name[mk]=Некое копче за заклучување беше активирано +Name[ml]=ഒരു ലോക്ക് കീ സജീവമാക്കിയിരിക്കുന്നു +Name[mr]=कुलूपबंद कि सक्रिय केली गेली +Name[nb]=En låsetast er blitt slått på +Name[nds]=En Tastrast is nu inleggt +Name[ne]=एउटा ताल्चा कुञ्जी सक्रिय बनाइएको छ +Name[nl]=Een vergrendeltoets is geactiveerd +Name[nn]=Ein låstetast er no aktiv +Name[or]=ଗୋଟିଏ ଅପରିବର୍ତ୍ତନୀୟ କିକୁ ସକ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਇੱਕ ਲਾਕ ਸਵਿੱਚ ਐਕਟਿਵੇਟ ਕੀਤੀ ਗਈ +Name[pl]=Klawisz blokujący został włączony +Name[pt]=Uma tecla de bloqueio foi activada +Name[pt_BR]=Uma tecla de bloqueio foi ativada +Name[ro]=O tastă de blocare a fost activată +Name[ru]=Активирована клавиша переключения режимов +Name[se]=Lohkkadanboallu lea aktiivalaš +Name[si]=අගුළු යතුර සක්‍රීයයි +Name[sk]=Zamykací kláves je aktívny +Name[sl]=Zaklepna tipka je bila omogočena +Name[sr]=Закључавајући тастер је активиран +Name[sr@ijekavian]=Закључавајући тастер је активиран +Name[sr@ijekavianlatin]=Zaključavajući taster je aktiviran +Name[sr@latin]=Zaključavajući taster je aktiviran +Name[sv]=En låstangent har aktiverats +Name[ta]=A lock key has been activated +Name[te]=అప్రవేశపు కీ క్రియాశీలం చేయబడింది +Name[tg]=Активирована клавиша переключения режимов +Name[th]=ปุ่มล็อคถูกเปิดการทำงาน +Name[tr]=Bir kilitleme tuşu etkinleştirildi +Name[ug]=بىر قۇلۇپلاش كۇنۇپكىسى ئاكتىپلاندى +Name[uk]=Було активовано клавішу фіксації +Name[wa]=Ene eclawåve tape a stî metowe en alaedje +Name[x-test]=xxA lock key has been activatedxx +Name[zh_CN]=锁定键现已激活 +Name[zh_TW]=已啟動鎖定鍵 +Comment=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now active +Comment[af]='n Sluitsleutel (bv. Caps Lock of Num Lock) se toestand het verander en is nou aktief +Comment[ar]=تغيرت حالة مفتاح قفل (Caps Lock أو Num Lock) وأصبح مفعلاً +Comment[ast]=Una tecla de bloquéu (como Bloq Mayús o Bloq Num) camudó l'estáu y ta activa +Comment[be@latin]=Klaviša macavańnia (naprykład, „Caps Lock” ci „Num Lock”) źmianiła svajo stanovišča j ciapier prycisnutaja. +Comment[bg]=Клавиш за превключване на режим (напр. Caps Lock или Num Lock) промени състоянието си и е активен +Comment[bn]=একটি লক কী (e.g. Caps Lock বা Num Lock) অবস্থা পরিবর্তন করে এখন সক্রিয় হয়েছে +Comment[bs]=Zaključavajući taster (npr. CapsLock ili NumLock) promijenio je stanje i sada je aktivan +Comment[ca]=Alguna tecla de fixació (p.ex. Bloq Maj o Bloq Núm) ha canviat el seu estat i ara està activa +Comment[ca@valencia]=Alguna tecla de fixació (p.ex. Bloq Maj o Bloq Núm) ha canviat el seu estat i ara està activa +Comment[cs]=Klávesa pro přepnutí stavu (např. CapsLock nebo NumLock) byla stisknuta a je nyní aktivní +Comment[csb]=Klawisza blokadë (Caps Lock abò Num Lock) zmienia swój sztatus ë je terô aktiwnô +Comment[da]=En låsetast (f.eks. Caps Lock eller Num Lock) har ændret sin tilstand og er nu aktiv +Comment[de]=Eine Sperrtaste (Feststelltaste oder Nummernblocksperre) hat ihren Status geändert und ist nun aktiv +Comment[el]=Ένα πλήκτρο κλειδώματος (π.χ., Caps Lock ή Num Lock) άλλαξε την κατάστασή του και είναι τώρα ενεργό +Comment[en_GB]=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now active +Comment[eo]=Baskula klavo (ekz. majuskla baskulo aŭ nombra baskulo) ŝanĝis sian staton kaj nun estas aktiva +Comment[es]=Una tecla de bloqueo (como Bloq Mayús o Bloq Num) ha cambiado su estado y está activa +Comment[et]=Lukustusklahv (nt. Caps Lock või Num Lock) muutis oma seisundit ning on nüüd aktiivne +Comment[eu]=Blokeo-tekla bat (adibidez, Blok Maius edo Blok Zenb) egoeraz aldatu da, eta orain aktibo dago +Comment[fi]=Lukitusnäppäin (esim. CapsLock tai NumLock) on vaihtanut tilaansa ja on nyt aktiivinen +Comment[fr]=Une touche de verrouillage (ex : « Verr. Maj. » ou « Verr. Num. ») a changé d'état et est maintenant active +Comment[fy]=De tastân fan in beskoatteltoets (lykas kaptaalskoattel of Nûm skoattel) is feroare en is no aktyf +Comment[ga]=Athraíodh staid eochrach glasála (m.sh. Caps Lock nó Num Lock) agus tá sí gníomhach anois +Comment[gl]=Unha tecla de bloqueo (por ex. Bloq Maiús ou Bloq Num) cambiou de estado e agora está activa +Comment[gu]=તાળાં કળે (દા.ત., કેપ્સ લોક અથવા નમ લોક) હવે તેની સ્થિતિ બદલી છે અને હવે સક્રિય છે +Comment[he]=מקש נועל (למשל Caps Lock או Num Lock) שינה את מצבו וכרגע פעיל +Comment[hne]=कोई ताला कुंजी (जइसन कि कैप्स लाक या न्यूम लाक) हर अपन स्थिति ल बदल दे हे अउ अब वो हर सक्रिय हो गे हे +Comment[hr]=Tipka zaključavanja (npr. CapsLock ili NumLock) promijenila je svoje stanje i aktivna je +Comment[hsb]=Tasta za stajne zaswěćene (na př. Stajny Wulkopis) je status změniła a je nětko aktiwna +Comment[hu]=Egy zároló billentyű (pl. a Caps Lock vagy a Num Lock) aktívvá vált +Comment[ia]=Un clave de bloco (p.ex. Caps Lock o Num Lock) ha cambiate su stato e ora es active +Comment[id]=Sebuah tombol kunci (misalnya Caps Lock atau Num Lock) telah diubah keadaannya dan sekarang aktif +Comment[is]=Læsilykill (t.d. Caps Lock eða Num Lock) hefur breytt um stöðu og er nú virkur +Comment[it]=Un tasto di blocco (ad es. Bloc Maiusc o Bloc Num) ha cambiato stato ed è ora attivo +Comment[ja]=ロックキー (Caps Lock や Num Lock) の状態が変更され、非アクティブになりました +Comment[kk]=Қосқыш перне (мыс. Caps Lock не Num Lock) күйін ауыстырып енді белсенді +Comment[km]=គ្រាប់ចុច​ចាក់សោ (ឧ. ប្ដូរ​ជាប់(Caps Lock) ឬ​គ្រាប់ចុច​លេខ) បាន​ផ្លាស់ប្ដូរ​ស្ថានភាព​របស់វា ហើយ​តឡូវ​សកម្ម +Comment[kn]=ಒಂದು ಭಂಧನ (ಲಾಕ್) ಕೀಲಿ (ಉ.ದಾ Shift ಅಥವಾ Ctrl) ನ ಸ್ಥಿತಿಯು ಬದಲಾಗಿದ್ದು ಈಗ ಸಕ್ರಿಯಗೊಂಡಿದೆ +Comment[ko]=Caps Lock이나 Num Lock 키 같은 잠금 키의 상태가 바뀌었고 현재 활성화됨 +Comment[ku]=Rewşa Bişkojkeke Mifteyê (wekî Caps Lock an jî Num Lock) hate guhertin û niha çalak e +Comment[lt]=Užrakto klavišo (pvz., Didž(Caps Lock) arba Sk(Num Lock)) būsena pakito ir jis dabar – aktyvus +Comment[lv]=Slēga taustiņš (piem. Caps Lock vai Num Lock) ir mainījis stāvokli un tagad ir aktīvs +Comment[mk]=Некое копче за заклучување (пр. Caps Lock или Num Lock) си ја смени состојбата и сега е активно +Comment[ml]=ഒരു ലോക്ക് കീ (ഉദാ. കാപ്സ് ലോക്ക് അല്ലെങ്കില്‍ നം ലോക്ക്) അവസ്ഥ മാറി സജീവമാക്കിയിരിക്കുന്നു +Comment[mr]=कुलूपबंद कि (उ.दा. Caps Lock किंवा Num Lock) ने स्तर बदलविले आहे व आता सक्रिय आहे +Comment[nb]=En låsetast (f.eks. Caps Lock eller Num Lock) har endret status og er nå slått på +Comment[nds]=En Tastrast (Tallen- oder Grootschriev-Rast a.B.) hett sien Tostand ännert un is nu inleggt +Comment[nl]=Een vergrendeltoets (bijv. Caps Lock of Num Lock ) is nu actief +Comment[nn]=Ein låsetast (som «Caps Lock» eller «Num Lock») har endra status, og er no aktiv +Comment[or]=ଗୋଟିଏ ଅପରିବର୍ତ୍ତନୀୟ କି (ଯେପରିକି Caps Lock କିମ୍ବା Num Lock) ସେମାନଙ୍କର ସ୍ଥିତି ପରିବର୍ତ୍ତନ କରିଛନ୍ତି ଏବଂ ବର୍ତ୍ତମାନ ସକ୍ରିୟ ଅଛନ୍ତି +Comment[pl]=Klawisz blokujący (np. Caps Lock lub Num Lock) zmienił stan i jest teraz włączony +Comment[pt]=Uma tecla de bloqueio (p.ex., a Caps Lock ou a Num Lock) alterou o seu estado e ficou agora activa +Comment[pt_BR]=Uma tecla de bloqueio (p.ex. Caps Lock ou Num Lock) teve seu estado alterado e agora está ativa +Comment[ro]=O tastă de blocare (cum ar fi Caps Lock sau Num Lock) și-a schimbat starea și este acum activă +Comment[ru]=Клавиша переключения режимов (например, Caps Lock или Num Lock) изменила своё состояние и сейчас активна +Comment[si]=අගුළු යතුරේ (උදා. Caps Lock හෝ Num Lock) තත්වය වෙනස් වී ඇති අතර එය දැන් සක්‍රීයයි +Comment[sk]=Zamykací kláves (napr. Caps Lock alebo Num Lock) zmenil svoj stav a je teraz aktívny +Comment[sl]=Zaklepna tipka (npr. Caps Lock ali Num Lock) je spremenila stanje in je sedaj dejavna +Comment[sr]=Закључавајући тастер (нпр. CapsLock или NumLock) променио је стање и сада је активан +Comment[sr@ijekavian]=Закључавајући тастер (нпр. CapsLock или NumLock) промијенио је стање и сада је активан +Comment[sr@ijekavianlatin]=Zaključavajući taster (npr. CapsLock ili NumLock) promijenio je stanje i sada je aktivan +Comment[sr@latin]=Zaključavajući taster (npr. CapsLock ili NumLock) promenio je stanje i sada je aktivan +Comment[sv]=En låstangent (t.ex. Caps Lock eller Num Lock) har ändrat tillstånd och är nu aktiv +Comment[ta]=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now active +Comment[te]=అప్రవేశపు కీ (ఉ.దా. Caps Lock లేదా Num Lock) దాని స్థితి మార్చుకుంది మరియు ఇప్పుడు క్రియాశీలంగా ఉంది +Comment[tg]=Клавиша переключения режимов (например, Caps Lock или Num Lock) изменила своё состояние и сейчас активна +Comment[th]=ปุ่มล็อค (เช่น Caps Lock หรือ Num Lock) ได้มีการเปลี่ยนสถานะของมันและขณะนี้กำลังทำงานอยู่ +Comment[tr]=Bir kilitleme tuşunun (Caps Lock ya da Num Lock gibi.) durumu değiştirildi ve etkinleştirildi +Comment[ug]=بىر قۇلۇپلاش كۇنۇپكىسى (مەسىلەن، Caps Lock ياكى Num Lock) ئۇنىڭ ھالىتىنى ئۆزگەرتتى، ھازىر ئاكتىپلاندى +Comment[uk]=Клавіша фіксації (наприклад Caps Lock або Num Lock) змінила свій стан і тепер активна +Comment[wa]=Ene eclawåve tape ki sere (metans CAPS LOCK oudonbén NUM LOCK) a candjî si estat eyet est asteure ovrante +Comment[x-test]=xxA lock key (e.g. Caps Lock or Num Lock) has changed its state and is now activexx +Comment[zh_CN]=锁定键(如 Caps Lock 或 Num Lock)更改了其状态,现已激活 +Comment[zh_TW]=一個鎖定鍵(如 CapsLock 或 NumLock)已改變它的狀態為啟用 +Sound=KDE-Sys-Special.ogg + +nopresentation=236 + +[Event/lockkey-unlocked] +Name=A lock key has been deactivated +Name[af]='n Sluit sleutel was gedeaktiveer +Name[ar]=تم إلغاء تفعيل مفتاح قفل +Name[ast]=Desactivóse una tecla de bloquéu +Name[be@latin]=Klaviša macavańnia adcisnutaja +Name[bg]=Изключен е клавиш за превключване на режим +Name[bn]=একটি লক কী (lock key) নিষ্ক্রীয় হয়েছে +Name[bs]=Zaključavajući taster je deaktiviran +Name[ca]=S'ha desactivat alguna tecla de fixació +Name[ca@valencia]=S'ha desactivat alguna tecla de fixació +Name[cs]=Klávesa pro přepnutí stavu byla deaktivována +Name[csb]=Klawisza blokadë òsta deaktiwòwónô +Name[da]=En låsetast er blevet deaktiveret +Name[de]=Eine Sperrtaste ist deaktiviert worden +Name[el]=Ένα πλήκτρο κλειδώματος απενεργοποιήθηκε +Name[en_GB]=A lock key has been deactivated +Name[eo]=Baskula klavo malaktiviĝis +Name[es]=Se ha desactivado una tecla de bloqueo +Name[et]=Lukustusklahv on nüüd mitteaktiivne +Name[eu]=Blokeo-tekla bat desaktibatu da +Name[fi]=Lukitusnäppäin on nyt deaktivoitu +Name[fr]=Une touche de verrouillage a été désactivée +Name[fy]=In beskoatteltoets is ûntaktivearre +Name[ga]=Tá eochair ghlasála neamhghníomhach anois +Name[gl]=Desactivouse unha tecla de bloqueo +Name[gu]=તાળાં કળ નિષ્ક્રિય કરવામાં આવી છે +Name[he]=מקש נועל הפך ללא פעיל +Name[hi]=कोई तालाबंद कुंजी अक्रिय किया जा चुका है +Name[hne]=कोई ताला कुंजी हर अक्रिय हो गे हे +Name[hr]=Tipka zaključavanja je deaktivirana +Name[hsb]=Tasta za stajne zaswěćene je nětko njeaktiwna +Name[hu]=Egy zároló billentyű inaktívvá vált +Name[ia]=Un clave de bloco ha essite deactivate +Name[id]=Sebuah tombol kunci telah dinonaktifkan +Name[is]=Læsilykill hefur verið aftengdur +Name[it]=Un tasto di blocco è stato disattivato +Name[ja]=ロックキーが非アクティブになりました +Name[ka]=დაბლოკვის ღილაკი ამორთულია +Name[kk]=Қосқыш перне белсенсіздірілді +Name[km]=គ្រាប់​ចុច​ចាក់​សោ​ត្រូវ​បាន​​​ធ្វើ​ឲ្យ​អសកម្ម +Name[kn]=ಒಂದು ಭಂಧನ ಕೀಲಿಯನ್ನು (ಲಾಕ್) ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=잠금 키가 비활성화됨 +Name[ku]=Bişkojkeke Mifteyê hate neçalakirin +Name[lt]=Užrakto klavišas buvo išjungtas +Name[lv]=Slēga taustiņš tika deaktivizēts +Name[mk]=Некое копче за заклучување беше активирано +Name[ml]=ഒരു ലോക്ക് കീ നിര്‍ജ്ജീവമാക്കിയിരിക്കുന്നു +Name[mr]=कुलूपबंद कि निष्क्रिय केली गेली +Name[nb]=En låsetast er blitt slått av +Name[nds]=En Tastrast is nich mehr inleggt +Name[ne]=लक कुञ्जी निष्क्रिय भएको छ +Name[nl]=Een vergrendeltoets is gedeactiveerd +Name[nn]=Ein låsetast er no inaktiv +Name[or]=ଗୋଟିଏ ଅପରିବର୍ତ୍ତନୀୟ କିକୁ ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਇੱਕ ਲਾਕ ਸਵਿੱਚ ਡਿਐਕਟਿਵੇਟ ਕੀਤੀ ਗਈ +Name[pl]=Klawisz blokujący został wyłączony +Name[pt]=Uma tecla de bloqueio foi desactivada +Name[pt_BR]=Uma tecla de bloqueio foi desativada +Name[ro]=O tastă de blocare a fost dezactivată +Name[ru]=Деактивирована клавиша переключения режимов +Name[se]=Lohkkadanboallu ii leat šat aktiivalaš +Name[si]=අගුළු යතුර අක්‍රීයයි +Name[sk]=Zamykací kláves je neaktívny +Name[sl]=Zaklepna tipka je bila onemogočena +Name[sr]=Закључавајући тастер је деактивиран +Name[sr@ijekavian]=Закључавајући тастер је деактивиран +Name[sr@ijekavianlatin]=Zaključavajući taster je deaktiviran +Name[sr@latin]=Zaključavajući taster je deaktiviran +Name[sv]=En låstangent har inaktiverats +Name[ta]=A lock key has been deactivated +Name[te]=అప్రవేశపు కీ క్రియాహీనం చేయబడింది +Name[tg]=Деактивирована клавиша переключения режимов +Name[th]=ปุ่มล็อคถูกปิดการทำงาน +Name[tr]=Bir kilitleme tuşu pasifleştirildi +Name[ug]=بىر قۇلۇپلاش كۇنۇپكىسى پاسسىپلاشتۇرۇلدى +Name[uk]=Було деактивовано клавішу фіксації +Name[wa]=Ene eclawåve tape a stî dismetowe +Name[x-test]=xxA lock key has been deactivatedxx +Name[zh_CN]=锁定键现已停用 +Name[zh_TW]=已解除鎖定鍵 +Comment=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now inactive +Comment[af]='n Sluitsleutel (bv. Caps Lock of Num Lock) se toestand het verander en is nou onaktief +Comment[ar]=تغيرت حالة مفتاح قفل (Caps Lock أو Num Lock) وألغي تفعيله +Comment[ast]=Una tecla de bloquéu (como Bloq Mayús o Bloq Num) camudó l'estáu y non ta activada +Comment[be@latin]=Klaviša macavańnia (naprykład, „Caps Lock” ci „Num Lock”) źmianiła svajo stanovišča j ciapier adcisnutaja. +Comment[bg]=Клавиш за превключване на режим (напр. Caps Lock или Num Lock) промени състоянието си и е неактивен +Comment[bn]=একটি লক কী (e.g. Caps Lock বা Num Lock) অবস্থা পরিবর্তন করে এখন নিষ্ক্রীয় হয়েছে +Comment[bs]=Zaključavajući taster (npr. CapsLock ili NumLock) promijenio je stanje i više nije aktivan +Comment[ca]=Alguna tecla de fixació (p.ex. Bloq Maj o Bloq Núm) ha canviat el seu estat i ara està inactiva +Comment[ca@valencia]=Alguna tecla de fixació (p.ex. Bloq Maj o Bloq Núm) ha canviat el seu estat i ara està inactiva +Comment[cs]=Klávesa pro přepnutí stavu (např. CapsLock nebo NumLock) byla stisknuta a je nyní neaktivní +Comment[csb]=Klawisza blokadë (Caps Lock abò Num Lock) zmienia swój sztatus ë nie je ju aktiwnô +Comment[da]=En låsetast (f.eks. Caps Lock eller Num Lock) har ændret sin tilstand og er nu inaktiv +Comment[de]=Eine Sperrtaste (Feststelltaste oder Nummernblocksperre) hat ihren Status geändert und ist nun inaktiv +Comment[el]=Ένα πλήκτρο κλειδώματος (π.χ. Caps Lock ή Num Lock) άλλαξε την κατάστασή του και είναι τώρα ανενεργό +Comment[en_GB]=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now inactive +Comment[eo]=Baskula klavo (ekz. majuskla baskulo aŭ nombra baskulo) ŝanĝis sian staton kaj nun estas malaktiva +Comment[es]=Una tecla de bloqueo (como Bloq Mayús o Bloq Num) ha cambiado su estado y no está activa +Comment[et]=Lukustusklahv (nt. Caps Lock või Num Lock) muutis oma seisundit ning on nüüd mitteaktiivne +Comment[eu]=Blokeo-tekla bat (adibidez, Blok Maius edo Blok Zenb) egoeraz aldatu da, eta orain inaktibo dago +Comment[fi]=Lukitusnäppäin (esim. CapsLock tai NumLock) on vaihtanut tilaansa ja ei ole enää aktiivinen +Comment[fr]=Une touche de verrouillage (ex : « Verr. Maj. » ou « Verr. Num. ») a changé d'état et est maintenant inactive +Comment[fy]=De tastân fan in beskoatteltoets (lykas kaptaalskoattel of Nûm skoattel) is feroare en is no ynaktyf +Comment[ga]=Athraíodh staid eochrach glasála (m.sh. Caps Lock nó Num Lock) agus tá sí neamhghníomhach anois +Comment[gl]=Unha tecla de bloqueo (por ex., Bloq Maiús ou Bloq Num) cambiou de estado e agora está inactiva +Comment[gu]=તાળાં કળે (દા.ત., કેપ્સ લોક અથવા નમ લોક) હવે તેની સ્થિતિ બદલી છે અને હવે તે નિષ્ક્રિય છે +Comment[he]=מקש נועל (למשל Caps Lock או Num Lock) שינה את מצבו וכרגע לא פעיל +Comment[hne]=कोई ताला कुंजी (जइसन कि कैप्स लाक या न्यूम लाक) हर अपन स्थिति ल बदल दे हे अउ अब वो हर अक्रिय हो गे हे +Comment[hr]=Tipka zaključavanja (npr. CapsLock ili NumLock) promijenila je svoje stanje i više nije aktivna +Comment[hsb]=Tasta za stajne zaswěćene (na př. Stajny Wulkopis) je status změniła a je nětko njeaktiwna +Comment[hu]=Egy zároló billentyű (pl. a Caps Lock vagy a Num Lock) inaktívvá vált +Comment[ia]=Un clave de bloco (p.ex. Caps Lock o Num Lock) ha cambiate su stato e ora es inactive +Comment[id]=Sebuah tombol kunci (misalnya Caps Lock atau Num Lock) telah diubah keadaannya dan sekarang tidak aktif +Comment[is]=Læsilykill (t.d. Caps Lock eða Num Lock) hefur breytt um stöðu og er nú óvirkur +Comment[it]=Un tasto di blocco (ad es. Bloc Maiusc o Bloc Num) ha cambiato stato ed è ora disattivo +Comment[ja]=ロックキー (Caps Lock や Num Lock) の状態が変更され、非アクティブになりました +Comment[kk]=Қосқыш перне (мыс. Caps Lock не Num Lock) күйін ауыстырып енді белсенді емес +Comment[km]=គ្រាប់​ចុច​ចាក់​សោ (ឧ. ប្ដូរ​ជាប់ (Caps Lock) ឬ​គ្រាប់ចុច​លេខ (Num Lock)) បាន​ត្រូវ​ផ្លាស់ប្ដូរ​ស្ថានភាព​​របស់​​វា ហើយ​ឥឡូវ​នេះ​អសកម្ម +Comment[kn]=ಒಂದು ಭಂಧನ (ಲಾಕ್) ಕೀಲಿ (ಉ.ದಾ Shift ಅಥವಾ Ctrl) ನ ಸ್ಥಿತಿಯು ಬದಲಾಗಿದ್ದು ಈಗ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ +Comment[ko]=Caps Lock이나 Num Lock 키 같은 잠금 키의 상태가 바뀌었고 현재 비활성화됨 +Comment[ku]=Rewşa bişkojkeke mifteyê (wekî Caps Lock an jî Num Lock) hate guhertin û niha neçalak e +Comment[lt]=Užrakto klavišo (pvz., Didž(Caps Lock) arba Sk(Num Lock)) būsena pakito ir jis dabar – neaktyvus +Comment[lv]=Slēga taustiņš (piem. Caps Lock vai Num Lock) ir mainījis stāvokli un tagad ir neaktīvs +Comment[mk]=Некое копче за заклучување (пр. Caps Lock или Num Lock) си ја смени состојбата и сега е неактивно +Comment[ml]=ഒരു ലോക്ക് കീ (ഉദാ. കാപ്സ് ലോക്ക് അല്ലെങ്കില്‍ നം ലോക്ക്) അവസ്ഥ മാറി നിര്‍ജീവമായിരിക്കുന്നു +Comment[mr]=कुलूपबंद कि (उ.दा. Caps Lock किंवा Num Lock) ने स्तर बदलविले आहे व आता निष्क्रिय आहे +Comment[nb]=En låsetast (f.eks. Caps Lock eller Num Lock) har endret status og er nå slått av +Comment[nds]=En Tastrast (Tallen- oder Grootschriev-Rast a.B.) hett sien Tostand ännert un is nu nich mehr inleggt +Comment[nl]=Een vergrendeltoets (bijv. Caps Lock of Num Lock ) is nu inactief +Comment[nn]=Ein låsetast (som «Caps Lock» eller «Num Lock») har endra status, og er no inaktiv +Comment[or]=ଗୋଟିଏ ଅପରିବର୍ତ୍ତନୀୟ କି (ଯେପରିକି Caps Lock କିମ୍ବା Num Lock) ସେମାନଙ୍କର ସ୍ଥିତି ପରିବର୍ତ୍ତନ କରିଛନ୍ତି ଏବଂ ବର୍ତ୍ତମାନ ନିଷ୍କ୍ରିୟ ଅଛି +Comment[pl]=Klawisz blokujący (np. Caps Lock lub Num Lock) zmienił stan i jest teraz wyłączony +Comment[pt]=Uma tecla de bloqueio (p.ex., a Caps Lock ou a Num Lock) alterou o seu estado e ficou agora inactiva +Comment[pt_BR]=Uma tecla de bloqueio (p.ex. Caps Lock ou Num Lock) teve seu estado alterado e agora está inativa +Comment[ro]=O tastă de blocare (cum ar fi Caps Lock sau Num Lock) și-a schimbat starea și este acum inactivă +Comment[ru]=Клавиша переключения режимов (например, Caps Lock или Num Lock) изменила своё состояние и сейчас не активна +Comment[si]=අගුළු යතුරේ (උදා. Caps Lock හෝ Num Lock) තත්වය වෙනස් වී ඇති අතර එය දැන් අක්‍රීයයි +Comment[sk]=Zamykací kláves (napr. Caps Lock alebo Num Lock) zmenil svoj stav a je teraz neaktívny +Comment[sl]=Zaklepna tipka (npr. Caps Lock ali Num Lock) je spremenila stanje in je sedaj nedejavna +Comment[sr]=Закључавајући тастер (нпр. CapsLock или NumLock) променио је стање и више није активан +Comment[sr@ijekavian]=Закључавајући тастер (нпр. CapsLock или NumLock) промијенио је стање и више није активан +Comment[sr@ijekavianlatin]=Zaključavajući taster (npr. CapsLock ili NumLock) promijenio je stanje i više nije aktivan +Comment[sr@latin]=Zaključavajući taster (npr. CapsLock ili NumLock) promenio je stanje i više nije aktivan +Comment[sv]=En låstangent (t.ex. Caps Lock eller Num Lock) har ändrat tillstånd och är nu inaktiv +Comment[ta]=A lock key (e.g. Caps Lock or Num Lock) has changed its state and is now inactive +Comment[te]=అప్రవేశపు కీ (ఉ.దా. Caps Lock లేదా Num Lock) దాని స్థితిని మార్చుకుంది మరియు ఇప్పుడు క్రియాహీనంగా ఉంది +Comment[tg]=Клавиша переключения режимов (например, Caps Lock или Num Lock) изменила своё состояние и сейчас не активна +Comment[th]=ปุ่มล็อค (เช่น Caps Lock หรือ Num Lock) ได้มีการเปลี่ยนสถานะของมันและขณะนี้ได้ปิดการทำงาน +Comment[tr]=Bir kilitleme tuşunun (Caps Lock ya da Num Lock gibi.) durumu değiştirildi ve pasifleştirildi +Comment[ug]=بىر قۇلۇپلاش كۇنۇپكىسى (مەسىلەن، Caps Lock ياكى Num Lock) ئۇنىڭ ھالىتىنى ئۆزگەرتتى، ھازىر پاسسىپلاشتۇرۇلدى +Comment[uk]=Клавіша фіксації (наприклад Caps Lock або Num Lock) змінила свій стан і тепер неактивна +Comment[wa]=Ene eclawåve tape (metans CAPS LOCK oudonbén NUM LOCK) a candjî si estat eyet n' est asteure pus ovrante +Comment[x-test]=xxA lock key (e.g. Caps Lock or Num Lock) has changed its state and is now inactivexx +Comment[zh_CN]=锁定键(如 Caps Lock 或 Num Lock)更改了其状态,现已停用 +Comment[zh_TW]=一個鎖定鍵(如 CapsLock 或 NumLock)已改變它的狀態成為未啟用 +Sound=KDE-Sys-Special.ogg + +nopresentation=236 + +[Event/stickykeys] +Name=Sticky keys has been enabled or disabled +Name[af]=Sticky sleutels was geaktiveer of gedeaktiveer +Name[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح المثبتة +Name[ast]=Les tecles pegañoses activáronse o desactiváronse +Name[be@latin]=Lipučyja klavišy źmianili svajo stanovišča +Name[bg]="Лепкави" клавиши са включени или изключени +Name[bs]=Ljepljivi tasteri su uključeni ili isključeni +Name[ca]=Les tecles apegaloses s'han activat o desactivat +Name[ca@valencia]=Les tecles apegaloses s'han activat o desactivat +Name[cs]=Lepivé klávesy byly povoleny nebo zakázány +Name[csb]=Klawisze przëlepieniô òstałë aktiwòwòné abò deaktiwòwóné +Name[da]=Klæbende taster er aktiveret eller deaktiveret +Name[de]=Klebende Tasten sind aktiviert oder deaktiviert worden +Name[el]=Τα κολλημένα πλήκτρα ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Name[en_GB]=Sticky keys has been enabled or disabled +Name[eo]=Fiksaj klavoj validiĝis aŭ malvalidiĝis +Name[es]=Las teclas pegajosas se han activado o desactivado +Name[et]=Kleepuvad klahvid on keelatud või lubatud +Name[eu]=Tekla itsaskorrak gaitu edo desgaitu dira +Name[fi]=Tahmeat näppäimet on otettu käyttöön tai poistettu käytöstä +Name[fr]=L'auto-maintien des touches a été activé ou désactivé +Name[fy]=Plakkende toetsen binne aktivearre of deaktivearre +Name[ga]=Cumasaíodh nó díchumasaíodh eochracha greamaitheacha +Name[gl]=As teclas pegañentas activáronse ou desactiváronse +Name[gu]=સ્થિત કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Name[he]=מקשים דביקים הופעלו או בוטלו +Name[hi]=चिपकती कुंजियों को सक्षम या अक्षम किया गया है +Name[hne]=स्टिकी कुंजी सक्रिय या अक्रिय हो गे हे +Name[hr]=Ljepljive tipke su omogućene ili onemogućene +Name[hsb]=Lěpjate tasty zaswěćene abo hasnjene +Name[hu]=Ragadós billentyűk átkapcsolva +Name[ia]=Le claves collate ha essite habilitate o dishabilitate +Name[id]=Tombol lekat telah diaktifkan atau dinonaktifkan +Name[is]=Slökkt eða kveikt hefur verið á klístruðum lyklum +Name[it]=I tasti permanenti sono stati attivati o disattivati +Name[ja]=スティッキーキーが有効または無効になりました +Name[kk]=Жабысқақ пернелер рұқсат етілді/етілмеді +Name[km]=គ្រាប់​ចុច​ស្អិត​​ត្រូវ​បាន​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Name[kn]=ಅಂಟು (ಸ್ಟಿಕಿ) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=끈적이 키가 활성화되거나 비활성화됨 +Name[ku]=Bişkojkên Mezeloqî hatin çalakirin an jî neçalakirin +Name[lt]=Lipnūs klavišai buvo įgalinti arba išjungti +Name[lv]=Lipīgie taustiņi tika ieslēgti vai izslēgti +Name[mk]=„Лепливи копчиња“ е овозможено или оневозможено +Name[ml]=സ്റ്റിക്കി കീ പ്രവര്‍ത്തന സജ്ജം അല്ലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതം ആക്കിയിരിക്കുന്നു +Name[mr]=स्टिकी कि कार्यन्वीत किंवा अकार्यान्वित केली गेली आहे +Name[nb]=Faste valgtaster er blitt slått på eller av +Name[nds]="Backig Tasten" wöör an- oder utmaakt +Name[ne]=स्टिकी कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Name[nl]=Plakkende toetsen is geactiveerd of gedeactiveerd +Name[nn]=Faste valtastar er no slått på eller av +Name[or]=Sticky କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਸਟਿੱਕੀ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Name[pl]=Lepkie klawisze zostały włączone lub wyłączone +Name[pt]=As teclas fixas foram activadas ou desactivadas +Name[pt_BR]=Teclas de aderência foram habilitadas ou desabilitadas +Name[ro]=Taste lipicioase au fost activate sau dezactivate +Name[ru]=Включены или отключены «залипающие» клавиши +Name[se]=Giddes válljenboallu lea rievdadan stáhtusa +Name[si]=ඇළෙන යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Name[sk]=Lepkavé klávesy zmenili svoj stav +Name[sl]=Lepljive tipke so bile omogočene ali onemogočene +Name[sr]=Лепљиви тастери су укључени или искључени +Name[sr@ijekavian]=Љепљиви тастери су укључени или искључени +Name[sr@ijekavianlatin]=Ljepljivi tasteri su uključeni ili isključeni +Name[sr@latin]=Lepljivi tasteri su uključeni ili isključeni +Name[sv]=Klistriga tangenter har aktiverats eller inaktiverats +Name[ta]=Sticky keys has been enabled or disabled +Name[te]=స్టికీ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Name[tg]=Тугмаҳои часпанда фаъол ё ғайрифаъол шудаанд +Name[th]=การกดปุ่มพิมพ์ค้างได้ถูกเปิดหรือปิดการทำงาน +Name[tr]=Yapışkan tuşlar etkinleştirildi ya da pasifleştirildi +Name[ug]=چاپلىشاڭغۇ(Sticky) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Name[uk]=Було активовано або деактивовано липкі клавіші +Name[wa]=Les aclapantès tapes on stî metowes oudonbén dismetowes +Name[x-test]=xxSticky keys has been enabled or disabledxx +Name[zh_CN]=启用或禁用了粘滞键 +Name[zh_TW]=相黏鍵已改變狀態 +Comment=Sticky keys has been enabled or disabled +Comment[af]=Sticky sleutels was geaktiveer of gedeaktiveer +Comment[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح المثبتة +Comment[ast]=Les tecles pegañoses activáronse o desactiváronse +Comment[be@latin]=Lipučyja klavišy źmianili svajo stanovišča. +Comment[bg]="Лепкави" клавиши са включени или изключени +Comment[bs]=Ljepljivi tasteri su uključeni ili isključeni +Comment[ca]=Les tecles apegaloses s'han activat o desactivat +Comment[ca@valencia]=Les tecles apegaloses s'han activat o desactivat +Comment[cs]=Lepivé klávesy byly povoleny nebo zakázány +Comment[csb]=Klawisze przëlepieniô òstałë aktiwòwòné abò deaktiwòwóné +Comment[da]=Klæbende taster er aktiveret eller deaktiveret +Comment[de]=Die Funktion „Klebende Tasten“ ist aktiviert oder deaktiviert worden +Comment[el]=Τα κολλημένα πλήκτρα ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Comment[en_GB]=Sticky keys has been enabled or disabled +Comment[eo]=Fiksaj klavoj validiĝis aŭ malvalidiĝis +Comment[es]=Las teclas pegajosas se han activado o desactivado +Comment[et]=Kleepuvad klahvid on keelatud või lubatud +Comment[eu]=Tekla itsaskorrak gaitu edo desgaitu dira +Comment[fi]=Tahmeat näppäimet on otettu käyttöön tai poistettu käytöstä +Comment[fr]=L'auto-maintien des touches a été activé ou désactivé +Comment[fy]=Plakkende toetsen binne aktivearre of deaktivearre +Comment[ga]=Cumasaíodh nó díchumasaíodh eochracha greamaitheacha +Comment[gl]=As teclas pegañentas foron ou activadas ou desactivadas +Comment[gu]=સ્થિત કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Comment[he]=מקשים דביקים הופעלו או בוטלו +Comment[hi]=चिपकती कुंजियों को सक्षम या अक्षम किया गया है +Comment[hne]=स्टिकी कुंजी सक्रिय या अक्रिय हो गे हे +Comment[hr]=Ljepljive tipke su omogućene ili onemogućene +Comment[hsb]=Lěpjate tasty zaswěćene abo hasnjene +Comment[hu]=A ragadós billentyűk használatát ki- vagy bekapcsolták +Comment[ia]=Le claves collate ha essite habilitate o dishabilitate +Comment[id]=Tombol lekat telah diaktifkan atau dinonaktifkan +Comment[is]=Slökkt eða kveikt hefur verið á klístruðum lyklum +Comment[it]=I tasti permanenti sono stati attivati o disattivati +Comment[ja]=スティッキーキーが有効または無効になりました +Comment[kk]=Жабысқақ пернелер рұқсат етілді/етілмеді +Comment[km]=គ្រាប់​ចុច​ស្អិត​​ត្រូវ​បាន​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Comment[kn]=ಅಂಟು (ಸ್ಟಿಕಿ) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Comment[ko]=끈적이 키가 활성화되거나 비활성화됨 +Comment[ku]=Bişkojkên Mezeloqî hatin çalakirin an jî neçalakirin +Comment[lt]=Lipnūs klavišai buvo įjungti arba išjungti +Comment[lv]=Lipīgie taustiņi tika ieslēgti vai izslēgti +Comment[mk]=„Лепливи копчиња“ е овозможено или оневозможено +Comment[ml]=സ്റ്റിക്കി കീ പ്രവര്‍ത്തന സജ്ജം അല്ലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതം ആക്കിയിരിക്കുന്നു +Comment[mr]=स्टिकी कि कार्यन्वीत किंवा अकार्यान्वित केली गेली आहे +Comment[nb]=Faste valgtaster er blitt slått på eller av +Comment[nds]="Backig Tasten" wöör an- oder utmaakt +Comment[ne]=स्टिकी कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Comment[nl]=Plakkende toetsen is geactiveerd of gedeactiveerd +Comment[nn]=Faste valtastar er no slått på eller av +Comment[or]=Sticky କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Comment[pa]=ਸਟਿੱਕੀ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Comment[pl]=Lepkie klawisze zostały włączone lub wyłączone +Comment[pt]=As teclas fixas foram activadas ou desactivadas +Comment[pt_BR]=Teclas de aderência foram habilitadas ou desabilitadas +Comment[ro]=Taste lipicioase au fost activate sau dezactivate +Comment[ru]=Включены или отключены «залипающие» клавиши +Comment[se]=Giddes válljenboallu lea rievdadan stáhtusa +Comment[si]=ඇළෙන යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Comment[sk]=Lepkavé klávesy zmenili svoj stav +Comment[sl]=Lepljive tipke so bile omogočene ali onemogočene +Comment[sr]=Лепљиви тастери су укључени или искључени +Comment[sr@ijekavian]=Љепљиви тастери су укључени или искључени +Comment[sr@ijekavianlatin]=Ljepljivi tasteri su uključeni ili isključeni +Comment[sr@latin]=Lepljivi tasteri su uključeni ili isključeni +Comment[sv]=Klistriga tangenter har aktiverats eller inaktiverats +Comment[ta]=Sticky keys has been enabled or disabled +Comment[te]=స్టికీ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Comment[tg]=Тугмаҳои часпанда фаъол ё ғайрифаъол шудаанд +Comment[th]=การกดปุ่มพิมพ์ค้างได้ถูกเปิดหรือปิดการทำงาน +Comment[tr]=Yapışkan tuşlar etkinleştirildi ya da pasifleştirildi +Comment[ug]=چاپلىشاڭغۇ(Sticky) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Comment[uk]=Було активовано або деактивовано липкі клавіші +Comment[wa]=Les aclapantès tapes on stî metowes oudonbén dismetowes +Comment[x-test]=xxSticky keys has been enabled or disabledxx +Comment[zh_CN]=启用或禁用了粘滞键 +Comment[zh_TW]=相黏鍵已啟動或關閉。 +Sound=KDE-Sys-Special.ogg +Action=Popup +nopresentation=236 + +[Event/slowkeys] +Name=Slow keys has been enabled or disabled +Name[af]=Stadige sleutels was geaktiveer of gedeaktiveer +Name[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح البطيئة +Name[ast]=Les tecles lentes activáronse o desactiváronse +Name[be@latin]=Pavolnyja klavišy źmianili svajo stanovišča +Name[bg]="Бавни" клавиши са включени или изключени +Name[bs]=Spori tasteri su uključeni ili isključeni +Name[ca]=Les tecles lentes s'han activat o desactivat +Name[ca@valencia]=Les tecles lentes s'han activat o desactivat +Name[cs]=Pomalé klávesy byly povoleny nebo zakázány +Name[csb]=Pòwòlné klawisze òstałë aktiwòwòné abò deaktiwòwóné +Name[da]=Langsomme taster er aktiveret eller deaktiveret +Name[de]=Langsame Tasten sind aktiviert oder deaktiviert worden +Name[el]=Τα αργά πλήκτρα ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Name[en_GB]=Slow keys has been enabled or disabled +Name[eo]=Malrapidklavoj validiĝis aŭ malvalidiĝis +Name[es]=Las teclas lentas se han activado o desactivado +Name[et]=Aeglased klahvid on keelatud või lubatud +Name[eu]=Tekla motelak gaitu edo desgaitu dira +Name[fi]=Hitaat näppäimet on otettu käyttöön tai poistettu käytöstä +Name[fr]=Les touches lentes ont été activées ou désactivées +Name[fy]=Trage toetsen binne aktivearre of ûntaktivearre +Name[ga]=Cumasaíodh nó díchumasaíodh eochracha malla +Name[gl]=As teclas lentas activáronse ou desactiváronse +Name[gu]=ધીમી કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Name[he]=תגובה איטית של המקשים הופעלה או הופסקה +Name[hi]=धीमी कुंजियों को सक्षम या अक्षम किया गया है +Name[hne]=धीमा कुंजी सक्रिय या अक्रिय हो गे हे +Name[hr]=Spore tipke su omogućene ili onemogućene +Name[hsb]=Pomałe tasty zaswěćene abo hasnjene +Name[hu]=A lassú billentyűk használata átkapcsolva +Name[ia]=Le claves lente ha essite activate o disactivate +Name[id]=Tombol pelan telah diaktifkan atau dinonaktifkan +Name[is]=Slökkt eða kveikt hefur verið á hægum lyklum +Name[it]=Il rallentamento dei tasti è stato attivato o disattivato +Name[ja]=スローキーが有効または無効になりました +Name[kk]=Баяу пернелер рұқсат етілді/етілмеді +Name[km]=គ្រាប់​ចុច​យឺត​​ត្រូវ​បាន​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Name[kn]=ನಿಧಾನ (ಸ್ಲೋ) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=느린 키가 활성화되거나 비활성화됨 +Name[ku]=Bişkojkên Hêdî hatin çalakirin an jî neçalakirin +Name[lt]=Lėti klavišai buvo įgalinti arba išjungti +Name[lv]=Lēnie taustiņi tika ieslēgti vai izslēgti +Name[mk]=„Спори копчиња“ е овозможено или оневозможено +Name[ml]=സ്ലോ കീ പ്രവര്‍ത്തന സജ്ജമലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതമാക്കിയിരിക്കുന്നു +Name[mr]=हळु कार्यरत कि आता कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Name[nb]=Trege taster er blitt slått på eller av +Name[nds]="Langsam Tasten" wöör an- oder utmaakt +Name[ne]=शो कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Name[nl]=Langzame toetsen is geactiveerd of gedeactiveerd +Name[nn]=Trege tastar er no slått på eller av +Name[or]=Slow କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਸਲੋਅ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Name[pl]=Powolne klawisze zostały włączone lub wyłączone +Name[pt]=As teclas lentas foram activadas ou desactivadas +Name[pt_BR]=Teclas lentas foram habilitadas ou desabilitadas +Name[ro]=Taste lente (Slow keys) au fost activate sau dezactivate +Name[ru]=Включены или отключены замедленные клавиши +Name[si]=වේගය අඩු යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Name[sk]=Pomalé klávesy zmenili svoj stav +Name[sl]=Počasne tipke so bile omogočene ali onemogočene +Name[sr]=Спори тастери су укључени или искључени +Name[sr@ijekavian]=Спори тастери су укључени или искључени +Name[sr@ijekavianlatin]=Spori tasteri su uključeni ili isključeni +Name[sr@latin]=Spori tasteri su uključeni ili isključeni +Name[sv]=Långsamma tangenter har aktiverats eller inaktiverats +Name[ta]=Slow keys has been enabled or disabled +Name[te]=స్లో కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Name[tg]=Тугмаҳои суст фаъол ё ғайрифаъол шудаанд +Name[th]=การกดปุ่มพิมพ์ช้าได้ถูกเปิดหรือปิดการทำงาน +Name[tr]=Yavaş tuşlar etkinleştirildi ya da pasifleştirildi +Name[ug]=ئاستا(Slow) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Name[uk]=Було активовано або деактивовано повільні клавіші +Name[wa]=Des londjinnès tapes ont stî metowe en alaedje oudonbén dismetowes +Name[x-test]=xxSlow keys has been enabled or disabledxx +Name[zh_CN]=启用或禁用了筛选键 +Name[zh_TW]=慢速鍵已改變狀態 +Comment=Slow keys has been enabled or disabled +Comment[af]=Stadige sleutels was geaktiveer of gedeaktiveer +Comment[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح البطيئة +Comment[ast]=Les tecles lentes activáronse o desactiváronse +Comment[be@latin]=Pavolnyja klavišy źmianili svajo stanovišča. +Comment[bg]="Бавни" клавиши са включени или изключени +Comment[bs]=Spori tasteri su uključeni ili isključeni +Comment[ca]=Les tecles lentes s'han activat o desactivat +Comment[ca@valencia]=Les tecles lentes s'han activat o desactivat +Comment[cs]=Pomalé klávesy byly povoleny nebo zakázány +Comment[csb]=Pòwòlné klawisze òstałë aktiwòwòné abò deaktiwòwóné +Comment[da]=Langsomme taster er aktiveret eller deaktiveret +Comment[de]=Die Funktion „Langsame Tasten“ ist aktiviert oder deaktiviert worden +Comment[el]=Τα αργά πλήκτρα ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Comment[en_GB]=Slow keys has been enabled or disabled +Comment[eo]=Malrapidklavoj validiĝis aŭ malvalidiĝis +Comment[es]=Las teclas lentas se han activado o desactivado +Comment[et]=Aeglased klahvid on keelatud või lubatud +Comment[eu]=Tekla motelak gaitu edo desgaitu dira +Comment[fi]=Hitaat näppäimet on otettu käyttöön tai poistettu käytöstä +Comment[fr]=Les touches lentes ont été activées ou désactivées +Comment[fy]=Trage toetsen binne aktivearre of ûntaktivearre +Comment[ga]=Cumasaíodh nó díchumasaíodh eochracha malla +Comment[gl]=As teclas lentas foron ou activadas ou desactivadas +Comment[gu]=ધીમી કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Comment[he]=תגובה איטית של המקשים הופעלה או הופסקה +Comment[hi]=धीमी कुंजियों को सक्षम या अक्षम किया गया है +Comment[hne]=धीमा कुंजी सक्छम या अक्छम हो गे हे +Comment[hr]=Spore tipke su omogućene ili onemogućene +Comment[hsb]=Pomałe tasty zaswěćene abo hasnjene +Comment[hu]=A lassú billentyűk használatát ki- vagy bekapcsolták +Comment[ia]=Le claves lente ha essite activate o disactivate +Comment[id]=Tombol pelan telah diaktifkan atau dinonaktifkan +Comment[is]=Slökkt eða kveikt hefur verið á hægum lyklum +Comment[it]=Il rallentamento dei tasti è stato attivato o disattivato +Comment[ja]=スローキーが有効または無効になりました +Comment[kk]=Баяу пернелер рұқсат етілді/етілмеді +Comment[km]=គ្រាប់​ចុច​យឺត​ត្រូវ​បាន​​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Comment[kn]=ನಿಧಾನ (ಸ್ಲೋ) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Comment[ko]=느린 키가 활성화되거나 비활성화됨 +Comment[ku]=Bişkojkên Hêdî hatin çalakirin an jî neçalakirin +Comment[lt]=Lėti klavišai buvo įgalinti arba išjungti +Comment[lv]=Lēnie taustiņi tika ieslēgti vai izslēgti +Comment[mk]=„Спори копчиња“ е овозможено или оневозможено +Comment[ml]=സ്ലോ കീ പ്രവര്‍ത്തന സജ്ജമലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതമാക്കിയിരിക്കുന്നു +Comment[mr]=हळु कार्यरत कि आता कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Comment[nb]=Trege taster er blitt slått på eller av +Comment[nds]="Langsam Tasten" wöör an- oder utmaakt +Comment[ne]=शो कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Comment[nl]=Langzame toetsen is geactiveerd of gedeactiveerd +Comment[nn]=Trege tastar er no slått på eller av +Comment[or]=Slow କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Comment[pa]=ਸਲੋਅ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Comment[pl]=Powolne klawisze zostały włączone lub wyłączone +Comment[pt]=As teclas lentas foram activadas ou desactivadas +Comment[pt_BR]=Teclas lentas foram habilitadas ou desabilitadas +Comment[ro]=Taste lente (Slow keys) au fost activate sau dezactivate +Comment[ru]=Включены или отключены замедленные клавиши +Comment[si]=වේගය අඩු යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Comment[sk]=Pomalé klávesy zmenili svoj stav +Comment[sl]=Počasne tipke so bile omogočene ali onemogočene +Comment[sr]=Спори тастери су укључени или искључени +Comment[sr@ijekavian]=Спори тастери су укључени или искључени +Comment[sr@ijekavianlatin]=Spori tasteri su uključeni ili isključeni +Comment[sr@latin]=Spori tasteri su uključeni ili isključeni +Comment[sv]=Långsamma tangenter har aktiverats eller inaktiverats +Comment[ta]=Slow keys has been enabled or disabled +Comment[te]=స్లో కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Comment[tg]=Тугмаҳои суст фаъол ё ғайрифаъол шудаанд +Comment[th]=การกดปุ่มพิมพ์ช้าได้ถูกเปิดหรือปิดการทำงาน +Comment[tr]=Yavaş tuşlar etkinleştirildi ya da pasifleştirildi +Comment[ug]=ئاستا(Slow) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Comment[uk]=Було активовано або деактивовано повільні клавіші +Comment[wa]=Des londjinnès tapes ont stî metowe en alaedje oudonbén dismetowes +Comment[x-test]=xxSlow keys has been enabled or disabledxx +Comment[zh_CN]=启用或禁用了筛选键 +Comment[zh_TW]=慢速鍵已啟動或關閉。 +Sound=KDE-Sys-Special.ogg +Action=Popup +nopresentation=236 + +[Event/bouncekeys] +Name=Bounce keys has been enabled or disabled +Name[af]=Hopsleutels is geaktiveer of gedeaktiveer +Name[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح المكررة +Name[ast]=Les tecles de rebote activáronse o desactiváronse +Name[bg]="Подскачащи" клавиши са включени или изключени +Name[bs]=Odskačući tasteri su uključeni ili isključeni +Name[ca]=Les tecles de repetició s'han activat o desactivat +Name[ca@valencia]=Les tecles de repetició s'han activat o desactivat +Name[cs]=Zdvojené klávesy byly povoleny nebo zakázány +Name[csb]=Òdbijającé klawisze òstałë aktiwòwòné abò deaktiwòwóné +Name[da]=Elastiske taster er aktiveret eller deaktiveret +Name[de]=Zurückschnellende Tasten sind aktiviert oder deaktiviert worden +Name[el]=Τα πλήκτρα αναπήδησης ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Name[en_GB]=Bounce keys has been enabled or disabled +Name[eo]=Prokrastaj klavoj validiĝis aŭ malvalidiĝis +Name[es]=Se ha activado o desactivado el rebote de teclas +Name[et]=Põrkavad klahvid on keelatud või lubatud +Name[eu]=Errebote-teklak gaitu edo desgaitu dira +Name[fi]=Kimpoavat näppäimet on otettu käyttöön tai poistettu käytöstä +Name[fr]=Les touches non répétées ont été activées ou désactivées +Name[fy]=Stuiterjende toetsen binne aktivearre of ûntaktivearre +Name[ga]=Cumasaíodh nó díchumasaíodh eochracha preabtha +Name[gl]=A anulación temporal de teclas activouse ou desactivouse +Name[gu]=ઉછાળ કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Name[he]=מניעת לחיצה על מספר מקשים בו־זמנית הופעלה או הופסקה +Name[hi]=बाउंस कुंजियों को सक्षम या अक्षम किया गया है +Name[hne]=बाउन्स कुंजी सक्छम या अक्छम हो गे हे +Name[hr]=Obijanje tipki je omogućeno ili onemogućeno +Name[hsb]=Zamkane tasty zaswěćene abo hasnjene +Name[hu]=A visszaugró billentyűk átkapcsolva +Name[ia]=Le claves elastic ha essite activate o disactivate +Name[id]=Tombol pantul telah diaktifkan atau dinonaktifkan +Name[is]=Slökkt eða kveikt hefur verið á skoppandi lyklum +Name[it]=I tasti ravvicinati sono stati abilitati o disattivati +Name[ja]=バウンスキーが有効または無効になりました +Name[kk]=Қалшылға қарсы пернелер рұқсат етілді/етілмеді +Name[km]=គ្រាប់​ចុច​លោត​​ត្រូវ​បាន​​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Name[kn]=ಪುಟಿಯುವ (ಬೌನ್ಸ್) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=튕김 키가 활성화되거나 비활성화됨 +Name[ku]=Bişkojkên Zindî hatin çalakirin an jî neçalakirin +Name[lt]=Tamprūs klavišai buvo įgalinti arba išjungti +Name[lv]=Atlecošie taustiņi tika ieslēgti vai izslēgti +Name[mk]=„Скокачки копчиња“ е овозможено или оневозможено +Name[ml]=ബൌണ്‍സ് കീ പ്രവര്‍ത്തന സജ്ജം അല്ലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതം ആക്കിയിരിക്കുന്നു +Name[mr]=बाउन्स् कि कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Name[nb]=Filtertaster er blitt slått på eller av +Name[nds]="Jumpen Tasten" wöör an- oder utmaakt +Name[ne]=बाउन्स कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Name[nl]=Stuiterende toetsen is geactiveerd of gedeactiveerd +Name[nn]=Filtertastar er no slått på eller av +Name[or]=Bounce କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਬਾਊਂਸ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Name[pl]=Odbijające klawisze zostały włączone lub wyłączone +Name[pt]=As teclas sonoras foram activadas ou desactivadas +Name[pt_BR]=As teclas de repercussão foram ativadas ou desativadas +Name[ro]=Taste săltărețe (Bounce keys) au fost activate sau dezactivate +Name[ru]=Включены или отключены «прыгающие» клавиши +Name[se]=Sillenboallu lea rievdadan stáhtusa +Name[si]=පොළාපැනුම් යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Name[sk]=Bounce klávesy zmenili svoj stav +Name[sl]=Odbijajoče tipke so bile omogočene ali onemogočene +Name[sr]=Одскачући тастери су укључени или искључени +Name[sr@ijekavian]=Одскачући тастери су укључени или искључени +Name[sr@ijekavianlatin]=Odskačući tasteri su uključeni ili isključeni +Name[sr@latin]=Odskačući tasteri su uključeni ili isključeni +Name[sv]=Studsande tangenter har aktiverats eller inaktiverats +Name[ta]=Bounce keys has been enabled or disabled +Name[te]=బౌన్‍స్ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Name[tg]=Тугмаҳои ҷаҳиш фаъол ё ғайрифаъол шудаанд +Name[th]=การกดปุ่มพิมพ์รัวได้ถูกเปิดหรือปิดการทำงาน +Name[tr]=Sıçrama tuşları etkinleştirildi ya da pasifleştirildi +Name[ug]=سەكرىمە(Bounce) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Name[uk]=Було активовано або деактивовано пружні клавіші +Name[vi]=Phím nảy đã được bật hoặc tắt +Name[wa]=Des dimey-eclawåvès tapes ont stî metowe en alaedje oudonbén dismetowes +Name[x-test]=xxBounce keys has been enabled or disabledxx +Name[zh_CN]=启用或禁用了撞击键 +Name[zh_TW]=彈回鍵已改變狀態 +Comment=Bounce keys has been enabled or disabled +Comment[af]=Hop sleutels was geaktiveer of gedeaktiveer +Comment[ar]=تم تفعيل أو إلغاء تفعيل المفاتيح المكررة +Comment[ast]=Les tecles de rebote activáronse o desactiváronse +Comment[bg]="Подскачащи" клавиши са включени или изключени +Comment[bs]=Odskačući tasteri su uključeni ili isključeni +Comment[ca]=Les tecles de repetició s'han activat o desactivat +Comment[ca@valencia]=Les tecles de repetició s'han activat o desactivat +Comment[cs]=Zdvojené klávesy byly povoleny nebo zakázány +Comment[csb]=Òdbijającé klawisze òstałë aktiwòwòné abò deaktiwòwóné +Comment[da]=Elastiske taster er aktiveret eller deaktiveret +Comment[de]=Die Funktion „Zurückschnellende Tasten“ ist aktiviert oder deaktiviert worden +Comment[el]=Τα πλήκτρα αναπήδησης ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Comment[en_GB]=Bounce keys has been enabled or disabled +Comment[eo]=Prokrastaj klavoj validiĝis aŭ malvalidiĝis +Comment[es]=Se ha activado o desactivado el rebote de teclas +Comment[et]=Põrkavad klahvid on keelatud või lubatud +Comment[eu]=Errebote-teklak gaitu edo desgaitu dira +Comment[fi]=Kimpoavat näppäimet on otettu käyttöön tai poistettu käytöstä +Comment[fr]=Les touches non répétées ont été activées ou désactivées +Comment[fy]=Stuiterjende toetsen binne aktivearre of ûntaktivearre +Comment[ga]=Cumasaíodh nó díchumasaíodh eochracha preabtha +Comment[gl]=A anulación temporal de teclas foi ou activada ou desactivada +Comment[gu]=ઉછાળ કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Comment[he]=מניעת לחיצה על מספר מקשים בו־זמנית הופעלה או הופסקה +Comment[hi]=बाउंस कुंजियों को सक्षम या अक्षम किया गया है +Comment[hne]=बाउन्स कुंजी सक्छम या अक्छम हो गे हे +Comment[hr]=Obijanje tipki je omogućeno ili onemogućeno +Comment[hsb]=Zamkane tasty zaswěćene abo hasnjene +Comment[hu]=A visszaugró billentyűk használatát ki- vagy bekapcsolták +Comment[ia]=Le claves elastic ha essite activate o disactivate +Comment[id]=Tombol pantul telah diaktifkan atau dinonaktifkan +Comment[is]=Slökkt eða kveikt hefur verið á skoppandi lyklum +Comment[it]=I tasti ravvicinati sono stati abilitati o disattivati +Comment[ja]=バウンスキーが有効または無効になりました +Comment[kk]=Қалшылға қарсы пернелер рұқсат етілді/етілмеді +Comment[km]=គ្រាប់​ចុច​លោត​​ត្រូវបាន​​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Comment[kn]=ಪುಟಿಯುವ (ಬೌನ್ಸ್) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Comment[ko]=튕김 키가 활성화되거나 비활성화됨 +Comment[ku]=Bişkojkên Zindî hatin çalakirin an jî neçalakirin +Comment[lt]=Tamprūs klavišai buvo įgalinti arba išjungti +Comment[lv]=Atlecošie taustiņi tika ieslēgti vai izslēgti +Comment[mk]=„Скокачки копчиња“ е овозможено или оневозможено +Comment[ml]=ബൌണ്‍സ് കീ പ്രവര്‍ത്തന സജ്ജം അല്ലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതം ആക്കിയിരിക്കുന്നു +Comment[mr]=बाउन्स् कि कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Comment[nb]=Filtertaster er blitt slått på eller av +Comment[nds]="Jumpen Tasten" wöör an- oder utmaakt +Comment[ne]=बाउन्स कुञ्जीहरू सक्षम वा अक्षम बनाइएको छ +Comment[nl]=Stuiterende toetsen is geactiveerd of gedeactiveerd +Comment[nn]=Filtertastar er no slått på eller av +Comment[or]=Bounce କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Comment[pa]=ਬਾਊਂਸ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Comment[pl]=Powolne klawisze zostały włączone lub wyłączone +Comment[pt]=As teclas sonoras foram activadas ou desactivadas +Comment[pt_BR]=As teclas de repercussão foram ativadas ou desativadas +Comment[ro]=Taste săltărețe (Bounce keys) au fost activate sau dezactivate +Comment[ru]=Включены или отключены «прыгающие» клавиши +Comment[se]=Sillenboallu lea rievdadan stáhtusa +Comment[si]=පොළාපැනුම් යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Comment[sk]=Bounce klávesy zmenili svoj stav +Comment[sl]=Odbijajoče tipke so bile omogočene ali onemogočene +Comment[sr]=Одскачући тастери су укључени или искључени +Comment[sr@ijekavian]=Одскачући тастери су укључени или искључени +Comment[sr@ijekavianlatin]=Odskačući tasteri su uključeni ili isključeni +Comment[sr@latin]=Odskačući tasteri su uključeni ili isključeni +Comment[sv]=Studsande tangenter har aktiverats eller inaktiverats +Comment[ta]=Bounce keys has been enabled or disabled +Comment[te]=బౌన్‍స్ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Comment[tg]=Тугмаҳои ҷаҳиш фаъол ё ғайрифаъол шудаанд +Comment[th]=การกดปุ่มพิมพ์รัวได้ถูกเปิดหรือปิดการทำงาน +Comment[tr]=Sıçrama tuşları etkinleştirildi ya da pasifleştirildi +Comment[ug]=سەكرىمە(Bounce) كۇنۇپكىلار ئىناۋەتلىك ياكى چەكلەنگەن +Comment[uk]=Було активовано або деактивовано пружні клавіші +Comment[vi]=Phím nảy đã được bật hoặc tắt +Comment[wa]=Des dimey-eclawåvès tapes ont stî metowes en alaejde oudonbén essoctêyes +Comment[x-test]=xxBounce keys has been enabled or disabledxx +Comment[zh_CN]=启用或禁用了撞击键 +Comment[zh_TW]=彈回鍵已啟動或關閉。 +Sound=KDE-Sys-Special.ogg +Action=PassivePopup +nopresentation=236 + +[Event/mousekeys] +Name=Mouse keys has been enabled or disabled +Name[af]=Muis sleutels was geaktiveer of gedeaktiveer +Name[ar]=تم تفعيل أو إلغاء تفعيل فأرة لوحة المفاتيح +Name[ast]=Tecles de mur activáronse o desactiváronse +Name[be@latin]=Klavišy kiravańnia kursoram źmianili svajo stanovišča +Name[bg]=Клавишите за управление на курсора са включени или изключени +Name[bs]=Miš‑tasteri su uključeni ili isključeni +Name[ca]=Les tecles del ratolí s'han activat o desactivat +Name[ca@valencia]=Les tecles del ratolí s'han activat o desactivat +Name[cs]=Klávesy myší byly povoleny nebo zakázány +Name[csb]=Knąpë mëszë òstałë aktiwòwòné abò deaktiwòwóné +Name[da]=Musetaster er aktiveret eller deaktiveret +Name[de]=Maustasten sind aktiviert oder deaktiviert worden +Name[el]=Τα πλήκτρα ποντικιού ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Name[en_GB]=Mouse keys has been enabled or disabled +Name[eo]=Musklavoj validiĝis aŭ malvalidiĝis +Name[es]=Se han activado o desactivado los botones del ratón +Name[et]=Hiire klahvid on keelatud või lubatud +Name[eu]=Saguaren botoiak gaitu edo desgaitu dira +Name[fi]=Hiiren näppäimet on otettu käyttöön tai poistettu käytöstä +Name[fr]=Les touches gérant la souris ont été activées ou désactivées +Name[fy]=Mûstoetsen binne aktivearre of ûntaktivearre +Name[ga]=Cumasaíodh nó díchumasaíodh eochracha luiche +Name[gl]=O control do rato co teclado activouse ou desactivouse +Name[gu]=માઉસ કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Name[he]=חיקוי כפתורי העכבר הופעל או הופסק +Name[hi]=माउस कुंजियों को सक्षम या अक्षम किया गया है +Name[hne]=मुसुवा कुंजी सच्छम या अच्छम हो गिस +Name[hr]=Mišolike tipke su omogućene ili onemogućene +Name[hsb]=Myšace tasty zaswěćene abo hasnjene +Name[hu]=Az egérmozgató billentyűk átkapcsolva +Name[ia]=Le claves de mus ha essite activate o disactivate +Name[id]=Tombol tetikus telah diaktifkan atau dinonaktifkan +Name[is]=Slökkt eða kveikt hefur verið á músarlyklum +Name[it]=Il mouse da tastiera è stato attivato o disattivato +Name[ja]=マウスキーが有効または無効になりました +Name[kk]=Тышқан пернелер рұқсат етілді/етілмеді +Name[km]=គ្រាប់​ចុច​កណ្ដុរ​ត្រូវ​បាន​​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Name[kn]=ಮೂಷಕ (ಮೌಸ್) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Name[ko]=마우스 키가 활성화되거나 비활성화됨 +Name[ku]=Bişkojkên Mişkî hatin çalakirin an jî neçalakirin +Name[lt]=Pelės klavišai buvo įgalinti arba išjungti +Name[lv]=Peles taustiņi tika ieslēgti vai izslēgti +Name[mk]=„Копчиња на глушецот“ е овозможено или оневозможено +Name[ml]=മൌസ് കീ പ്രവര്‍ത്തന സജ്ജം അല്ലെങ്കില്‍ പ്രവര്‍ത്തന രഹിതം ആക്കിയിരിക്കുന്നു +Name[mr]=माऊस कि कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Name[nb]=Musetaster er blitt slått på eller av +Name[nds]="Muustasten" wöör an- oder utmaakt +Name[ne]=माउस कुञ्जी सक्षम वा अक्षम बानइएको छ +Name[nl]=Muistoetsen is geactiveerd of gedeactiveerd +Name[nn]=Musetastar er no slått på eller av +Name[or]=ମାଉସ କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Name[pa]=ਮਾਊਸ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Name[pl]=Klawisze myszy zostały włączone lub wyłączone +Name[pt]=As teclas do rato foram activadas ou desactivadas +Name[pt_BR]=Teclas de mouse foram habilitadas ou desabilitadas +Name[ro]=Taste de maus au fost activate sau dezactivate +Name[ru]=Нажаты или отжаты клавиши мыши +Name[se]=Sáhppánboalut leat rievdadan stáhtusa +Name[si]=මවුස යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Name[sk]=Klávesy myši zmenili svoj stav +Name[sl]=Miškine tipke so bile omogočene ali onemogočene +Name[sr]=Миш‑тастери су укључени или искључени +Name[sr@ijekavian]=Миш‑тастери су укључени или искључени +Name[sr@ijekavianlatin]=Miš‑tasteri su uključeni ili isključeni +Name[sr@latin]=Miš‑tasteri su uključeni ili isključeni +Name[sv]=Mustangenter har aktiverats eller inaktiverats +Name[ta]=Mouse keys has been enabled or disabled +Name[te]=మౌస్ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Name[tg]=Тугмаҳои муш фаъол ё ғайрифаъол шудаанд +Name[th]=การจำลองเมาส์ด้วยแป้นพิมพ์ได้ถูกเปิดหรือปิดการทำงาน +Name[tr]=Fare tuşları etkinleştirildi ya da pasifleştirildi +Name[ug]=چاشقىنەك كۇنۇپكىلىرى ئىناۋەتلىك ياكى چەكلەنگەن +Name[uk]=Було активовано або деактивовано клавіші мишки +Name[wa]=Des tapes di soris ont stî metowe en alaedje oudonbén essoctêyes +Name[x-test]=xxMouse keys has been enabled or disabledxx +Name[zh_CN]=启用或禁用了鼠标键 +Name[zh_TW]=滑鼠鍵已改變狀態 +Comment=Mouse keys has been enabled or disabled +Comment[af]=Muis sleutels was geaktiveer of gedeaktiveer +Comment[ar]=تم تفعيل أو إلغاء تفعيل فأرة لوحة المفاتيح +Comment[ast]=Tecles de mur activáronse o desactiváronse +Comment[be@latin]=Klavišy kiravańnia kursoram źmianili svajo stanovišča +Comment[bg]=Клавишите за управление на курсора са включени или изключени +Comment[bs]=Miš‑tasteri su uključeni ili isključeni +Comment[ca]=Les tecles del ratolí s'han activat o desactivat +Comment[ca@valencia]=Les tecles del ratolí s'han activat o desactivat +Comment[cs]=Klávesy myší byly povoleny nebo zakázány +Comment[csb]=Knąpë mëszë òstałë aktiwòwòné abò deaktiwòwóné +Comment[da]=Musetaster er aktiveret eller deaktiveret +Comment[de]=Die Funktion „Maustasten“ ist aktiviert oder deaktiviert worden +Comment[el]=Τα πλήκτρα ποντικιού ενεργοποιήθηκαν ή απενεργοποιήθηκαν +Comment[en_GB]=Mouse keys has been enabled or disabled +Comment[eo]=Musklavoj validiĝis aŭ malvalidiĝis +Comment[es]=Se han activado o desactivado los botones del ratón +Comment[et]=Hiire klahvid on keelatud või lubatud +Comment[eu]=Saguaren botoiak gaitu edo desgaitu dira +Comment[fi]=Hiiren näppäimet on otettu käyttöön tai poistettu käytöstä +Comment[fr]=Les touches gérant la souris ont été activées ou désactivées +Comment[fy]=Mûstoetsen binne aktivearre of ûntaktivearre +Comment[ga]=Cumasaíodh nó díchumasaíodh eochracha luiche +Comment[gl]=O control do rato co teclado foi ou activado ou desactivado +Comment[gu]=માઉસ કળો સક્રિય અથવા નિષ્ક્રિય કરવામાં આવી છે +Comment[he]=חיקוי כפתורי העכבר הופעל או הופסק +Comment[hi]=माउस कुंजियों को सक्षम या अक्षम किया गया है +Comment[hne]=मुसुवा कुंजी सच्छम या अच्छम हो गिस +Comment[hr]=Mišolike tipke su omogućene ili onemogućene +Comment[hsb]=Myšace tasty zaswěćene abo hasnjene +Comment[hu]=Az egérmozgató billentyűk használatát ki- vagy bekapcsolták +Comment[ia]=Le claves de mus ha essite activate o disactivate +Comment[id]=Tombol tetikus telah diaktifkan atau dinonaktifkan +Comment[is]=Slökkt eða kveikt hefur verið á músarlyklum +Comment[it]=Il mouse da tastiera è stato attivato o disattivato +Comment[ja]=マウスキーが有効または無効になりました +Comment[kk]=Тышқан пернелер рұқсат етілді/етілмеді +Comment[km]=គ្រាប់​ចុច​កណ្ដុរ​ត្រូវ​បាន​​​អនុញ្ញាត ឬ​មិន​អនុញ្ញាត +Comment[kn]=ಮೂಷಕ (ಮೌಸ್) ಕೀಲಿಯನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ +Comment[ko]=마우스 키가 활성화되거나 비활성화됨 +Comment[ku]=Bişkojkên Mişkî hatin çalakirin an jî neçalakirin +Comment[lt]=Pelės mygtukai buvo įgalinti arba išjungti +Comment[lv]=Peles taustiņi tika ieslēgti vai izslēgti +Comment[mk]=„Копчиња на глушецот“ е овозможено или оневозможено +Comment[ml]=മൌസ് കീ പ്രവര്‍ത്തന സജ്ജം അല്ല്ലെങ്കില്‍ പ്രവര്‍ത്തനരഹിതം ആക്കിയിരിക്കുന്നു +Comment[mr]=माऊस कि कार्यान्वित किंवा अकार्यान्वित केली गेली आहे +Comment[nb]=Musetaster er blitt slått på eller av +Comment[nds]="Muustasten" wöör an- oder utmaakt +Comment[ne]=माउस कुञ्जी सक्षम वा अक्षम बनाइएको छ +Comment[nl]=Muistoetsen is geactiveerd of gedeactiveerd +Comment[nn]=Musetastar er no slått på eller av +Comment[or]=ମାଉସ କିଗୁଡ଼ିକୁ ସକ୍ରିୟ ଅଥବା ନିଷ୍କ୍ରିୟ କରାଯାଇଛି +Comment[pa]=ਮਾਊਸ ਸਵਿੱਚਾਂ ਯੋਗ ਜਾਂ ਆਯੋਗ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ +Comment[pl]=Klawisze myszy zostały włączone lub wyłączone +Comment[pt]=As teclas do rato foram activadas ou desactivadas +Comment[pt_BR]=Teclas de mouse foram habilitadas ou desabilitadas +Comment[ro]=Taste de maus au fost activate sau dezactivate +Comment[ru]=Нажаты или отжаты клавиши мыши +Comment[se]=Sáhppánboalut leat rievdadan stáhtusa +Comment[si]=මවුස යතුරු සක්‍රීය හෝ අක්‍රීය කර ඇත +Comment[sk]=Klávesy myši zmenili svoj stav +Comment[sl]=Miškine tipke so bile omogočene ali onemogočene +Comment[sr]=Миш‑тастери су укључени или искључени +Comment[sr@ijekavian]=Миш‑тастери су укључени или искључени +Comment[sr@ijekavianlatin]=Miš‑tasteri su uključeni ili isključeni +Comment[sr@latin]=Miš‑tasteri su uključeni ili isključeni +Comment[sv]=Mustangenter har aktiverats eller inaktiverats +Comment[ta]=Mouse keys has been enabled or disabled +Comment[te]=మౌస్ కీలు చేతనంకాబడినవి లేదా అచేతనంకాబడినవి +Comment[tg]=Тугмаҳои муш фаъол ё ғайрифаъол шудаанд +Comment[th]=การจำลองเมาส์ด้วยแป้นพิมพ์ได้ถูกเปิดหรือปิดการทำงาน +Comment[tr]=Fare tuşları etkinleştirildi ya da pasifleştirildi +Comment[ug]=چاشقىنەك كۇنۇپكىلىرى ئىناۋەتلىك ياكى چەكلەنگەن +Comment[uk]=Було активовано або деактивовано клавіші мишки +Comment[wa]=Des tapes di soris ont stî metowe en alaedje oudonbén essoctêyes +Comment[x-test]=xxMouse keys has been enabled or disabledxx +Comment[zh_CN]=启用或禁用了鼠标键 +Comment[zh_TW]=滑鼠鍵已啟動或關閉。 +Sound=KDE-Sys-Special.ogg +Action=PassivePopup +nopresentation=236 diff --git a/kcms/access/kcmaccess.cpp b/kcms/access/kcmaccess.cpp new file mode 100644 index 0000000000..2ffafe7d5a --- /dev/null +++ b/kcms/access/kcmaccess.cpp @@ -0,0 +1,786 @@ +/** + * kcmaccess.cpp + * + * Copyright (c) 2000 Matthias H�zer-Klpfel + * + */ + +#include "kcmaccess.h" + +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +//Added by qt3to4: +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define XK_MISCELLANY +#define XK_XKB_KEYS +#include +#include + +K_PLUGIN_FACTORY(KAccessConfigFactory, registerPlugin();) +K_EXPORT_PLUGIN(KAccessConfigFactory("kcmaccess")) + +QString mouseKeysShortcut (Display *display) { + // Calculate the keycode + KeySym sym = XK_MouseKeys_Enable; + KeyCode code = XKeysymToKeycode(display, sym); + if (code == 0) { + sym = XK_Pointer_EnableKeys; + code = XKeysymToKeycode(display, sym); + if (code == 0) + return ""; // No shortcut available? + } + + // Calculate the modifiers by searching the keysym in the X keyboard mapping + XkbDescPtr xkbdesc = XkbGetMap(display, XkbKeyTypesMask | XkbKeySymsMask, XkbUseCoreKbd); + if (!xkbdesc) + return ""; // Failed to obtain the mapping from server + + bool found = false; + unsigned char modifiers = 0; + int groups = XkbKeyNumGroups(xkbdesc, code); + for (int grp = 0; grp < groups && !found; grp++) + { + int levels = XkbKeyGroupWidth(xkbdesc, code, grp); + for (int level = 0; level < levels && !found; level++) + { + if (sym == XkbKeySymEntry(xkbdesc, code, level, grp)) + { + // keysym found => determine modifiers + int typeIdx = xkbdesc->map->key_sym_map[code].kt_index[grp]; + XkbKeyTypePtr type = &(xkbdesc->map->types[typeIdx]); + for (int i = 0; i < type->map_count && !found; i++) + { + if (type->map[i].active && (type->map[i].level == level)) + { + modifiers = type->map[i].mods.mask; + found = true; + } + } + } + } + } + XkbFreeClientMap (xkbdesc, 0, true); + + if (!found) + return ""; // Somehow the keycode -> keysym mapping is flawed + + XEvent ev; + ev.type = KeyPress; + ev.xkey.display = display; + ev.xkey.keycode = code; + ev.xkey.state = 0; + int key; + KKeyServer::xEventToQt(&ev, &key); + QString keyname = QKeySequence(key).toString(); + + unsigned int AltMask = KKeyServer::modXAlt(); + unsigned int WinMask = KKeyServer::modXMeta(); + unsigned int NumMask = KKeyServer::modXNumLock(); + unsigned int ScrollMask= KKeyServer::modXScrollLock(); + + unsigned int MetaMask = XkbKeysymToModifiers (display, XK_Meta_L); + unsigned int SuperMask = XkbKeysymToModifiers (display, XK_Super_L); + unsigned int HyperMask = XkbKeysymToModifiers (display, XK_Hyper_L); + unsigned int AltGrMask = XkbKeysymToModifiers (display, XK_Mode_switch) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Shift) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Latch) + | XkbKeysymToModifiers (display, XK_ISO_Level3_Lock); + + unsigned int mods = ShiftMask | ControlMask | AltMask | WinMask + | LockMask | NumMask | ScrollMask; + + AltGrMask &= ~mods; + MetaMask &= ~(mods | AltGrMask); + SuperMask &= ~(mods | AltGrMask | MetaMask); + HyperMask &= ~(mods | AltGrMask | MetaMask | SuperMask); + + if ((modifiers & AltGrMask) != 0) + keyname = i18n("AltGraph") + '+' + keyname; + if ((modifiers & HyperMask) != 0) + keyname = i18n("Hyper") + '+' + keyname; + if ((modifiers & SuperMask) != 0) + keyname = i18n("Super") + '+' + keyname; + if ((modifiers & WinMask) != 0) + keyname = QKeySequence(Qt::META).toString() + '+' + keyname; + if ((modifiers & AltMask) != 0) + keyname = QKeySequence(Qt::ALT).toString() + '+' + keyname; + if ((modifiers & ControlMask) != 0) + keyname = QKeySequence(Qt::CTRL).toString() + '+' + keyname; + if ((modifiers & ShiftMask) != 0) + keyname = QKeySequence(Qt::SHIFT).toString() + '+' + keyname; + + QString result; + if ((modifiers & ScrollMask) != 0) + if ((modifiers & LockMask) != 0) + if ((modifiers & NumMask) != 0) + result = i18n("Press %1 while NumLock, CapsLock and ScrollLock are active", keyname); + else + result = i18n("Press %1 while CapsLock and ScrollLock are active", keyname); + else if ((modifiers & NumMask) != 0) + result = i18n("Press %1 while NumLock and ScrollLock are active", keyname); + else + result = i18n("Press %1 while ScrollLock is active", keyname); + else if ((modifiers & LockMask) != 0) + if ((modifiers & NumMask) != 0) + result = i18n("Press %1 while NumLock and CapsLock are active", keyname); + else + result = i18n("Press %1 while CapsLock is active", keyname); + else if ((modifiers & NumMask) != 0) + result = i18n("Press %1 while NumLock is active", keyname); + else + result = i18n("Press %1", keyname); + + return result; +} + +KAccessConfig::KAccessConfig(QWidget *parent, const QVariantList& args) + : KCModule(parent, args) +{ + + KAboutData *about = + new KAboutData(I18N_NOOP("kaccess"), QString(), i18n("KDE Accessibility Tool"), + QString(), QString(), KAboutData::License_GPL, + i18n("(c) 2000, Matthias Hoelzer-Kluepfel")); + + about->addAuthor(i18n("Matthias Hoelzer-Kluepfel"), i18n("Author") , QStringLiteral("hoelzer@kde.org")); + + setAboutData( about ); + + QVBoxLayout *main = new QVBoxLayout(this); + main->setMargin(0); + QTabWidget *tab = new QTabWidget(this); + main->addWidget(tab); + + // bell settings --------------------------------------- + QWidget *bell = new QWidget(this); + + QVBoxLayout *vbox = new QVBoxLayout(bell); + + QGroupBox *grp = new QGroupBox(i18n("Audible Bell"), bell); + QHBoxLayout *layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + QVBoxLayout *vvbox = new QVBoxLayout(); + layout->addLayout( vvbox ); + + systemBell = new QCheckBox(i18n("Use &system bell"), grp); + vvbox->addWidget(systemBell); + customBell = new QCheckBox(i18n("Us&e customized bell"), grp); + vvbox->addWidget(customBell); + systemBell->setWhatsThis( i18n("If this option is checked, the default system bell will be used. See the" + " \"System Bell\" control module for how to customize the system bell." + " Normally, this is just a \"beep\".") ); + customBell->setWhatsThis( i18n("

    Check this option if you want to use a customized bell, playing" + " a sound file. If you do this, you will probably want to turn off the system bell.

    Please note" + " that on slow machines this may cause a \"lag\" between the event causing the bell and the sound being played.

    ") ); + + QHBoxLayout *hbox = new QHBoxLayout(); + vvbox->addLayout( hbox ); + hbox->addSpacing(24); + soundEdit = new QLineEdit(grp); + soundLabel = new QLabel(i18n("Sound &to play:"), grp); + soundLabel->setBuddy(soundEdit); + hbox->addWidget(soundLabel); + hbox->addWidget(soundEdit); + soundButton = new QPushButton(i18n("Browse..."), grp); + hbox->addWidget(soundButton); + QString wtstr = i18n("If the option \"Use customized bell\" is enabled, you can choose a sound file here." + " Click \"Browse...\" to choose a sound file using the file dialog."); + soundEdit->setWhatsThis( wtstr ); + soundLabel->setWhatsThis( wtstr ); + soundButton->setWhatsThis( wtstr ); + + connect(soundButton, SIGNAL(clicked()), this, SLOT(selectSound())); + + connect(customBell, SIGNAL(clicked()), this, SLOT(checkAccess())); + + connect(systemBell, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(customBell, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(soundEdit, SIGNAL(textChanged(QString)), this, SLOT(configChanged())); + + // ----------------------------------------------------- + + // visible bell ---------------------------------------- + grp = new QGroupBox(i18n("Visible Bell"), bell); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout( vvbox ); + + visibleBell = new QCheckBox(i18n("&Use visible bell"), grp); + vvbox->addWidget(visibleBell); + visibleBell->setWhatsThis( i18n("This option will turn on the \"visible bell\", i.e. a visible" + " notification shown every time that normally just a bell would occur. This is especially useful" + " for deaf people.") ); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + invertScreen = new QRadioButton(i18n("I&nvert screen"), grp); + hbox->addWidget(invertScreen); + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + invertScreen->setWhatsThis( i18n("All screen colors will be inverted for the amount of time specified below.") ); + hbox->addSpacing(24); + flashScreen = new QRadioButton(i18n("F&lash screen"), grp); + hbox->addWidget(flashScreen); + flashScreen->setWhatsThis( i18n("The screen will turn to a custom color for the amount of time specified below.") ); + hbox->addSpacing(12); + colorButton = new KColorButton(grp); + colorButton->setFixedWidth(colorButton->sizeHint().height()*2); + hbox->addWidget(colorButton); + hbox->addStretch(); + colorButton->setWhatsThis( i18n("Click here to choose the color used for the \"flash screen\" visible bell.") ); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + + durationSlider = new KDoubleNumInput(grp); + durationSlider->setRange(100, 2000, 100); + durationSlider->setExponentRatio(2); + durationSlider->setDecimals(0); + durationSlider->setLabel(i18n("Duration:")); + durationSlider->setSuffix(i18n(" msec")); + hbox->addWidget(durationSlider); + durationSlider->setWhatsThis( i18n("Here you can customize the duration of the \"visible bell\" effect being shown.") ); + + connect(invertScreen, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(flashScreen, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(visibleBell, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(visibleBell, SIGNAL(clicked()), this, SLOT(checkAccess())); + connect(colorButton, SIGNAL(clicked()), this, SLOT(changeFlashScreenColor())); + + connect(invertScreen, SIGNAL(clicked()), this, SLOT(invertClicked())); + connect(flashScreen, SIGNAL(clicked()), this, SLOT(flashClicked())); + + connect(durationSlider, SIGNAL(valueChanged(double)), this, SLOT(configChanged())); + + vbox->addStretch(); + + // ----------------------------------------------------- + + tab->addTab(bell, i18n("&Bell")); + + + // modifier key settings ------------------------------- + QWidget *modifiers = new QWidget(this); + + vbox = new QVBoxLayout(modifiers); + + grp = new QGroupBox(i18n("S&ticky Keys"), modifiers); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout(vvbox); + + stickyKeys = new QCheckBox(i18n("Use &sticky keys"), grp); + vvbox->addWidget(stickyKeys); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + stickyKeysLock = new QCheckBox(i18n("&Lock sticky keys"), grp); + hbox->addWidget(stickyKeysLock); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + stickyKeysAutoOff = new QCheckBox(i18n("Turn sticky keys off when two keys are pressed simultaneously"), grp); + hbox->addWidget(stickyKeysAutoOff); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + stickyKeysBeep = new QCheckBox(i18n("Use system bell whenever a modifier gets latched, locked or unlocked"), grp); + hbox->addWidget(stickyKeysBeep); + + grp = new QGroupBox(i18n("Locking Keys"), modifiers); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout(vvbox); + + toggleKeysBeep = new QCheckBox(i18n("Use system bell whenever a locking key gets activated or deactivated"), grp); + vvbox->addWidget(toggleKeysBeep); + + kNotifyModifiers = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a modifier or locking key changes its state"), grp); + vvbox->addWidget(kNotifyModifiers); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addStretch(1); + kNotifyModifiersButton = new QPushButton(i18n("Configure &Notifications..."), grp); + kNotifyModifiersButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + hbox->addWidget(kNotifyModifiersButton); + + connect(stickyKeys, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(stickyKeysLock, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(stickyKeysAutoOff, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(stickyKeys, SIGNAL(clicked()), this, SLOT(checkAccess())); + + connect(stickyKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(toggleKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(checkAccess())); + connect(kNotifyModifiersButton, SIGNAL(clicked()), this, SLOT(configureKNotify())); + + vbox->addStretch(); + + tab->addTab(modifiers, i18n("&Modifier Keys")); + + // key filter settings --------------------------------- + QWidget *filters = new QWidget(this); + + vbox = new QVBoxLayout(filters); + grp = new QGroupBox(i18n("Slo&w Keys"), filters); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout(vvbox); + + slowKeys = new QCheckBox(i18n("&Use slow keys"), grp); + vvbox->addWidget(slowKeys); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + slowKeysDelay = new KDoubleNumInput(grp); + slowKeysDelay->setRange(50, 10000, 100); + slowKeysDelay->setExponentRatio(2); + slowKeysDelay->setDecimals(0); + slowKeysDelay->setSuffix(i18n(" msec")); + slowKeysDelay->setLabel(i18n("Acceptance dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); + hbox->addWidget(slowKeysDelay); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + slowKeysPressBeep = new QCheckBox(i18n("&Use system bell whenever a key is pressed"), grp); + hbox->addWidget(slowKeysPressBeep); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + slowKeysAcceptBeep = new QCheckBox(i18n("&Use system bell whenever a key is accepted"), grp); + hbox->addWidget(slowKeysAcceptBeep); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + slowKeysRejectBeep = new QCheckBox(i18n("&Use system bell whenever a key is rejected"), grp); + hbox->addWidget(slowKeysRejectBeep); + + grp = new QGroupBox(i18n("Bounce Keys"), filters); + layout= new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout( vvbox ); + + bounceKeys = new QCheckBox(i18n("Use bou&nce keys"), grp); + vvbox->addWidget(bounceKeys); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + bounceKeysDelay = new KDoubleNumInput(grp); + bounceKeysDelay->setRange(100, 5000, 100); + bounceKeysDelay->setExponentRatio(2); + bounceKeysDelay->setDecimals(0); + bounceKeysDelay->setSuffix(i18n(" msec")); + bounceKeysDelay->setLabel(i18n("D&ebounce time:"), Qt::AlignVCenter|Qt::AlignLeft);; + hbox->addWidget(bounceKeysDelay); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + bounceKeysRejectBeep = new QCheckBox(i18n("Use the system bell whenever a key is rejected"), grp); + hbox->addWidget(bounceKeysRejectBeep); + + connect(slowKeysDelay, SIGNAL(valueChanged(double)), this, SLOT(configChanged())); + connect(slowKeys, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(slowKeys, SIGNAL(clicked()), this, SLOT(checkAccess())); + + connect(slowKeysPressBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(slowKeysAcceptBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(slowKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + + connect(bounceKeysDelay, SIGNAL(valueChanged(double)), this, SLOT(configChanged())); + connect(bounceKeys, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(bounceKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(bounceKeys, SIGNAL(clicked()), this, SLOT(checkAccess())); + + vbox->addStretch(); + + tab->addTab(filters, i18n("&Keyboard Filters")); + + // gestures -------------------------------------------- + QWidget *features = new QWidget(this); + + vbox = new QVBoxLayout(features); + + grp = new QGroupBox(i18n("Activation Gestures"), features); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout( vvbox ); + + gestures = new QCheckBox(i18n("Use gestures for activating sticky keys and slow keys"), grp); + vvbox->addWidget(gestures); + QString shortcut = mouseKeysShortcut(QX11Info::display()); + if (shortcut.isEmpty()) + gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n" + "Sticky keys: Press Shift key 5 consecutive times\n" + "Slow keys: Hold down Shift for 8 seconds")); + else + gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n" + "Mouse Keys: %1\n" + "Sticky keys: Press Shift key 5 consecutive times\n" + "Slow keys: Hold down Shift for 8 seconds", shortcut)); + + timeout = new QCheckBox(i18n("Turn sticky keys and slow keys off after a certain period of inactivity."), grp); + vvbox->addWidget(timeout); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addSpacing(24); + timeoutDelay = new KIntNumInput(grp); + timeoutDelay->setSuffix(i18n(" min")); + timeoutDelay->setRange(1, 30, 4); + timeoutDelay->setLabel(i18n("Timeout:"), Qt::AlignVCenter|Qt::AlignLeft);; + hbox->addWidget(timeoutDelay); + + grp = new QGroupBox(i18n("Notification"), features); + layout = new QHBoxLayout; + grp->setLayout(layout); + vbox->addWidget(grp); + + vvbox = new QVBoxLayout(); + layout->addLayout(vvbox); + + accessxBeep = new QCheckBox(i18n("Use the system bell whenever a gesture is used to turn an accessibility feature on or off"), grp); + vvbox->addWidget(accessxBeep); + + gestureConfirmation = new QCheckBox(i18n("Show a confirmation dialog whenever a keyboard accessibility feature is turned on or off"), grp); + vvbox->addWidget(gestureConfirmation); + gestureConfirmation->setWhatsThis( i18n("If this option is checked, KDE will show a confirmation dialog whenever a keyboard accessibility feature is turned on or off.\nEnsure you know what you are doing if you uncheck it, as the keyboard accessibility settings will then always be applied without confirmation.") ); + + kNotifyAccessX = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a keyboard accessibility feature is turned on or off"), grp); + vvbox->addWidget(kNotifyAccessX); + + hbox = new QHBoxLayout(); + vvbox->addLayout(hbox); + hbox->addStretch(1); + kNotifyAccessXButton = new QPushButton(i18n("Configure &Notifications..."), grp); + kNotifyAccessXButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + hbox->addWidget(kNotifyAccessXButton); + + connect(gestures, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(timeout, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(timeout, SIGNAL(clicked()), this, SLOT(checkAccess())); + connect(timeoutDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged())); + connect(accessxBeep, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(gestureConfirmation, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(configChanged())); + connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(checkAccess())); + connect(kNotifyAccessXButton, SIGNAL(clicked()), this, SLOT(configureKNotify())); + + vbox->addStretch(); + + tab->addTab(features, i18n("Activation Gestures")); +} + + +KAccessConfig::~KAccessConfig() +{ +} + +void KAccessConfig::configureKNotify() +{ + KNotifyConfigWidget::configure (this, "kaccess"); +} + +void KAccessConfig::changeFlashScreenColor() +{ + invertScreen->setChecked(false); + flashScreen->setChecked(true); + configChanged(); +} + +void KAccessConfig::selectSound() +{ + QStringList list = KGlobal::dirs()->findDirs("sound", ""); + QString start; + if (list.count()>0) + start = list[0]; + QString fname = QFileDialog::getOpenFileName(this, QString(), start); + if (!fname.isEmpty()) + soundEdit->setText(fname); +} + + +void KAccessConfig::configChanged() +{ + emit changed(true); +} + + +void KAccessConfig::load() +{ + KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell"); + + systemBell->setChecked(cg.readEntry("SystemBell", true)); + customBell->setChecked(cg.readEntry("ArtsBell", false)); + soundEdit->setText(cg.readPathEntry("ArtsBellFile", QString())); + + visibleBell->setChecked(cg.readEntry("VisibleBell", false)); + invertScreen->setChecked(cg.readEntry("VisibleBellInvert", true)); + flashScreen->setChecked(!invertScreen->isChecked()); + colorButton->setColor(cg.readEntry("VisibleBellColor", QColor(Qt::red))); + + durationSlider->setValue(cg.readEntry("VisibleBellPause", 500)); + + KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard"); + + stickyKeys->setChecked(keyboardGroup.readEntry("StickyKeys", false)); + stickyKeysLock->setChecked(keyboardGroup.readEntry("StickyKeysLatch", true)); + stickyKeysAutoOff->setChecked(keyboardGroup.readEntry("StickyKeysAutoOff", false)); + stickyKeysBeep->setChecked(keyboardGroup.readEntry("StickyKeysBeep", true)); + toggleKeysBeep->setChecked(keyboardGroup.readEntry("ToggleKeysBeep", false)); + kNotifyModifiers->setChecked(keyboardGroup.readEntry("kNotifyModifiers", false)); + + slowKeys->setChecked(keyboardGroup.readEntry("SlowKeys", false)); + slowKeysDelay->setValue(keyboardGroup.readEntry("SlowKeysDelay", 500)); + slowKeysPressBeep->setChecked(keyboardGroup.readEntry("SlowKeysPressBeep", true)); + slowKeysAcceptBeep->setChecked(keyboardGroup.readEntry("SlowKeysAcceptBeep", true)); + slowKeysRejectBeep->setChecked(keyboardGroup.readEntry("SlowKeysRejectBeep", true)); + + bounceKeys->setChecked(keyboardGroup.readEntry("BounceKeys", false)); + bounceKeysDelay->setValue(keyboardGroup.readEntry("BounceKeysDelay", 500)); + bounceKeysRejectBeep->setChecked(keyboardGroup.readEntry("BounceKeysRejectBeep", true)); + + gestures->setChecked(keyboardGroup.readEntry("Gestures", false)); + timeout->setChecked(keyboardGroup.readEntry("AccessXTimeout", false)); + timeoutDelay->setValue(keyboardGroup.readEntry("AccessXTimeoutDelay", 30)); + + accessxBeep->setChecked(keyboardGroup.readEntry("AccessXBeep", true)); + gestureConfirmation->setChecked(keyboardGroup.readEntry("GestureConfirmation", false)); + kNotifyAccessX->setChecked(keyboardGroup.readEntry("kNotifyAccessX", false)); + + checkAccess(); + + emit changed(false); +} + + +void KAccessConfig::save() +{ + KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell"); + + cg.writeEntry("SystemBell", systemBell->isChecked()); + cg.writeEntry("ArtsBell", customBell->isChecked()); + cg.writePathEntry("ArtsBellFile", soundEdit->text()); + + cg.writeEntry("VisibleBell", visibleBell->isChecked()); + cg.writeEntry("VisibleBellInvert", invertScreen->isChecked()); + cg.writeEntry("VisibleBellColor", colorButton->color()); + + cg.writeEntry("VisibleBellPause", durationSlider->value()); + + KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard"); + + keyboardGroup.writeEntry("StickyKeys", stickyKeys->isChecked()); + keyboardGroup.writeEntry("StickyKeysLatch", stickyKeysLock->isChecked()); + keyboardGroup.writeEntry("StickyKeysAutoOff", stickyKeysAutoOff->isChecked()); + keyboardGroup.writeEntry("StickyKeysBeep", stickyKeysBeep->isChecked()); + keyboardGroup.writeEntry("ToggleKeysBeep", toggleKeysBeep->isChecked()); + keyboardGroup.writeEntry("kNotifyModifiers", kNotifyModifiers->isChecked()); + + keyboardGroup.writeEntry("SlowKeys", slowKeys->isChecked()); + keyboardGroup.writeEntry("SlowKeysDelay", slowKeysDelay->value()); + keyboardGroup.writeEntry("SlowKeysPressBeep", slowKeysPressBeep->isChecked()); + keyboardGroup.writeEntry("SlowKeysAcceptBeep", slowKeysAcceptBeep->isChecked()); + keyboardGroup.writeEntry("SlowKeysRejectBeep", slowKeysRejectBeep->isChecked()); + + + keyboardGroup.writeEntry("BounceKeys", bounceKeys->isChecked()); + keyboardGroup.writeEntry("BounceKeysDelay", bounceKeysDelay->value()); + keyboardGroup.writeEntry("BounceKeysRejectBeep", bounceKeysRejectBeep->isChecked()); + + keyboardGroup.writeEntry("Gestures", gestures->isChecked()); + keyboardGroup.writeEntry("AccessXTimeout", timeout->isChecked()); + keyboardGroup.writeEntry("AccessXTimeoutDelay", timeoutDelay->value()); + + keyboardGroup.writeEntry("AccessXBeep", accessxBeep->isChecked()); + keyboardGroup.writeEntry("GestureConfirmation", gestureConfirmation->isChecked()); + keyboardGroup.writeEntry("kNotifyAccessX", kNotifyAccessX->isChecked()); + + + cg.sync(); + keyboardGroup.sync(); + + if (systemBell->isChecked() || + customBell->isChecked() || + visibleBell->isChecked()) + { + KConfig _cfg("kdeglobals", KConfig::NoGlobals); + KConfigGroup cfg(&_cfg, "General"); + cfg.writeEntry("UseSystemBell", true); + cfg.sync(); + } + + // make kaccess reread the configuration + // turning a11y features off needs to be done by kaccess + // so run it to clear any enabled features and it will exit if it should + KToolInvocation::startServiceByDesktopName("kaccess"); + + emit changed(false); +} + + +void KAccessConfig::defaults() +{ + systemBell->setChecked(true); + customBell->setChecked(false); + soundEdit->setText(""); + + visibleBell->setChecked(false); + invertScreen->setChecked(true); + flashScreen->setChecked(false); + colorButton->setColor(QColor(Qt::red)); + + durationSlider->setValue(500); + + slowKeys->setChecked(false); + slowKeysDelay->setValue(500); + slowKeysPressBeep->setChecked(true); + slowKeysAcceptBeep->setChecked(true); + slowKeysRejectBeep->setChecked(true); + + bounceKeys->setChecked(false); + bounceKeysDelay->setValue(500); + bounceKeysRejectBeep->setChecked(true); + + stickyKeys->setChecked(false); + stickyKeysLock->setChecked(true); + stickyKeysAutoOff->setChecked(false); + stickyKeysBeep->setChecked(true); + toggleKeysBeep->setChecked(false); + kNotifyModifiers->setChecked(false); + + gestures->setChecked(false); + timeout->setChecked(false); + timeoutDelay->setValue(30); + + accessxBeep->setChecked(true); + gestureConfirmation->setChecked(true); + kNotifyAccessX->setChecked(false); + + checkAccess(); + + emit changed(true); +} + + +void KAccessConfig::invertClicked() +{ + flashScreen->setChecked(false); +} + + +void KAccessConfig::flashClicked() +{ + invertScreen->setChecked(false); +} + + +void KAccessConfig::checkAccess() +{ + bool custom = customBell->isChecked(); + soundEdit->setEnabled(custom); + soundButton->setEnabled(custom); + soundLabel->setEnabled(custom); + + bool visible = visibleBell->isChecked(); + invertScreen->setEnabled(visible); + flashScreen->setEnabled(visible); + colorButton->setEnabled(visible); + durationSlider->setEnabled(visible); + + bool sticky = stickyKeys->isChecked(); + stickyKeysLock->setEnabled(sticky); + stickyKeysAutoOff->setEnabled(sticky); + stickyKeysBeep->setEnabled(sticky); + + bool slow = slowKeys->isChecked(); + slowKeysDelay->setEnabled(slow); + slowKeysPressBeep->setEnabled(slow); + slowKeysAcceptBeep->setEnabled(slow); + slowKeysRejectBeep->setEnabled(slow); + + bool bounce = bounceKeys->isChecked(); + bounceKeysDelay->setEnabled(bounce); + bounceKeysRejectBeep->setEnabled(bounce); + + bool useTimeout = timeout->isChecked(); + timeoutDelay->setEnabled(useTimeout); +} + +extern "C" +{ + /* This one gets called by kcminit + + */ + Q_DECL_EXPORT void kcminit_access() + { + KConfig config("kaccessrc", KConfig::NoGlobals); + KToolInvocation::startServiceByDesktopName("kaccess"); + } +} + +#include "kcmaccess.moc" + diff --git a/kcms/access/kcmaccess.desktop b/kcms/access/kcmaccess.desktop new file mode 100644 index 0000000000..e855b8eb7b --- /dev/null +++ b/kcms/access/kcmaccess.desktop @@ -0,0 +1,240 @@ +[Desktop Entry] +Exec=kcmshell5 kcmaccess +Icon=preferences-desktop-accessibility +Type=Service +X-KDE-ServiceTypes=KCModule,KCModuleInit +X-DocPath=kcontrol/kcmaccess/index.html + +X-KDE-Library=kcm_access +X-KDE-Init-Symbol=kcminit_access +X-KDE-ParentApp=kcontrol +X-KDE-OnlyShowOnQtPlatforms=xcb; + +X-KDE-System-Settings-Parent-Category=accessibility + +Name=Accessibility +Name[af]=Toeganklikheid +Name[ar]=الإتاحة +Name[as]=অভিগম্যতা +Name[ast]=Accesibilidá +Name[be]=Даступнасць +Name[be@latin]=Dastupnaść +Name[bg]=Равностоен достъп +Name[bn]=সহায়ক প্রযুক্তি +Name[bn_IN]=বিশেষ ব্যবহারের সহায়তা +Name[br]=Haezadusted +Name[bs]=Pristupačnost +Name[ca]=Accessibilitat +Name[ca@valencia]=Accessibilitat +Name[cs]=Zpřístupnění +Name[csb]=Pòmòce przëstãpù +Name[cy]=Hygyrchedd +Name[da]=Tilgængelighed +Name[de]=Zugangshilfen +Name[el]=Προσιτότητα +Name[en_GB]=Accessibility +Name[eo]=Alirebleco +Name[es]=Accesibilidad +Name[et]=Hõlbustus +Name[eu]=Erabilerraztasuna +Name[fa]=دستیابی‌پذیری +Name[fi]=Esteettömyys +Name[fr]=Accessibilité +Name[fy]=Tagonklikens +Name[ga]=Inrochtaineacht +Name[gl]=Accesibilidade +Name[gu]=ઉપયોગિતા +Name[he]=נגישות +Name[hi]=पहुँच +Name[hne]=पहुंच +Name[hr]=Pristupačnost +Name[hsb]=Přistupnosć +Name[hu]=Kezelési segítség +Name[ia]=Accessibilitate +Name[id]=Aksesibilitas +Name[is]=Aðgengi +Name[it]=Accessibilità +Name[ja]=アクセシビリティ +Name[ka]=სპეციალური შესაძლბლობები +Name[kk]=Арнайы мүмкіндіктер +Name[km]=មធ្យោបាយ​ងាយស្រួល +Name[kn]=ನಿಲುಕಣೆ (ಆಕ್ಸೆಸಿಬಿಲಿಟಿ) +Name[ko]=내게 필요한 설정 +Name[ku]=Gihîştin +Name[lt]=Pritaikymas neįgaliesiems +Name[lv]=Pieejamība +Name[mai]=अभिगम्यता +Name[mk]=Пристапливост +Name[ml]=സാമീപ്യത +Name[mr]=सुलभता +Name[ms]=Kebolehcapaian +Name[nb]=Tilgjengelighet +Name[nds]=Toganghülp +Name[ne]=पहुँचता +Name[nl]=Toegankelijkheid +Name[nn]=Tilgjenge +Name[oc]=Accessibilitat +Name[or]=ଅଭିଗମ୍ୟତା +Name[pa]=ਸਹੂਲਤਾਂ +Name[pl]=Ułatwienia dostępu +Name[pt]=Acessibilidade +Name[pt_BR]=Acessibilidade +Name[ro]=Accesibilitate +Name[ru]=Специальные возможности +Name[se]=Álkkibut geavaheapmi +Name[si]=ප්‍රවේශණය +Name[sk]=Prístupnosť +Name[sl]=Dostopnost +Name[sr]=Приступачност +Name[sr@ijekavian]=Приступачност +Name[sr@ijekavianlatin]=Pristupačnost +Name[sr@latin]=Pristupačnost +Name[sv]=Handikappstöd +Name[ta]=அணுகல் +Name[te]=అందుబాటు +Name[tg]=Имкониятҳо +Name[th]=ช่วยการใช้งาน +Name[tr]=Erişilebilirlik +Name[ug]=ياردەم ئىقتىدارى +Name[uk]=Доступність +Name[uz]=Qulayliklar +Name[uz@cyrillic]=Қулайликлар +Name[vi]=Hỗ trợ truy cập +Name[wa]=Accessibilité +Name[xh]=Unikezelo +Name[x-test]=xxAccessibilityxx +Name[zh_CN]=辅助 +Name[zh_TW]=無障礙輔助 + +Comment=Improve accessibility for disabled persons +Comment[af]=Verbeter toeganklikheid vir gestremde persone +Comment[ar]=تحسين إمكانية الوصول للمعوقين +Comment[ast]=Ameyorar accesibilidá pa discapacitaos +Comment[be]=Павялічвае даступнасць для людзей з фізічнымі адхіленнямі +Comment[be@latin]=Palapšeńnie dastupnaści prahramaŭ dla invalidaŭ +Comment[bg]=Настройки на достъпа за хора с увреждания +Comment[bn]=অসমর্থ ব্যবহারকারীদের সহায়তা করার প্রযুক্তি +Comment[bs]=Poboljšava pristupačnost hendikepiranim osobama +Comment[ca]=Accessibilitat millorada per a persones discapacitades +Comment[ca@valencia]=Accessibilitat millorada per a persones discapacitades +Comment[cs]=Zlepšení přístupnosti pro osoby s postižením +Comment[csb]=Pòprôwionô przëstãpnosc dlô niefùlsprôwnëch lëdzi +Comment[cy]=Gwella hygyrchedd i bobl anabl +Comment[da]=Forbedr tilgængelighed for handicappede personer +Comment[de]=Verbesserte Benutzbarkeit für Menschen mit Behinderung +Comment[el]=Βελτίωση της προσιτότητας για άτομα με ειδικές ανάγκες +Comment[en_GB]=Improve accessibility for disabled persons +Comment[eo]=Plibonigita alirebleco por handikapitoj +Comment[es]=Mejorar accesibilidad para discapacitados +Comment[et]=Puuetega inimestele mõeldud seaded +Comment[eu]=Ezinduentzako erabilerraztasuna handitzen du +Comment[fa]=بهبود دستیابی‌پذیری برای اشخاص ناتوان +Comment[fi]=Esteettömyysasetukset +Comment[fr]=Améliore l'accessibilité pour les personnes handicapées +Comment[fy]=Ferbeterde tagonklikens foar brûkers mei in handikap +Comment[ga]=Feabhsaigh an inrochtaineacht do dhaoine míchumasaithe +Comment[gl]=Accesibilidade mellorada para persoas con discapacidades +Comment[gu]=અસક્ષમ વ્યક્તિઓ માટે ઉપયોગિતામાં સુધારો કરો +Comment[he]=שיפור הנגישות עבור אנשים עם מוגבלויות +Comment[hi]=विकलांग व्यक्तियों के लिए पहुँच बेहतर बनाए +Comment[hne]=विकलांग मनखे बर पहुंच बेहतर बनाए +Comment[hr]=Unaprijedite pristupačnost osobama s invaliditetom +Comment[hsb]=Přistupnosć za zbrašenych zlěpšić +Comment[hu]=A számítógép kezelését segítő eszközök fogyatékosoknak +Comment[ia]=Il meliora le accessibilitate pro personas invalide +Comment[id]=Tingkatkan aksesibilitas bagi orang cacat +Comment[is]=Endurbætt aðgengi fyrir þá sem þurfa +Comment[it]=Migliora l'accessibilità per i disabili +Comment[ja]=障害を持った方達のためのアクセシビリティの改善 +Comment[ka]=ფიზიკური ნაკლოვანებბის მქონი ხალხისთვის სპეციალური შესაძლბლობები +Comment[kk]=Мүмкіншіліктері шектеулі адамдарға көмек +Comment[km]=បង្កើន​មធ្យោបាយ​ងាយស្រួល​សម្រាប់​មនុស្ស​ពិការ +Comment[kn]=ದುರ್ಬಲೀನರಾದ ವ್ಯಕ್ತಿಗಳಿಗೆ ನಿಲುಕಣೆಯನ್ನು (ಅಕ್ಸೆಸಿಬಲಿಟಿ) ಸುಧಾರಿಸಿ +Comment[ko]=장애인들을 위하여 접근성을 향상시킵니다 +Comment[ku]=Ji bo kesên neçalak gihîştinê biguherîne +Comment[lt]=Pagerintas prieinamumas neįgaliems asmenims +Comment[lv]=Uzlabo pieejamību cilvēkiem ar īpašām vajadzībām +Comment[mai]=विकलांग लोकनिसभक लेल पहुँच बेहतर बनाएल जाए +Comment[mk]=Ја подобрува пристапливоста за хендикепирани лица +Comment[ml]=അംഗവൈകല്യമുള്ളവര്‍ക്കുള്ള സാമീപ്യത നന്നാക്കുക +Comment[mr]=विकलांग व्यक्तिं करिता सुधारित सुलभता +Comment[ms]=Tingkatkan keaksesan bagi orang kurang upaya +Comment[nb]=Forbedret tilgjengelighet for funksjonshemmede +Comment[nds]=Verbetert den Togang för behinnert Lüüd +Comment[ne]=अक्षम व्यक्तिका लागि पहुँच क्षमता सुधार गर्नुहोस् +Comment[nl]=Verbeterde toegankelijkheid voor gebruikers met een handicap +Comment[nn]=Forbetra tilgjenge for funksjonshemma personar +Comment[or]=ନିଷ୍କ୍ରିୟ ବ୍ୟକ୍ତିମାନଙ୍କ ପାଇଁ ଅଭିଗମ୍ୟତା ଉନ୍ନତ କରନ୍ତୁ +Comment[pa]=ਅਪੰਗ ਵਿਅਕਤੀ ਲਈ ਸੁਧਾਰੀਆਂ ਸਹੂਲਤਾਂ +Comment[pl]=Poprawiona dostępność dla osób niepełnosprawnych +Comment[pt]=Acessibilidade melhorada para pessoas com necessidades especiais +Comment[pt_BR]=Melhora a acessibilidade para pessoas com deficiência +Comment[ro]=Îmbunătățește accesibilitate KDE pentru persoanele cu handicap +Comment[ru]=Специальные возможности для людей с физическими ограничениями +Comment[se]=Álkkibut geavaheapmi doaimmahehttejuvvon olbmuide +Comment[si]=අබාධිත අයෙකුට පහසුවෙන් පිවිසීමට ඉඩදෙයි +Comment[sk]=Zlepšenie prístupnosti pre postihnutých užívateľov +Comment[sl]=Izboljšana dostopnost za prizadete osebe +Comment[sr]=Побољшава приступачност хендикепираним особама +Comment[sr@ijekavian]=Побољшава приступачност хендикепираним особама +Comment[sr@ijekavianlatin]=Poboljšava pristupačnost hendikepiranim osobama +Comment[sr@latin]=Poboljšava pristupačnost hendikepiranim osobama +Comment[sv]=Förbättrad tillgänglighet för handikappade personer +Comment[ta]=பார்க்க முடியாதவர்களுக்கு அணுகலை அதிகப்படுத்தவும் +Comment[te]=వికలాంగులైన వ్యక్తులకు అందుబాటును మెరుగుపరుచుము +Comment[tg]=Специальные возможности для людей с физическими недостатками +Comment[th]=ช่วยให้ผู้พิการหรือผู้บกพร่องทางร่างกายด้านอื่นๆ สามารถใช้งานได้สะดวกสบายมากขึ้น +Comment[tr]=Görme sorunu olanlar için erişilebilirlik seçenekleri +Comment[ug]=مېيىپلەر ئۈچۈن ئىشلىتىلىدىغان ياردەمچى ئىقتىدارلار +Comment[uk]=Підвищення зручності для інвалідів +Comment[uz]=Nogiron kishilar uchun qulayliklar +Comment[uz@cyrillic]=Ногирон кишилар учун қулайликлар +Comment[vi]=Cải thiện khả năng truy cập cho người khuyết tật +Comment[wa]=Rind pus åjhey l' accessibilité po les sakîs k' ont des andicapes +Comment[xh]=Phucula unikekezeleko lwabantu abakhubazekileyo +Comment[x-test]=xxImprove accessibility for disabled personsxx +Comment[zh_CN]=方便残疾人使用的辅助功能 +Comment[zh_TW]=方便傷殘人士使用 + +X-KDE-Keywords=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys +X-KDE-Keywords[bs]=pristup,pristupačnost,gluh,oštećen,sluh,gubitak sluha,zvono,zvučno zvono,vidljivo zvono,tastatura,tipke,ljepljive tipke,odskočne tipke,usporene tipke,navigacija uz pomoć miša,numerički dio, +X-KDE-Keywords[ca]=accés,accessibilitat,sord,discapacitat,oïda,pèrdua d'oïda,campana,campana audible,campana visible,Teclat,tecles apegaloses,repetició de tecles,tecles lentes,navegació de ratolí,teclat numèric,activació de gestos,gestors,apegalós,tecles modificadores,modificador,tecles bloquejadores +X-KDE-Keywords[ca@valencia]=accés,accessibilitat,sord,discapacitat,oïda,pèrdua d'oïda,campana,campana audible,campana visible,Teclat,tecles apegaloses,repetició de tecles,tecles lentes,navegació de ratolí,teclat numèric,activació de gestos,gestors,apegalós,tecles modificadores,modificador,tecles bloquejadores +X-KDE-Keywords[da]=tilgang,tilgængelighed,døv,hæmmet,handicappet,hørelse,hørehæmmet,klokke,hørbar klokke,synlig klokke,tastatur,taster,sticky keys,elastiske taster,bounce,langsomme taster,musenavigation,numerisk tastatur,aktiveringsgestusser,gestusser,klæbende,ændringstaster,låsetaster +X-KDE-Keywords[de]=Behinderung,Maussteuerung,Signale,Tastatur,Tasten,Klebende Tasten,Taubheit,Verlangsamte Tasten,Zahlenblock,Zugang,Zugangshilfen,Zahlentasten,Gesten aktivieren,Sondertasten,Sperrtasten +X-KDE-Keywords[el]=πρόσβαση,προσβασιμότητα,βαρήκοος,πρόβλημα,ακοής,απώλεια ακοής,κουδούνι,ηχητικό κουδούνι,οπτικό κουδούνι,πληκτρολόγιο,πλήκτρα,κολλημένα πλήκτρα,πλήκτρα αναπήδησης,αργά πλήκτρα,πλοήγηση με ποντίκι,αριθμητικό πληκτρολόγιο,numpad,νεύματα ενεργοποίησης,νεύματα,κολλημένο,πλήκτρα τροποποιητή,τροποποιητής,πλήκτρα κλειδώματος +X-KDE-Keywords[es]=acceso,accesibilidad,sordera,descapacitado,oído,pérdida de oído,campana,campana audible,campana visible,teclado,teclas,teclas pegajosas,repetición de teclas,teclas lentas,navegación con ratón,teclado numérico,gestos de activación,gestos,pegajoso,teclas modificadoras,modificador,teclas de bloqueo +X-KDE-Keywords[et]=hõlbustus,kasutusmugavus,kurdid,tummad,kuulmine,kuulmiskaotus,puuetega,kell,kuuldav kell,nähtav kell,klaviatuur,klahvid,kleepuvad klahvid,põrkuvad klahvid,aeglased klahvid,hiirega liikumine,numbriklahvistik,aktiveerimisžestid,žestid,muuteklahvid,lukustusklahvid +X-KDE-Keywords[eu]=sarbide,erabilerraztasun,gor,baliaezintasun,entzumen,entzumena galdu,kanpai,kanpai entzungarri,kanpai ikusgarri,teklatu,tekla,tekla itsaskor,errebote-teklak,tekla motel,sagu bidezko nabigazio,zenbakizko teklatu,zk teklatu,aktibazio-keinu,keinu,itsaskor,tekla aldatzaile,aldatzaile,blokeo-tekla +X-KDE-Keywords[fi]=esteettömyys,kuuro,heikentynyt,heikko,kuulo,varoitus,äänimerkki,visuaalinen äänimerkki,näppäimistö,näppäimet,alas jäävät näppäimet,tahmeat näppäimet,ponnahdusnäppäimet,hitaat näppäimet,hiirinäppäimet,numeronäppäimistö +X-KDE-Keywords[fr]=accès, accessibilité, sourd, affaiblis, audition, perte d'audition, cloche, cloche audible, cloche visuelle, clavier, touches, touches collantes, touche rebondissante, touches lentes, navigation de la souris, pavé numérique, gestes d'activation, gestes, collant, touches modifiantes, modificateur, touche de verrouillage +X-KDE-Keywords[ga]=rochtain,inrochtaineacht,bodhar,lagaithe,cloigín,cloigín inchloiste,clog infheicthe,Méarchlár,eochracha,eochracha greamaitheacha,eochracha preabtha,eochracha go mall,nascleanúint luiche,eochaircheap uimhriúil,gothaí,greamaitheach,mionthraitheoir,eochracha glasála +X-KDE-Keywords[gl]=acceso, accesibilidade, xordo, discapacitado, minusválido, audición, auditiva, campá audíbel, campá visíbel, teclado, tecla pegañentas, teclas lentas, navegación co rato, teclado numérico, acenos, teclas modificadoras +X-KDE-Keywords[hu]=kezelés,akadálymentesítés,süket,károsodott,hallás,halláskárosodás,csengő,hallható csengő,látható csengő,Billentyűzet,billentyűk,ragadós billentyűk,pattogó billentyűk,lassú billentyűk,egérnavigáció,numerikus billentyűzet +X-KDE-Keywords[ia]=accesso,accessibilitate,surde,debilitate,audito, perdita de audito,campana,campana audibile,campana visibile,Claviero,claves,claves collose,claves saltante,claves lente,navigation de mus,pad numeric, gestos de activation,gestos,collose, claves modificator, modificator, claves blocante +X-KDE-Keywords[it]=accesso,accessibilità,sordo,handicap,udito,sordità,campanella,campanella udibile,campanella visiva,tastiera,tasti,permanenza dei tasti,pressione ravvicinata dei tasti,rallentamento dei tasti,navigazione col mouse,tastierino numerico,attivazione gesti,gesti,tasti modificatori,modificatore,tasti di blocco +X-KDE-Keywords[kk]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys +X-KDE-Keywords[km]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys +X-KDE-Keywords[ko]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,접근,접근성,청각장애,청각 장애,시각장애,시각 장애,키보드,키,고정키,튕김키,느린키,마우스키,숫자패드 +X-KDE-Keywords[mr]=एक्सेस, एक्सेसिबिलिटी, कर्णबधीर, विकलांग, ऐकणे, कमी ऐकू येणे, घंटा, घंटानाद , दृश्यघंटा, कि-बोर्ड, कीज, स्टिकी किज, बाउन्स किज, स्लो किज, माऊस दिशानिर्देश, न्यूम पॅड, एक्टिव्हेशन गेस्चर्स, गेस्चर्स, स्टिकी, मॉडीफायर कीज, मॉडीफायर, लॉकिंग किज, +X-KDE-Keywords[nb]=tilgang,tilgjengelighet,døv,hemmet,hørsel, hørselstap,bjelle,hørbar bjelle,synlig bjelle,Tastatur,låsetaster,faste taster,trege taster,musnavigering, talltastatur,tallboks,aktiveringsbevegelser,bevegelser,valgtaster +X-KDE-Keywords[nds]=Togang,Toganghülp,doof,kiekbehinnert,Hören,Pingel,Ogenpingel,Tastatuur,Tasten,backige Tasten,jumpen Tasten,langsame Tasten,Muusstüern,Tallenblock,Tekens,Anmaaktekens,backig,Sünnertasten,Wesseltekens,Fastsetttasten +X-KDE-Keywords[nl]=toegang,toegankelijkheid,doof,gehandicapt,gehoor,gehoorverlies,bel,hoorbare bel,zichtbare bel,toetsenbord,toetsen,dode toetsen,herhaaltoetsen,langzame toetsen,muisnavigatie,numeriek toetsenbord,activeringsgebaren,gebaren,plakkerig,modificatietoetsen,modificator,vergrendeltoets +X-KDE-Keywords[pl]=dostęp,dostępność,głuchota,upośledzenie,dzwonek,słyszalny dzwonek,widoczny dzwonek,Klawiatura,klawisze,lepkie klawisze,odbijające klawisze,powolne klawisze, ruchy myszą,klawiatura numeryczna +X-KDE-Keywords[pt]=acesso,acessibilidade,surdo,deficiente,campainha,campainha audível,campainha visível,teclado,teclas,teclas fixas,teclas lentas,teclas sonoras,navegação do rato,teclado numérico,numérico,gestos de activação,gestos,fixo,teclas modificadoras,modificadora,teclas de bloqueio +X-KDE-Keywords[pt_BR]=acesso,acessibilidade,surdo,deficiente,audição,campainha,campainha audível,campainha visível,Teclado,teclas,teclas de aderência,teclas lentas,teclas de repercussão,navegação do mouse,teclado numérico numérico,gestos de ativação,gestos,fixo,teclas modificadoras,modificadora,teclas de bloqueio +X-KDE-Keywords[ru]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,доступ,доступность,глухота,слух,ослабленный,слабый,потеря слуха,звонок,сигнал,звуковой сигнал,визуальный сигнал,видимый сигнал,клавиатура,кнопки,клавиши,залипание,залипающие клавиши,липкие клавиши,прыгающие клавиши,«прыгающие» клавиши,замедленные клавиши,навигация с помощью мыши,управление мышью,цифровая клавиатура,жесты активации,жесты,клавиши-модификаторы,модификаторы,модификатор,клавиши индикаторов +X-KDE-Keywords[sk]=prístup,prístupnosť,hluchý,opitý,sluch,strata sluchu,zvonček,hlasný zvonček,viditeľný zvonček,Klávesnica,klávesy,lepkavé klávesy,skákajúce klávesy,pomalé klávesy,navigácia myšou,numerická klávesnica,numpad,aktivačné gestá,lepkavé,modifikačné klávesy,modifikátor,zamykacie klávesy +X-KDE-Keywords[sl]=dostop,dostopnost,gluh,oviran,sluh,slušno,izguba sluha,zvonec,slišen zvonec,viden zvonec,tipkovnica,tipke,lepljive tipke,odbijajoče tipke,počasne tipke,krmarjenje z miško,številčnica,številske tipke,kretnje za vklop,kretnje,lepljivo,spremenilne tipke,zaklepne tipke +X-KDE-Keywords[sr]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,приступ,приступачност,глув,оштећен,слух,губитак,звоно,чујно,видно,тастатура,тастери,лепљиви,одскачући,спори,нумеричка,активација,гестови,лепљив,модификаторски,тастери,закључавање +X-KDE-Keywords[sr@ijekavian]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,приступ,приступачност,глув,оштећен,слух,губитак,звоно,чујно,видно,тастатура,тастери,лепљиви,одскачући,спори,нумеричка,активација,гестови,лепљив,модификаторски,тастери,закључавање +X-KDE-Keywords[sr@ijekavianlatin]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,pristup,pristupačnost,gluv,oštećen,sluh,gubitak,zvono,čujno,vidno,tastatura,tasteri,lepljivi,odskačući,spori,numerička,aktivacija,gestovi,lepljiv,modifikatorski,tasteri,zaključavanje +X-KDE-Keywords[sr@latin]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,pristup,pristupačnost,gluv,oštećen,sluh,gubitak,zvono,čujno,vidno,tastatura,tasteri,lepljivi,odskačući,spori,numerička,aktivacija,gestovi,lepljiv,modifikatorski,tasteri,zaključavanje +X-KDE-Keywords[sv]=åtkomst,handikappstöd,döva,funktionshindrade,hörsel,hörselförlust,summer,hörbar summer,synlig summer,Tangentbord,tangenter,klistriga tangenter,studsande tangenter,långsamma tangenter,musnavigering,numeriskt tangentbord,aktiveringsgester,gester,klistrig,väljartangenter,väljare,låstangenter +X-KDE-Keywords[tr]=erişim,erişebilirlik,sağır,bozukluk,işitme,kayıp,zil,işitilebilir zil,görünen zil,Klayve,tuşlar,yapışkan tuşlar,sıçrama tuşları,yavaş tuşlar,fare gezinmesi,rakamlar klavyesi,jestler,yapışkan,hızlandırma tuşları,hızlandırıcı,kilitleme tuşları +X-KDE-Keywords[uk]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,доступ,доступність,спеціальні можливості,глухий,слух,враження,вади,звук,сповіщення,видиме сповіщення,візуальне сповіщення,клавіатура,клавіші,клавіша,липкі клавіші,утримування,повільні клавіші,миша,навігація,цифри,цифровий блок,слух,втрата слуху,жести активування,жести,липка,липкі клавіші,клавіші-модифікатори,модифікатори,клавіші фіксування,фіксування,блокування +X-KDE-Keywords[x-test]=xxaccess,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keysxx +X-KDE-Keywords[zh_CN]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys,访问,可访问性,耳聋,聋,听力,听力丧失,铃声,可视铃声,按键,残疾人,残疾,聋哑,键盘,粘滞键,鼠标,小键盘,撞击键,鼠标导航,数字键盘,激活手势,手势,粘滞,修饰键,锁定键 +X-KDE-Keywords[zh_TW]=access,accessibility,deaf,impaired,hearing,hearing loss,bell,audible bell,visible bell,Keyboard,keys,sticky keys,bounce keys,slow keys,mouse navigation,num pad,numpad,activation gestures,gestures,sticky,modifier keys,modifier,locking keys + +Categories=Qt;KDE;X-KDE-settings-accessibility; diff --git a/kcms/access/kcmaccess.h b/kcms/access/kcmaccess.h new file mode 100644 index 0000000000..d3cb40f304 --- /dev/null +++ b/kcms/access/kcmaccess.h @@ -0,0 +1,76 @@ +/** + * kcmaccess.h + * + * Copyright (c) 2000 Matthias H�zer-Klpfel + * + */ + +#ifndef __kcmaccess_h__ +#define __kcmaccess_h__ + + +#define KDE3_SUPPORT +#include +#undef KDE3_SUPPORT +#include + + +class QCheckBox; +class QLabel; +class QLineEdit; +class QPushButton; +class QRadioButton; +class KColorButton; +class QSlider; + +class KAccessConfig : public KCModule +{ + Q_OBJECT + +public: + + KAccessConfig( QWidget *parent, const QVariantList& ); + virtual ~KAccessConfig(); + + void load(); + void save(); + void defaults(); + +protected Q_SLOTS: + + void configChanged(); + void checkAccess(); + void invertClicked(); + void flashClicked(); + void selectSound(); + void changeFlashScreenColor(); + void configureKNotify(); + +private: + + QCheckBox *systemBell, *customBell, *visibleBell; + QRadioButton *invertScreen, *flashScreen; + QLabel *soundLabel, *colorLabel; + QLineEdit *soundEdit; + QPushButton *soundButton; + KColorButton *colorButton; + KDoubleNumInput *durationSlider; + + QCheckBox *stickyKeys, *stickyKeysLock, *stickyKeysAutoOff; + QCheckBox *stickyKeysBeep, *toggleKeysBeep, *kNotifyModifiers; + QPushButton *kNotifyModifiersButton; + + QCheckBox *slowKeys, *bounceKeys; + KDoubleNumInput *slowKeysDelay, *bounceKeysDelay; + QCheckBox *slowKeysPressBeep, *slowKeysAcceptBeep; + QCheckBox *slowKeysRejectBeep, *bounceKeysRejectBeep; + + QCheckBox *gestures, *gestureConfirmation; + QCheckBox *timeout; + KIntNumInput *timeoutDelay; + QCheckBox *accessxBeep, *kNotifyAccessX; + QPushButton *kNotifyAccessXButton; +}; + + +#endif diff --git a/kcms/access/main.cpp b/kcms/access/main.cpp new file mode 100644 index 0000000000..09864fc2f8 --- /dev/null +++ b/kcms/access/main.cpp @@ -0,0 +1,55 @@ + +#include "kaccess.h" +#include +#include +#include +#include +#include +#include + +extern "C" Q_DECL_EXPORT int kdemain(int argc, char * argv[] ) +{ + K4AboutData about(I18N_NOOP("kaccess"), 0, ki18n("KDE Accessibility Tool"), + 0, KLocalizedString(), K4AboutData::License_GPL, + ki18n("(c) 2000, Matthias Hoelzer-Kluepfel")); + + about.addAuthor(ki18n("Matthias Hoelzer-Kluepfel"), ki18n("Author") , "hoelzer@kde.org"); + + KCmdLineArgs::init( argc, argv, &about ); + + if (!KAccessApp::start()) + return 0; + + // verify the Xlib has matching XKB extension + int major = XkbMajorVersion; + int minor = XkbMinorVersion; + if (!XkbLibraryVersion(&major, &minor)) + { + kError() << "Xlib XKB extension does not match" << endl; + return 1; + } + kDebug() << "Xlib XKB extension major=" << major << " minor=" << minor; + + // we need an application object for QX11Info + KAccessApp app; + + // verify the X server has matching XKB extension + // if yes, the XKB extension is initialized + int opcode_rtrn; + int error_rtrn; + int xkb_opcode; + if (!XkbQueryExtension(QX11Info::display(), &opcode_rtrn, &xkb_opcode, &error_rtrn, + &major, &minor)) + { + kError() << "X server has not matching XKB extension" << endl; + return 1; + } + kDebug() << "X server XKB extension major=" << major << " minor=" << minor; + + //Without that, the application dies when the dialog is closed only once. + app.setQuitOnLastWindowClosed(false); + + app.setXkbOpcode(xkb_opcode); + app.disableSessionManagement(); + return app.exec(); +} diff --git a/kcms/autostart/AUTHORS b/kcms/autostart/AUTHORS new file mode 100644 index 0000000000..ab559c90d6 --- /dev/null +++ b/kcms/autostart/AUTHORS @@ -0,0 +1,2 @@ +Stephen Leaf +Montel Laurent diff --git a/kcms/autostart/CMakeLists.txt b/kcms/autostart/CMakeLists.txt new file mode 100644 index 0000000000..d1832e8774 --- /dev/null +++ b/kcms/autostart/CMakeLists.txt @@ -0,0 +1,18 @@ +project (autostart) + +set(kcm_autostart_PART_SRCS + autostartitem.cpp + addscriptdialog.cpp + advanceddialog.cpp + autostart.cpp ) + +qt5_wrap_ui(kcm_autostart_PART_SRCS autostartconfig.ui ) + +add_library(kcm_autostart MODULE ${kcm_autostart_PART_SRCS}) + +target_link_libraries(kcm_autostart KF5::KCMUtils KF5::I18n KF5::KIOCore KF5::KIOWidgets) + +########### install files ############### + +install(TARGETS kcm_autostart DESTINATION ${PLUGIN_INSTALL_DIR} ) +install( FILES autostart.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/kcms/autostart/Messages.sh b/kcms/autostart/Messages.sh new file mode 100644 index 0000000000..8f32b9b787 --- /dev/null +++ b/kcms/autostart/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC *.ui >> rc.cpp +$XGETTEXT *.cpp -o $podir/kcm_autostart.pot +rm -f rc.cpp diff --git a/kcms/autostart/addscriptdialog.cpp b/kcms/autostart/addscriptdialog.cpp new file mode 100644 index 0000000000..8077c24919 --- /dev/null +++ b/kcms/autostart/addscriptdialog.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2007 by Stephen Leaf * + * smileaf@gmail.com * + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "addscriptdialog.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +AddScriptDialog::AddScriptDialog (QWidget* parent) + : QDialog( parent ) +{ + QVBoxLayout *lay= new QVBoxLayout; + setLayout( lay ); + QLabel *lab = new QLabel( i18n( "Shell script path:" ), this ); + lay->addWidget( lab ); + m_url = new KUrlRequester( this ); + lay->addWidget( m_url ); + m_symlink = new QCheckBox( i18n( "Create as symlink" ), this ); //TODO fix text + m_symlink->setChecked( true ); + lay->addWidget( m_symlink ); + connect( m_url->lineEdit(), SIGNAL(textChanged(QString)), SLOT(textChanged(QString)) ); + m_url->lineEdit()->setFocus(); + + m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, this); + m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false); + lay->addWidget(m_buttons); + connect(m_buttons, SIGNAL(accepted()), SLOT(accept())); + connect(m_buttons, SIGNAL(rejected()), SLOT(reject())); +} + +AddScriptDialog::~AddScriptDialog() +{ +} + +void AddScriptDialog::textChanged(const QString &text) +{ + m_buttons->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); +} + +void AddScriptDialog::accept() +{ + if ( doBasicSanityCheck() ) + QDialog::accept(); +} + +bool AddScriptDialog::doBasicSanityCheck() +{ + const QString& path = KShell::tildeExpand(m_url->text()); + + QFileInfo file(path); + + if ( ! file.isAbsolute() ) { + KMessageBox::sorry( 0, i18n("\"%1\" is not an absolute path.", path) ); + return false; + } else if ( ! file.exists() ) { + KMessageBox::sorry( 0, i18n("\"%1\" does not exist.", path) ); + return false; + } else if ( !file.isFile() ) { + KMessageBox::sorry( 0, i18n("\"%1\" is not a file.", path) ); + return false; + } else if ( ! file.isReadable() ) { + KMessageBox::sorry( 0, i18n("\"%1\" is not readable.", path) ); + return false; + } + + return true; +} + +QUrl AddScriptDialog::importUrl() const +{ + return m_url->url(); +} + +bool AddScriptDialog::symLink() const +{ + return m_symlink->isChecked(); +} + +#include "addscriptdialog.moc" diff --git a/kcms/autostart/addscriptdialog.h b/kcms/autostart/addscriptdialog.h new file mode 100644 index 0000000000..fc1e608d6a --- /dev/null +++ b/kcms/autostart/addscriptdialog.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2007 by Stephen Leaf * + * smileaf@gmail.com * + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 ADDSCRIPTDIALOG_H +#define ADDSCRIPTDIALOG_H + +#include +#include + +class QDialogButtonBox; +class KUrlRequester; +class QCheckBox; + +class AddScriptDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AddScriptDialog(QWidget* parent=0); + ~AddScriptDialog(); + // Returns the Url of the script to be imported + QUrl importUrl() const; + bool symLink() const; + +public Q_SLOTS: + // reimplemented + virtual void accept(); + +protected: + virtual bool doBasicSanityCheck(); + +private Q_SLOTS: + void textChanged(const QString &text); + +private: + KUrlRequester *m_url; + QCheckBox* m_symlink; + + QDialogButtonBox* m_buttons; +}; + +#endif + diff --git a/kcms/autostart/advanceddialog.cpp b/kcms/autostart/advanceddialog.cpp new file mode 100644 index 0000000000..02b90f8670 --- /dev/null +++ b/kcms/autostart/advanceddialog.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "advanceddialog.h" + +#include +#include +#include + +#include + +AdvancedDialog::AdvancedDialog( QWidget *parent, bool status ) + : QDialog( parent ) +{ + QVBoxLayout *lay= new QVBoxLayout(this); + m_onlyInKde = new QCheckBox( i18n( "Autostart only in KDE" ), this ); + m_onlyInKde->setChecked( status ); + lay->addWidget( m_onlyInKde ); + + QDialogButtonBox* buttons = new QDialogButtonBox(this); + buttons->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + setLayout( lay ); + + connect(buttons, SIGNAL(accepted()), SLOT(accept())); + connect(buttons, SIGNAL(rejected()), SLOT(reject())); +} + +AdvancedDialog::~AdvancedDialog() +{ +} + +bool AdvancedDialog::onlyInKde() const +{ + return m_onlyInKde->isChecked(); +} + + +#include "advanceddialog.moc" + diff --git a/kcms/autostart/advanceddialog.h b/kcms/autostart/advanceddialog.h new file mode 100644 index 0000000000..3f22924805 --- /dev/null +++ b/kcms/autostart/advanceddialog.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 ADVANCEDDIALOG_H +#define ADVANCEDDIALOG_H + +#include +class QCheckBox; + +class AdvancedDialog : public QDialog +{ + Q_OBJECT + +public: + AdvancedDialog(QWidget* parent, bool status); + ~AdvancedDialog(); + + bool onlyInKde() const; + +private: + QCheckBox *m_onlyInKde; +}; + +#endif diff --git a/kcms/autostart/autostart.cpp b/kcms/autostart/autostart.cpp new file mode 100644 index 0000000000..7a18a1775a --- /dev/null +++ b/kcms/autostart/autostart.cpp @@ -0,0 +1,438 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Stephen Leaf * + * smileaf@gmail.com * + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "autostart.h" +#include "autostartitem.h" +#include "addscriptdialog.h" +#include "advanceddialog.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +K_PLUGIN_FACTORY(AutostartFactory, registerPlugin();) +K_EXPORT_PLUGIN(AutostartFactory( "kcmautostart", "kcm_autostart" )) + +Autostart::Autostart( QWidget* parent, const QVariantList& ) + : KCModule(parent ) +{ + widget = new Ui_AutostartConfig(); + widget->setupUi(this); + + QStringList lstHeader; + lstHeader << i18n( "Name" ) + << i18n( "Command" ) + << i18n( "Status" ) + << i18nc("@title:column The name of the column that decides if the program is run on kde startup, on kde shutdown, etc", "Run On" ); + widget->listCMD->setHeaderLabels(lstHeader); + widget->listCMD->setFocus(); + + setButtons(Help); + + connect( widget->btnAddScript, SIGNAL(clicked()), SLOT(slotAddScript()) ); + connect( widget->btnAddProgram, SIGNAL(clicked()), SLOT(slotAddProgram()) ); + connect( widget->btnRemove, SIGNAL(clicked()), SLOT(slotRemoveCMD()) ); + connect( widget->btnAdvanced, SIGNAL(clicked()), SLOT(slotAdvanced()) ); + connect( widget->listCMD, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(slotEditCMD(QTreeWidgetItem*)) ); + connect( widget->listCMD, SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(slotItemClicked(QTreeWidgetItem*,int)) ); + connect( widget->btnProperties, SIGNAL(clicked()), SLOT(slotEditCMD()) ); + connect( widget->listCMD, SIGNAL(itemSelectionChanged()), SLOT(slotSelectionChanged()) ); + + + KAboutData* about = new KAboutData(QStringLiteral("Autostart"), QString(), + i18n("KDE Autostart Manager"), + QStringLiteral("1.0"), + i18n("KDE Autostart Manager Control Panel Module"), + KAboutData::License_GPL, + i18n("Copyright © 2006–2010 Autostart Manager team")); + about->addAuthor(i18n("Stephen Leaf"), QString(), QStringLiteral("smileaf@gmail.com")); + about->addAuthor(i18n("Montel Laurent"), i18n( "Maintainer" ), QStringLiteral("montel@kde.org")); + setAboutData( about ); + +} + +Autostart::~Autostart() +{ + delete widget; +} + + +void Autostart::slotItemClicked( QTreeWidgetItem *item, int col) +{ + if ( item && col == COL_STATUS ) { + DesktopStartItem *entry = dynamic_cast( item ); + if ( entry ) { + bool disable = ( item->checkState( col ) == Qt::Unchecked ); + KDesktopFile kc(entry->fileName().path()); + KConfigGroup grp = kc.desktopGroup(); + if ( grp.hasKey( "Hidden" ) && !disable) { + grp.deleteEntry( "Hidden" ); + } + else + grp.writeEntry("Hidden", disable); + + kc.sync(); + if ( disable ) + item->setText( COL_STATUS, i18nc( "The program won't be run", "Disabled" ) ); + else + item->setText( COL_STATUS, i18nc( "The program will be run", "Enabled" ) ); + } + } +} + +void Autostart::addItem( DesktopStartItem* item, const QString& name, const QString& run, const QString& command, bool disabled ) +{ + Q_ASSERT( item ); + item->setText( COL_NAME, name ); + item->setText( COL_RUN, run ); + item->setText( COL_COMMAND, command ); + item->setCheckState( COL_STATUS, disabled ? Qt::Unchecked : Qt::Checked ); + item->setText( COL_STATUS, disabled ? i18nc( "The program won't be run", "Disabled" ) : i18nc( "The program will be run", "Enabled" )); +} + +void Autostart::addItem(ScriptStartItem* item, const QString& name, const QString& command, ScriptStartItem::ENV type ) +{ + Q_ASSERT( item ); + item->setText( COL_NAME, name ); + item->setText( COL_COMMAND, command ); + item->changeStartup( type ); +} + + +void Autostart::load() +{ + // share/autostart may *only* contain .desktop files + // shutdown and env may *only* contain scripts, links or binaries + // autostart on the otherhand may contain all of the above. + // share/autostart is special as it overrides entries found in $KDEDIR/share/autostart + m_paths << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/autostart/") + << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/shutdown/") + << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/env/") + << QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/share/autostart/"); // For Importing purposes + + // share/autostart shouldn't be an option as this should be reserved for global autostart entries + m_pathName << i18n("Startup") + << i18n("Shutdown") + << i18n("Pre-KDE startup") + ; + widget->listCMD->clear(); + + m_programItem = new QTreeWidgetItem( widget->listCMD ); + m_programItem->setText( 0, i18n( "Desktop File" )); + m_programItem->setFlags(m_programItem->flags()^Qt::ItemIsSelectable ); + + QFont boldFont = m_programItem->font(0); + boldFont.setBold( true ); + m_programItem->setData ( 0, Qt::FontRole, boldFont ); + + m_scriptItem = new QTreeWidgetItem( widget->listCMD ); + m_scriptItem->setText( 0, i18n( "Script File" )); + m_scriptItem->setFlags(m_scriptItem->flags()^Qt::ItemIsSelectable); + m_scriptItem->setData ( 0, Qt::FontRole, boldFont); + + widget->listCMD->expandItem( m_programItem ); + widget->listCMD->expandItem( m_scriptItem ); + + foreach (const QString& path, m_paths) { + QDir d(path); + if (!d.exists()) + d.mkpath(path); + + QDir autostartdir( path ); + autostartdir.setFilter( QDir::Files ); + const QFileInfoList list = autostartdir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fi = list.at(i); + QString filename = fi.fileName(); + bool desktopFile = filename.endsWith(".desktop"); + if ( desktopFile ) + { + KDesktopFile config(fi.absoluteFilePath()); + //kDebug() << fi.absoluteFilePath() << "trying" << config.desktopGroup().readEntry("Exec"); + QStringList commandLine = KShell::splitArgs(config.desktopGroup().readEntry("Exec")); + if (commandLine.isEmpty()) { + continue; + } + + const QString exe = commandLine.first(); + if (exe.isEmpty() || QStandardPaths::findExecutable(exe).isEmpty()) { + continue; + } + + DesktopStartItem *item = new DesktopStartItem( fi.absoluteFilePath(), m_programItem, this ); + + const KConfigGroup grp = config.desktopGroup(); + const bool hidden = grp.readEntry("Hidden", false); + const QStringList notShowList = grp.readXdgListEntry("NotShowIn"); + const QStringList onlyShowList = grp.readXdgListEntry("OnlyShowIn"); + + const bool disabled = hidden || + notShowList.contains("KDE") || + (!onlyShowList.isEmpty() && !onlyShowList.contains("KDE")); + + int indexPath = m_paths.indexOf((item->fileName().adjusted(QUrl::RemoveFilename).toString() ) ); + if ( indexPath > 2 ) + indexPath = 0; //.kde/share/autostart and .config/autostart load destkop at startup + addItem(item, config.readName(), m_pathName.value(indexPath), grp.readEntry("Exec"), disabled ); + } + else + { + ScriptStartItem *item = new ScriptStartItem( fi.absoluteFilePath(), m_scriptItem,this ); + int typeOfStartup = m_paths.indexOf((item->fileName().adjusted(QUrl::RemoveFilename).toString()) ); + ScriptStartItem::ENV type = ScriptStartItem::START; + switch( typeOfStartup ) + { + case 0: + type =ScriptStartItem::START; + break; + case 1: + type = ScriptStartItem::SHUTDOWN; + break; + case 2: + type = ScriptStartItem::PRE_START; + break; + default: + qDebug()<<" type is not defined :"<listCMD->resizeColumnToContents(COL_NAME); + //widget->listCMD->resizeColumnToContents(COL_COMMAND); + widget->listCMD->resizeColumnToContents(COL_STATUS); + widget->listCMD->resizeColumnToContents(COL_RUN); +} + +void Autostart::slotAddProgram() +{ + KOpenWithDialog owdlg( this ); + if (owdlg.exec() != QDialog::Accepted) + return; + + KService::Ptr service = owdlg.service(); + + Q_ASSERT(service); + if (!service) { + return; // Don't crash if KOpenWith wasn't able to create service. + } + + // It is important to ensure that we make an exact copy of an existing + // desktop file (if selected) to enable users to override global autostarts. + // Also see + // https://bugs.launchpad.net/ubuntu/+source/kde-workspace/+bug/923360 + QString desktopPath; + QUrl desktopTemplate; + if ( service->desktopEntryName().isEmpty() ) { + // Build custom desktop file (e.g. when the user entered an executable + // name in the OpenWithDialog). + desktopPath = m_paths[4] + service->name() + ".desktop"; + desktopTemplate = QUrl( desktopPath ); + KConfig kc(desktopTemplate.path(), KConfig::SimpleConfig); + KConfigGroup kcg = kc.group("Desktop Entry"); + kcg.writeEntry("Exec",service->exec()); + kcg.writeEntry("Icon","system-run"); + kcg.writeEntry("Path",""); + kcg.writeEntry("Terminal",false); + kcg.writeEntry("Type","Application"); + kc.sync(); + + KPropertiesDialog dlg( desktopTemplate, this ); + if ( dlg.exec() != QDialog::Accepted ) + { + return; + } + } + else + { + // Use existing desktop file and use same file name to enable overrides. + desktopPath = m_paths[4] + service->desktopEntryName() + ".desktop"; + desktopTemplate = QUrl( QStandardPaths::locate(QStandardPaths::ApplicationsLocation, service->entryPath()) ); + + KPropertiesDialog dlg( desktopTemplate, QUrl(m_paths[4]), service->desktopEntryName() + ".desktop", this ); + if ( dlg.exec() != QDialog::Accepted ) + return; + } + DesktopStartItem * item = new DesktopStartItem( desktopPath, m_programItem,this ); + addItem( item, service->name(), m_pathName[0], service->exec() , false); +} + +void Autostart::slotAddScript() +{ + AddScriptDialog * addDialog = new AddScriptDialog(this); + int result = addDialog->exec(); + if (result == QDialog::Accepted) { + if (addDialog->symLink()) + KIO::link(addDialog->importUrl(), QUrl(m_paths[0])); + else + KIO::copy(addDialog->importUrl(), QUrl(m_paths[0])); + + ScriptStartItem * item = new ScriptStartItem( m_paths[0] + addDialog->importUrl().fileName(), m_scriptItem,this ); + addItem( item, addDialog->importUrl().fileName(), addDialog->importUrl().fileName(),ScriptStartItem::START ); + } + delete addDialog; +} + +void Autostart::slotRemoveCMD() +{ + QTreeWidgetItem* item = widget->listCMD->currentItem(); + if (!item) + return; + DesktopStartItem *startItem = dynamic_cast( item ); + if ( startItem ) + { + m_programItem->takeChild( m_programItem->indexOfChild( startItem ) ); + KIO::del(startItem->fileName()); + delete item; + } + else + { + ScriptStartItem * scriptItem = dynamic_cast( item ); + if ( scriptItem ) + { + m_scriptItem->takeChild( m_scriptItem->indexOfChild( scriptItem ) ); + KIO::del(scriptItem->fileName()); + delete item; + } + } +} + +void Autostart::slotEditCMD(QTreeWidgetItem* ent) +{ + if (!ent) return; + AutoStartItem *entry = dynamic_cast( ent ); + if ( entry ) + { + const KFileItem kfi = KFileItem( KFileItem::Unknown, KFileItem::Unknown, QUrl( entry->fileName() ), true ); + if (! slotEditCMD( kfi )) + return; + DesktopStartItem *desktopEntry = dynamic_cast( entry ); + if (desktopEntry) { + KService service(desktopEntry->fileName().path()); + addItem( desktopEntry, service.name(), m_pathName.value(m_paths.indexOf(desktopEntry->fileName().adjusted(QUrl::RemoveFilename).toString())), service.exec(),false ); + } + } +} + +bool Autostart::slotEditCMD( const KFileItem &item) +{ + KPropertiesDialog dlg( item, this ); + bool c = ( dlg.exec() == QDialog::Accepted ); + return c; +} + +void Autostart::slotEditCMD() +{ + if ( widget->listCMD->currentItem() == 0 ) + return; + slotEditCMD( (AutoStartItem*)widget->listCMD->currentItem() ); +} + +void Autostart::slotAdvanced() +{ + if ( widget->listCMD->currentItem() == 0 ) + return; + + DesktopStartItem *entry = static_cast( widget->listCMD->currentItem() ); + KDesktopFile kc(entry->fileName().path()); + KConfigGroup grp = kc.desktopGroup(); + bool status = false; + QStringList lstEntry; + if (grp.hasKey("OnlyShowIn")) + { + lstEntry = grp.readXdgListEntry("OnlyShowIn"); + status = lstEntry.contains("KDE"); + } + + AdvancedDialog *dlg = new AdvancedDialog( this,status ); + if ( dlg->exec() ) + { + status = dlg->onlyInKde(); + if ( lstEntry.contains( "KDE" ) && !status ) + { + lstEntry.removeAll( "KDE" ); + grp.writeXdgListEntry( "OnlyShowIn", lstEntry ); + } + else if ( !lstEntry.contains( "KDE" ) && status ) + { + lstEntry.append( "KDE" ); + grp.writeXdgListEntry( "OnlyShowIn", lstEntry ); + } + } + delete dlg; +} + +void Autostart::slotChangeStartup( ScriptStartItem* item, int index ) +{ + Q_ASSERT(item); + + if ( item ) + { + item->setPath(m_paths.value(index)); + widget->listCMD->setCurrentItem( item ); + if ( ( index == 2 ) && !item->fileName().path().endsWith( ".sh" )) + KMessageBox::information( this, i18n( "Only files with “.sh” extensions are allowed for setting up the environment." ) ); + + } +} + +void Autostart::slotSelectionChanged() +{ + const bool hasItems = ( dynamic_cast( widget->listCMD->currentItem() )!=0 ) ; + widget->btnRemove->setEnabled(hasItems); + + const bool isDesktopItem = (dynamic_cast(widget->listCMD->currentItem() ) != 0) ; + widget->btnProperties->setEnabled(isDesktopItem); + widget->btnAdvanced->setEnabled(isDesktopItem) ; +} + +void Autostart::defaults() +{ +} + +void Autostart::save() +{ +} + +#include "autostart.moc" diff --git a/kcms/autostart/autostart.desktop b/kcms/autostart/autostart.desktop new file mode 100644 index 0000000000..5a1048e724 --- /dev/null +++ b/kcms/autostart/autostart.desktop @@ -0,0 +1,190 @@ +[Desktop Entry] +Exec=kcmshell5 autostart +Icon=system-run +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/autostart/index.html + +X-KDE-Library=kcm_autostart +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=startup-and-shutdown + +Name=Autostart +Name[af]=Outomatiese begin +Name[ar]=البدء التلقائي +Name[ast]=Autoarranque +Name[be]=Аўтаматычны запуск +Name[be@latin]=Aŭtamatyčnaje ŭklučeńnie +Name[bg]=Автоматично стартиране +Name[bn]=অটো-স্টার্ট +Name[bn_IN]=স্বয়ং-আরম্ভ +Name[br]=Emloc'h +Name[bs]=Samopokretanje +Name[ca]=Inici automàtic +Name[ca@valencia]=Inici automàtic +Name[cs]=Automatické spuštění +Name[csb]=Aùtomatné zrëszanié +Name[cy]=Hunan-gychwyn +Name[da]=Autostart +Name[de]=Autostart +Name[el]=Αυτόματη εκκίνηση +Name[en_GB]=Autostart +Name[eo]=Aŭtomata lanĉo +Name[es]=Autoarranque +Name[et]=Autostart +Name[eu]=Hasiera automatikoa +Name[fa]=آغاز خودکار +Name[fi]=Automaattikäynnistys +Name[fr]=Démarrage automatique +Name[fy]=Auto-úteinsette +Name[ga]=Tosú uathoibríoch +Name[gl]=Inicio automático +Name[gu]=આપમેળેશરૂ +Name[he]=הפעלה אוטומטית +Name[hi]=स्वतःप्रारंभ +Name[hne]=खुद से चालू +Name[hr]=Automatsko pokretanje +Name[hsb]=Awtostart +Name[hu]=Automatikus indítás +Name[ia]=Auto starta +Name[id]=Start Otomatis +Name[is]=Sjálfræsing +Name[it]=Avvio automatico +Name[ja]=自動起動 +Name[ka]=ავტოგაშვება +Name[kk]=Автобастау +Name[km]=ចាប់ផ្ដើម​ស្វ័យប្រវត្តិ +Name[kn]=ಸ್ವಯಮಾರಂಭ +Name[ko]=자동 시작 +Name[ku]=Bixweber Bide Destpêkirin +Name[lt]=Autostartas +Name[lv]=Autopalaišana +Name[mai]=स्वतः चालू +Name[mk]=Автостарт +Name[ml]=ഓട്ടോസ്റ്റാര്‍ട്ട് +Name[mr]=स्वप्रारंभ +Name[ms]=Automula +Name[nb]=Autostart +Name[nds]=Autostart +Name[nl]=Autostart +Name[nn]=Autostart +Name[or]=ସ୍ୱୟଂଚାଳନ +Name[pa]=ਆਟੋ-ਸਟਾਰਟ +Name[pl]=Samoczynne uruchamianie +Name[pt]=Arranque +Name[pt_BR]=Iniciar automaticamente +Name[ro]=Pornire automată +Name[ru]=Автозапуск +Name[si]=ක්‍ෂණික ඇරඹුම +Name[sk]=Automatické spustenie +Name[sl]=Samodejni zagon +Name[sr]=Самопокретање +Name[sr@ijekavian]=Самопокретање +Name[sr@ijekavianlatin]=Samopokretanje +Name[sr@latin]=Samopokretanje +Name[sv]=Automatisk start +Name[ta]=சுயதுவக்கம் +Name[te]=స్వయంచాలకప్రారంభం +Name[tg]=Худоғозӣ +Name[th]=เริ่มอัตโนมัติ +Name[tr]=Otomatik Başlat +Name[ug]=ئۆزلۈكىدىن قوزغات +Name[uk]=Автозапуск +Name[uz]=Avto-boshlash +Name[uz@cyrillic]=Авто-бошлаш +Name[vi]=Tự khởi chạy +Name[wa]=Enondaedje tot seu +Name[xh]=Isiqalo esizenzekelayo +Name[x-test]=xxAutostartxx +Name[zh_CN]=自动启动 +Name[zh_TW]=自動啟動 + +Comment=Manage which programs start up automatically with KDE. +Comment[bs]=Upravljanje koji će se programi automatski pokretati pomoću KDE. +Comment[ca]=Gestiona quins programes s'iniciaran automàticament amb el KDE. +Comment[ca@valencia]=Gestiona quins programes s'iniciaran automàticament amb el KDE. +Comment[cs]=Spravujte automatické spouštění programů při startu KDE. +Comment[da]=Håndtér hvilke programmer der automatisk starter op med KDE. +Comment[de]=Verwaltung der automatisch mit KDE zu startenden Anwendungen. +Comment[el]=Διαχείριση των προγραμμάτων που θα ξεκινούν αυτόματα με το KDE. +Comment[es]=Gestionar qué programas se inician automáticamente con KDE. +Comment[et]=Määramine, millised programmid käivituvad automaatselt koos KDE-ga. +Comment[eu]=KDErekin automatikoki abiatuko diren programak kudeatu. +Comment[fi]=Aseta, mitkä ohjelmat käynnistetään automaattisesti KDE:n käynnistyessä. +Comment[fr]=Gère les programmes démarrant automatiquement avec KDE. +Comment[ga]=Bainistigh na ríomhchláir a thosaíonn nuair a thosaíonn KDE. +Comment[gl]=Xestiona os programas que se inician xunto con KDE. +Comment[he]=נהל אילו תוכניות מופעלות ביחד עם KDE. +Comment[hu]=Annak kezelése, hogy mely programok induljanak automatikusan a KDE-vel. +Comment[ia]=Gere qual programma debe startar automaticamente con KDE. +Comment[is]=Stjórntæki til að stilla hvaða forrit eigi að ræsast sjálfkrafa með KDE. +Comment[it]=Gestisci quali programmi avviare automaticamente assieme a KDE. +Comment[kk]=KDE бастағанда автожегілетін бағдарламаларды басқару. +Comment[ko]=KDE를 시작할 때 같이 시작될 프로그램을 관리합니다. +Comment[lt]=Konfigūravimo įrankis valdyti programas, kurios paleidžiamos automatiškai kartu su KDE. +Comment[mr]=केडीई सह कोणते कार्यक्रम स्वप्रारंभ होतील ते नियंत्रीत करा. +Comment[nb]=Styr hvilke program som skal starte automatisk med KDE. +Comment[nds]=Programmen fastleggen, de automaatsch mit KDE opropen warrt +Comment[nl]=Beheren van programma's die automatisch met KDE opstarten. +Comment[pa]=ਪਰਬੰਧ ਕਰਦੀ ਹੈ ਕਿ ਕਿਹੜੇ ਪਰੋਗਰਾਮ ਕੇਡੀਈ (KDE) ਨਾਲ ਆਪਣੇ-ਆਪਣ ਚੱਲਣ। +Comment[pl]=Zdecyduj, które programy mają się uruchamiać wraz ze startem KDE. +Comment[pt]=Gerir os programas que são arrancados automaticamente com o KDE. +Comment[pt_BR]=Gerencia os programas que são carregados automaticamente com o KDE. +Comment[ro]=Gestionează ce programe se pornesc automat împreună cu KDE. +Comment[ru]=Управление программами, запускаемыми автоматически в начале сеанса KDE +Comment[sk]=Spravovať, ktoré programy spustiť automaticky s KDE. +Comment[sl]=Upravljanje programov, ki se samodejno zaženejo ob zagonu KDE. +Comment[sr]=Одредите који се програми покрећу са КДЕ‑ом по пријављивању. +Comment[sr@ijekavian]=Одредите који се програми покрећу са КДЕ‑ом по пријављивању. +Comment[sr@ijekavianlatin]=Odredite koji se programi pokreću sa KDE‑om po prijavljivanju. +Comment[sr@latin]=Odredite koji se programi pokreću sa KDE‑om po prijavljivanju. +Comment[sv]=Hantera vilka program som startas automatiskt när KDE startas. +Comment[tr]=Hangi programların KDE açılırken otomatik olarak başlatılacağını yönetin. +Comment[uk]=Керування програмами, які будуть запускатися разом з графічним середовищем KDE автоматично. +Comment[x-test]=xxManage which programs start up automatically with KDE.xx +Comment[zh_CN]=管理随 KDE 自动启动的程序 +Comment[zh_TW]=管理 KDE 要自動啟動哪些程式。 + +X-KDE-Keywords=Autostart Manager,autostart,startup,system startup,kde start,cron +X-KDE-Keywords[bs]=automatsko pokretanje upravitelja,automatsko pokretanje,pokretanje,sustav za pokretanje,početak kde,kompjuter izvodi zadatak za određeno vrijeme. +X-KDE-Keywords[ca]=Gestor d'inici automàtic,inici automàtic,inici,inici del sistema,inici del kde,cron +X-KDE-Keywords[ca@valencia]=Gestor d'inici automàtic,inici automàtic,inici,inici del sistema,inici del kde,cron +X-KDE-Keywords[da]=autostart,opstart,systemstart,kde start,cron +X-KDE-Keywords[de]=Autostartverwaltung,Autostart,Startvorgang,Systemstart,KDE-Start,Cron +X-KDE-Keywords[el]=διαχειριστής αυτόματης εκκίνησης,αυτόματη εκκίνηση,έναρξη,έναρξη συστήματος,έναρξη kde,cron +X-KDE-Keywords[es]=Gestor de inicio automático,inicio automático,inicio,inicio del sistema,inicio de kde,cron +X-KDE-Keywords[et]=Autostardi haldur,autostart,käivitamine,süsteemi käivitamine,kde käivitamine,cron +X-KDE-Keywords[eu]=Hasiera automatikoaren kudeatzailea,hasiera automatikoa,abiarazi,sistema abiarazi,kde hasi,cron +X-KDE-Keywords[fi]=automaattikäynnistys,hallinta,käynnistys,järjestelmän käynnistys, järjestelmän käynnistyminen,kde:n käynnistys,kde:n käynnistyminen,cron +X-KDE-Keywords[fr]=Gestionnaire de démarrage, démarrage automatique, démarrage, démarrage du système, démarrage de kde, cron +X-KDE-Keywords[gl]=Xestor de inicio, inicio automático, inicio, sistema de arranque, inicio de kde, cron +X-KDE-Keywords[he]=Autostart Manager,autostart,startup,system startup,kde start,cron,הפעלה,התחלה +X-KDE-Keywords[hu]=Automatikus indítás kezelő,automatikus indítás,indulás,rendszerindulás,kde indulás,cron +X-KDE-Keywords[ia]=Gestor de autoinitio,autoinitio,initio,initio de systema.initio de kde,crom +X-KDE-Keywords[it]=Gestore avvio,avvio automatico,avvio,avvio del sistema,avvio di kde,cron +X-KDE-Keywords[kk]=Autostart Manager,autostart,startup,system startup,kde start,cron +X-KDE-Keywords[km]=ចាប់ផ្ដើម​កម្មវិធី​គ្រប់គ្រង​ដោយ​ស្វ័យ​ប្រវត្តិ ចាប់ផ្ដើម​ស្វ័យ​ប្រវត្តិ ចាប់ផ្ដើម ចាប់ផ្ដើម​ប្រព័ន្ធ ចាប់ផ្ដើម kde cron +X-KDE-Keywords[ko]=Autostart Manager,autostart,startup,system startup,kde start,cron,자동 시작,자동시작,시작프로그램,시스템 시작 +X-KDE-Keywords[lt]=Automatinio paleidimo tvarkyklė,automatinis paleidimas, sistemos paleidimas,kde paleidimas,cron +X-KDE-Keywords[mr]=स्वप्रारंभ व्यवस्थापक, स्वप्रारंभ, सुरुवात, सुरुवात प्रणाली, kde सुरुवात, क्रॉन +X-KDE-Keywords[nb]=Autostartbehandler,autostart,oppstart,systemstart,kde-start,cron +X-KDE-Keywords[nds]=Autostartpleger,Autostart,Starten,Hoochfohren,KDE-Start,Cron +X-KDE-Keywords[nl]=Autostartbeheerder,autostarten,opstarten,opstarten systeem,opstarten kde,cron +X-KDE-Keywords[pl]=Menadżer autostartu,autostart,uruchamianie,uruchamianie systemu,kde start,cron +X-KDE-Keywords[pt]=Gestor de arranque,arranque,início,arranque do sistema,início do kde,cron +X-KDE-Keywords[pt_BR]=Gerenciado de inicialização,inicialização,início,inicialização do sistema,início do kde,cron +X-KDE-Keywords[ru]=Autostart Manager,autostart,startup,system startup,kde start,cron,диспетчер автоматического запуска,автоматический запуск,автозапуск,загрузка системы,запуск kde +X-KDE-Keywords[sk]=Správca automatického spustenia,autostart,spustenie,spustenie systému,štart kde,cron +X-KDE-Keywords[sl]=upravljalnik samodejnega zagona,samodejni zagon,zagon,sistemski zagon,zagon kde,zagon sistema,cron +X-KDE-Keywords[sr]=Autostart Manager,autostart,startup,system startup,kde start,cron,самопокретање,менаџер самопокретања,покретање система +X-KDE-Keywords[sr@ijekavian]=Autostart Manager,autostart,startup,system startup,kde start,cron,самопокретање,менаџер самопокретања,покретање система +X-KDE-Keywords[sr@ijekavianlatin]=Autostart Manager,autostart,startup,system startup,kde start,cron,samopokretanje,menadžer samopokretanja,pokretanje sistema +X-KDE-Keywords[sr@latin]=Autostart Manager,autostart,startup,system startup,kde start,cron,samopokretanje,menadžer samopokretanja,pokretanje sistema +X-KDE-Keywords[sv]=Hantering av autostart,autostart,start,systemstart,kde-start,cron +X-KDE-Keywords[tr]=Otomatik Başlatma Yöneticisi, otomatik,başlatma,sistem başlangıcı,kde başlangıcı,görevler,cron +X-KDE-Keywords[uk]=Autostart Manager,autostart,startup,system startup,kde start,cron,керування автозапуском,автозапуск,запуск,запуск системи,запуск kde +X-KDE-Keywords[vi]=trình quản lý tự động chạy,tự động chạy,khởi động,khởi động hệ thống,chạy kde,cron +X-KDE-Keywords[x-test]=xxAutostart Manager,autostart,startup,system startup,kde start,cronxx +X-KDE-Keywords[zh_CN]=Autostart Manager,autostart,startup,system startup,kde start,cron,自动启动管理器,自动启动,启动,系统启动,kde 启动,任务调度 +X-KDE-Keywords[zh_TW]=Autostart Manager,autostart,startup,system startup,kde start,cron diff --git a/kcms/autostart/autostart.h b/kcms/autostart/autostart.h new file mode 100644 index 0000000000..11675e1eaf --- /dev/null +++ b/kcms/autostart/autostart.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2006-2007 by Stephen Leaf * + * smileaf@gmail.com * + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 AUTOSTART_H +#define AUTOSTART_H + +#include +#include + +#include +#include + +#include "ui_autostartconfig.h" +#include "autostartitem.h" + +class Autostart: public KCModule +{ + Q_OBJECT + +public: + Autostart( QWidget* parent, const QVariantList& ); + ~Autostart(); + enum COL_TYPE { COL_NAME = 0, COL_COMMAND=1, COL_STATUS=2,COL_RUN=3 }; + void load(); + void save(); + void defaults(); + + QStringList listPathName() const { return m_pathName;} + +public Q_SLOTS: + void slotChangeStartup( ScriptStartItem* item, int index ); + +protected: + void addItem(DesktopStartItem *item, const QString& name, const QString& run, const QString& command, bool disabled ); + void addItem(ScriptStartItem *item, const QString& name, const QString& command, ScriptStartItem::ENV type ); + +private Q_SLOTS: + void slotAddProgram(); + void slotAddScript(); + void slotRemoveCMD(); + void slotEditCMD(QTreeWidgetItem*); + bool slotEditCMD(const KFileItem&); + void slotEditCMD(); + void slotSelectionChanged(); + void slotItemClicked( QTreeWidgetItem *, int); + void slotAdvanced(); + +private: + QTreeWidgetItem *m_programItem, *m_scriptItem; + QStringList m_paths; + QStringList m_pathName; + + Ui_AutostartConfig *widget; +}; + +#endif diff --git a/kcms/autostart/autostartconfig.ui b/kcms/autostart/autostartconfig.ui new file mode 100644 index 0000000000..6dfdb8b87c --- /dev/null +++ b/kcms/autostart/autostartconfig.ui @@ -0,0 +1,82 @@ + + AutostartConfig + + + + 0 + 0 + 553 + 384 + + + + + + + false + + + false + + + + + + + Add Program... + + + + + + + Add Script... + + + + + + + &Remove + + + + + + + &Properties... + + + + + + + Qt::Vertical + + + + 79 + 141 + + + + + + + + Qt::Horizontal + + + + + + + Advanced... + + + + + + + + diff --git a/kcms/autostart/autostartitem.cpp b/kcms/autostart/autostartitem.cpp new file mode 100644 index 0000000000..4607408325 --- /dev/null +++ b/kcms/autostart/autostartitem.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "autostartitem.h" +#include "autostart.h" + +#include +#include +#include +#include +#include + +#include +#include + +AutoStartItem::AutoStartItem( const QString &service, QTreeWidgetItem *parent, Autostart* ) + : QTreeWidgetItem( parent ) + , m_fileName(service) +{ +} + +AutoStartItem::~AutoStartItem() +{ + +} + +QUrl AutoStartItem::fileName() const +{ + return m_fileName; +} + +void AutoStartItem::setPath(const QString &path) +{ + Q_ASSERT( path.endsWith(QDir::separator()) ); + + if (QUrl(path) == m_fileName.adjusted(QUrl::RemoveFilename)) + return; + + const QString& newFileName = path + m_fileName.fileName(); + KIO::move(m_fileName, QUrl(newFileName)); + + m_fileName = QUrl(newFileName); +} + +DesktopStartItem::DesktopStartItem( const QString &service, QTreeWidgetItem *parent, Autostart*autostart ) + : AutoStartItem( service, parent,autostart ) +{ + setCheckState ( Autostart::COL_STATUS,Qt::Checked ); +} + +DesktopStartItem::~DesktopStartItem() +{ +} + +ScriptStartItem::ScriptStartItem( const QString &service, QTreeWidgetItem *parent, Autostart* autostart ) + : AutoStartItem( service, parent,autostart ) +{ + m_comboBoxStartup = new QComboBox; + m_comboBoxStartup->addItems( autostart->listPathName() ); + + setText( 2, i18nc( "The program will be run", "Enabled" ) ); + QObject::connect( m_comboBoxStartup,SIGNAL(activated(int)),this,SLOT(slotStartupChanged(int)) ); + QObject::connect( this,SIGNAL(askChangeStartup(ScriptStartItem*,int)),autostart,SLOT(slotChangeStartup(ScriptStartItem*,int)) ); + treeWidget()->setItemWidget ( this, Autostart::COL_RUN, m_comboBoxStartup ); +} + +ScriptStartItem::~ScriptStartItem() +{ +} + +void ScriptStartItem::slotStartupChanged(int index) +{ + emit askChangeStartup(this, index); +} + +void ScriptStartItem::changeStartup(ScriptStartItem::ENV type ) +{ + switch( type ) + { + case ScriptStartItem::START: + m_comboBoxStartup->setCurrentIndex( 0 ); + break; + case ScriptStartItem::SHUTDOWN: + m_comboBoxStartup->setCurrentIndex( 1 ); + break; + case ScriptStartItem::PRE_START: + m_comboBoxStartup->setCurrentIndex( 2 ); + break; + default: + qWarning() << " startup type is not defined :" << type; + break; + } +} + +#include "autostartitem.moc" diff --git a/kcms/autostart/autostartitem.h b/kcms/autostart/autostartitem.h new file mode 100644 index 0000000000..2e305bb393 --- /dev/null +++ b/kcms/autostart/autostartitem.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2008 by Montel Laurent * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 AUTOSTARTITEM_H +#define AUTOSTARTITEM_H + +#include +#include +#include + +class QComboBox; +class QTreeWidget; +class Autostart; + +class AutoStartItem : public QTreeWidgetItem, public QObject +{ +public: + AutoStartItem( const QString &service, QTreeWidgetItem *parent, Autostart* ); + ~AutoStartItem(); + + QUrl fileName() const; + + void setPath(const QString &path); + +private: + QUrl m_fileName; +}; + +class DesktopStartItem : public AutoStartItem +{ +public: + DesktopStartItem( const QString &service, QTreeWidgetItem *parent, Autostart* ); + ~DesktopStartItem(); +}; + + +class ScriptStartItem : public AutoStartItem +{ + Q_OBJECT + +public: + enum ENV { START=0, SHUTDOWN=1, PRE_START=2}; //rename + ScriptStartItem( const QString &service, QTreeWidgetItem *parent, Autostart* ); + ~ScriptStartItem(); + + void changeStartup( ScriptStartItem::ENV type ); + +Q_SIGNALS: + void askChangeStartup(ScriptStartItem* item, int index); + +private Q_SLOTS: + + void slotStartupChanged(int index); + +private: + QComboBox *m_comboBoxStartup; +}; + +#endif diff --git a/kcms/bell/CMakeLists.txt b/kcms/bell/CMakeLists.txt new file mode 100644 index 0000000000..772b65c15c --- /dev/null +++ b/kcms/bell/CMakeLists.txt @@ -0,0 +1,28 @@ + + + +########### next target ############### + +set(kcm_bell_PART_SRCS bell.cpp ) + + +add_library(kcm_bell MODULE ${kcm_bell_PART_SRCS}) + + +target_link_libraries(kcm_bell + Qt5::X11Extras + KF5::KCMUtils + KF5::I18n + KF5::Notifications + KF5::WindowSystem + KF5::KDE4Support + ${X11_X11_LIB}) + +install(TARGETS kcm_bell DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES bell.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + +ecm_install_icons( ${ICON_INSTALL_DIR} ) diff --git a/kcms/bell/Messages.sh b/kcms/bell/Messages.sh new file mode 100644 index 0000000000..cb6a47821d --- /dev/null +++ b/kcms/bell/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kcmbell.pot diff --git a/kcms/bell/bell.cpp b/kcms/bell/bell.cpp new file mode 100644 index 0000000000..2bf9423d1e --- /dev/null +++ b/kcms/bell/bell.cpp @@ -0,0 +1,257 @@ +/* + Copyright (c) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) + 1998 Bernd Wuebben + 2000 Matthias Elter + 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; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + + +//Added by qt3to4: +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bell.h" + +#include +#include +#include +#include +#include +#include + + + +K_PLUGIN_FACTORY(KBellConfigFactory, registerPlugin();) +K_EXPORT_PLUGIN(KBellConfigFactory("kcmbell")) + + + +extern "C" +{ + Q_DECL_EXPORT void kcminit_bell() + { + XKeyboardState kbd; + XKeyboardControl kbdc; + + XGetKeyboardControl(QX11Info::display(), &kbd); + + KConfig _config( "kcmbellrc", KConfig::NoGlobals ); + KConfigGroup config(&_config, "General"); + + kbdc.bell_percent = config.readEntry("Volume", kbd.bell_percent); + kbdc.bell_pitch = config.readEntry("Pitch", kbd.bell_pitch); + kbdc.bell_duration = config.readEntry("Duration", kbd.bell_duration); + XChangeKeyboardControl(QX11Info::display(), + KBBellPercent | KBBellPitch | KBBellDuration, + &kbdc); + } +} + +KBellConfig::KBellConfig(QWidget *parent, const QVariantList &args): + KCModule(parent, args) +{ + QBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + + QGroupBox *box = new QGroupBox(i18n("Bell Settings"), this ); + QFormLayout *form = new QFormLayout(); + form->setVerticalSpacing(0); + box->setLayout(form); + layout->addWidget(box); + + m_useBell = new QCheckBox( i18n("&Use system bell instead of system notification" ), box ); + m_useBell->setWhatsThis( i18n("You can use the standard system bell (PC speaker) or a " + "more sophisticated system notification, see the " + "\"System Notifications\" control module for the " + "\"Something Special Happened in the Program\" event.")); + connect(m_useBell, SIGNAL(toggled(bool)), SLOT(useBell(bool))); + form->addRow(m_useBell); + + setQuickHelp( i18n("

    System Bell

    Here you can customize the sound of the standard system bell," + " i.e. the \"beep\" you always hear when there is something wrong. Note that you can further" + " customize this sound using the \"Accessibility\" control module; for example, you can choose" + " a sound file to be played instead of the standard bell.")); + + m_volume = new KIntNumInput(50, box); + m_volume->setRange(0, 100, 5); + m_volume->setSuffix("%"); + m_volume->setSteps(5,25); + form->addRow(i18n("&Volume:"), m_volume); + m_volume->setWhatsThis( i18n("Here you can customize the volume of the system bell. For further" + " customization of the bell, see the \"Accessibility\" control module.") ); + + m_pitch = new KIntNumInput(800, box); + m_pitch->setRange(20, 2000, 20); + m_pitch->setSuffix(i18n(" Hz")); + m_pitch->setSteps(40,200); + form->addRow(i18n("&Pitch:"), m_pitch); + m_pitch->setWhatsThis( i18n("Here you can customize the pitch of the system bell. For further" + " customization of the bell, see the \"Accessibility\" control module.") ); + + m_duration = new KIntNumInput(100, box); + m_duration->setRange(1, 1000, 50); + m_duration->setSuffix(i18n(" msec")); + m_duration->setSteps(20,100); + form->addRow(i18n("&Duration:"), m_duration); + m_duration->setWhatsThis( i18n("Here you can customize the duration of the system bell. For further" + " customization of the bell, see the \"Accessibility\" control module.") ); + + m_testButton = new QPushButton(i18n("&Test"), box); + m_testButton->setObjectName("test"); + form->addRow(QString(), m_testButton); + connect( m_testButton, SIGNAL(clicked()), SLOT(ringBell())); + m_testButton->setWhatsThis( i18n("Click \"Test\" to hear how the system bell will sound using your changed settings.") ); + + // watch for changes + connect(m_volume, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(m_pitch, SIGNAL(valueChanged(int)), SLOT(changed())); + connect(m_duration, SIGNAL(valueChanged(int)), SLOT(changed())); + + KAboutData *about = + new KAboutData(I18N_NOOP("kcmbell"), QString(), i18n("KDE Bell Control Module"), + QString(), QString(), KAboutData::License_GPL, + i18n("(c) 1997 - 2001 Christian Czezatke, Matthias Elter")); + + about->addAuthor(i18n("Christian Czezatke"), i18n("Original author"), QStringLiteral("e9025461@student.tuwien.ac.at")); + about->addAuthor(i18n("Bernd Wuebben"), QString(), QStringLiteral("wuebben@kde.org")); + about->addAuthor(i18n("Matthias Elter"), i18n("Current maintainer"), QStringLiteral("elter@kde.org")); + about->addAuthor(i18n("Carsten Pfeiffer"), QString(), QStringLiteral("pfeiffer@kde.org")); + setAboutData(about); +} + +void KBellConfig::load() +{ + XKeyboardState kbd; + XGetKeyboardControl(QX11Info::display(), &kbd); + + m_volume->setValue(kbd.bell_percent); + m_pitch->setValue(kbd.bell_pitch); + m_duration->setValue(kbd.bell_duration); + + KConfig _cfg("kdeglobals", KConfig::NoGlobals); + KConfigGroup cfg(&_cfg, "General"); + m_useBell->setChecked(cfg.readEntry("UseSystemBell", false)); + useBell(m_useBell->isChecked()); + emit changed(false); +} + +void KBellConfig::save() +{ + XKeyboardControl kbd; + + int bellVolume = m_volume->value(); + int bellPitch = m_pitch->value(); + int bellDuration = m_duration->value(); + + kbd.bell_percent = bellVolume; + kbd.bell_pitch = bellPitch; + kbd.bell_duration = bellDuration; + XChangeKeyboardControl(QX11Info::display(), + KBBellPercent | KBBellPitch | KBBellDuration, + &kbd); + + KConfig _config("kcmbellrc", KConfig::NoGlobals); + KConfigGroup config(&_config, "General"); + config.writeEntry("Volume",bellVolume); + config.writeEntry("Pitch",bellPitch); + config.writeEntry("Duration",bellDuration); + + config.sync(); + + KConfig _cfg("kdeglobals", KConfig::NoGlobals); + KConfigGroup cfg(&_cfg, "General"); + cfg.writeEntry("UseSystemBell", m_useBell->isChecked()); + cfg.sync(); + + if (!m_useBell->isChecked()) + { + KConfig config("kaccessrc"); + + KConfigGroup group = config.group("Bell"); + group.writeEntry("SystemBell", false); + group.writeEntry("ArtsBell", false); + group.writeEntry("VisibleBell", false); + } +} + +void KBellConfig::ringBell() +{ + if (!m_useBell->isChecked()) { + KNotification::beep(QString(), this); + return; + } + + // store the old state + XKeyboardState old_state; + XGetKeyboardControl(QX11Info::display(), &old_state); + + // switch to the test state + XKeyboardControl kbd; + kbd.bell_percent = m_volume->value(); + kbd.bell_pitch = m_pitch->value(); + if (m_volume->value() > 0) + kbd.bell_duration = m_duration->value(); + else + kbd.bell_duration = 0; + XChangeKeyboardControl(QX11Info::display(), + KBBellPercent | KBBellPitch | KBBellDuration, + &kbd); + // ring bell + XBell(QX11Info::display(),0); + + // restore old state + kbd.bell_percent = old_state.bell_percent; + kbd.bell_pitch = old_state.bell_pitch; + kbd.bell_duration = old_state.bell_duration; + XChangeKeyboardControl(QX11Info::display(), + KBBellPercent | KBBellPitch | KBBellDuration, + &kbd); +} + +void KBellConfig::defaults() +{ + m_volume->setValue(100); + m_pitch->setValue(800); + m_duration->setValue(100); + m_useBell->setChecked( false ); + useBell( false ); +} + +void KBellConfig::useBell( bool on ) +{ + m_volume->setEnabled( on ); + m_pitch->setEnabled( on ); + m_duration->setEnabled( on ); + m_testButton->setEnabled( on ); + changed(); +} + +#include "bell.moc" diff --git a/kcms/bell/bell.desktop b/kcms/bell/bell.desktop new file mode 100644 index 0000000000..04575958f6 --- /dev/null +++ b/kcms/bell/bell.desktop @@ -0,0 +1,242 @@ +[Desktop Entry] +Exec=kcmshell5 bell +Icon=preferences-desktop-notification-bell +Type=Service +X-KDE-ServiceTypes=KCModule,KCModuleInit +X-DocPath=kcontrol/bell/index.html +Categories=Qt;KDE;X-KDE-settings-sound; +X-KDE-OnlyShowOnQtPlatforms=xcb; + +X-KDE-Library=kcm_bell +X-KDE-Init-Symbol=bell +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=application-and-system-notifications +X-KDE-Weight=60 + +Name=System Bell +Name[af]=Stelsel Klok +Name[ar]=جرس النظام +Name[ast]=Pitíu del sistema +Name[be]=Сістэмны званок +Name[be@latin]=Systemny hukavy syhnał +Name[bg]=Системен звук +Name[bn]=সিস্টেম ঘণ্টা +Name[bn_IN]=সিস্টেমের ঘন্টা +Name[br]=Kloc'h ar reizhiad +Name[bs]=Sistemsko zvono +Name[ca]=Timbre del sistema +Name[ca@valencia]=Timbre del sistema +Name[cs]=Systémový zvonek +Name[csb]=Systemowi brzãczk +Name[cy]=Cloch Cysawd +Name[da]=Systemklokke +Name[de]=Signalton +Name[el]=Μεγαφωνάκι συστήματος +Name[en_GB]=System Bell +Name[eo]=Sistempepo +Name[es]=Timbre del sistema +Name[et]=Süsteemne signaal +Name[eu]=Sistemaren soinua +Name[fa]=زنگ سیستم +Name[fi]=Järjestelmän varoitus +Name[fr]=Cloche du système +Name[fy]=Systeembel +Name[ga]=Cloigín an Chórais +Name[gl]=Badalada do sistema +Name[gu]=સિસ્ટમ ઘંટડી +Name[he]=פעמון המערכת +Name[hi]=तंत्र घंटी +Name[hne]=तंत्र घंटी +Name[hr]=Sistemsko zvono +Name[hsb]=Systemowy zwónčk +Name[hu]=Rendszercsengő +Name[ia]=Campana de systema +Name[id]=Bel Sistem +Name[is]=Kerfisbjalla +Name[it]=Campanella di sistema +Name[ja]=システムベル +Name[ka]=სისტემის ხმოვანი სიგნალი +Name[kk]=Жүйелік қоңырау +Name[km]=កណ្ដឹង​ប្រព័ន្ធ +Name[kn]=ವ್ಯವಸ್ಥಾ ಗಂಟೆ +Name[ko]=시스템 종소리 +Name[ku]=Zingila Pergalê +Name[lt]=Sistemos skambutis +Name[lv]=Sistēmas zvans +Name[mai]=तंत्र घंटी +Name[mk]=Системско ѕвонче +Name[ml]=സിസ്റ്റം മണി +Name[mr]=प्रणाली घंटी +Name[ms]=Loceng Sistem +Name[nb]=Systemlyd +Name[nds]=Systeempingel +Name[ne]=प्रणाली बेल +Name[nl]=Systeembel +Name[nn]=Systemlyd +Name[or]=ତନ୍ତ୍ର ଘଣ୍ଟି +Name[pa]=ਸਿਸਟਮ ਘੰਟੀ +Name[pl]=Brzęczyk systemowy +Name[pt]=Campainha do Sistema +Name[pt_BR]=Campainha do sistema +Name[ro]=Clopoțel de sistem +Name[ru]=Системный звуковой сигнал +Name[se]=Vuogádatjietna +Name[si]=පද්ධති සීනුව +Name[sk]=Zvonček +Name[sl]=Sistemski zvonec +Name[sr]=Системско звоно +Name[sr@ijekavian]=Системско звоно +Name[sr@ijekavianlatin]=Sistemsko zvono +Name[sr@latin]=Sistemsko zvono +Name[sv]=Systemsummer +Name[ta]=அமைப்பு மணி +Name[te]=వ్యవస్థ గంట +Name[tg]=Системаи занг +Name[th]=ออดระบบ +Name[tr]=Sistem Zili +Name[ug]=سىستېما قوڭغۇراق ئاۋازى +Name[uk]=Системний дзвінок +Name[uz]=Tizim tovush signali +Name[uz@cyrillic]=Тизим товуш сигнали +Name[vi]=Chuông hệ thống +Name[wa]=Xhuflet do sistinme +Name[xh]=Indlela yokusebenza Yentsimbi +Name[x-test]=xxSystem Bellxx +Name[zh_CN]=系统铃声 +Name[zh_TW]=系統鈴聲 + +Comment=System Bell Configuration +Comment[af]=Stelsel Klok Opstelling +Comment[ar]=إعداد جرس النظام +Comment[ast]=Configuración del pitíu del sistema +Comment[be]=Настаўленне сістэмнага званка +Comment[be@latin]=Nałady systemnaha hukavoha syhnału +Comment[bg]=Настройване звуковия сигнал на системата +Comment[bn]=সিস্টেম ঘণ্টা কনফিগারেশন +Comment[bn_IN]=সিস্টেমের ঘন্টা সংক্রান্ত কনফিগারেশন +Comment[br]=Kefluniañ kloc'h ar reizhiad +Comment[bs]=Postava sistemskog zvona +Comment[ca]=Configuració del timbre del sistema +Comment[ca@valencia]=Configuració del timbre del sistema +Comment[cs]=Nastavení systémového zvonku +Comment[csb]=Kònfigùracëjô systemòwégò brzãczka +Comment[cy]=Gosodiadau'r Cloch Cysawd +Comment[da]=Systemklokkeindstilling +Comment[de]=Einstellungen zum Signalton +Comment[el]=Διαμόρφωση για το μεγαφωνάκι του συστήματός σας +Comment[en_GB]=System Bell Configuration +Comment[eo]=Agordo de la sistempepo +Comment[es]=Configuración del timbre del sistema +Comment[et]=Süsteemse signaali seadistamine +Comment[eu]=Sistemaren soinuaren konfigurazioa +Comment[fa]=پیکربندی زنگ سیستم +Comment[fi]=Järjestelmän varoitusäänen asetus +Comment[fr]=Configuration de la cloche du système +Comment[fy]=Systeemlûden ynstelle +Comment[ga]=Cumraíocht Chloigín an Chórais +Comment[gl]=Configuración da badalada do sistema +Comment[gu]=સિસ્ટમ ઘંટડી રૂપરેખાંકન +Comment[he]=הגדרות פעמון המערכת +Comment[hi]=तंत्र घंटी कॉन्फ़िगरेशन +Comment[hne]=तंत्र घंटी कान्फिगरेसन +Comment[hr]=Konfiguracija sistemskog zvona +Comment[hsb]=Připrawjenje systemoweho zwónčka +Comment[hu]=A rendszercsengő beállításai +Comment[ia]=Configuration del campana de systema +Comment[id]=Konfigurasi Bel Sistem +Comment[is]=Stillingar kerfishljóða +Comment[it]=Configurazione della campanella di sistema +Comment[ja]=システムベルの設定 +Comment[ka]=სისტემის ხმოვანი სიგნალის კონფიგურაცია +Comment[kk]=Жүйелік қоңырауды баптау +Comment[km]=ការ​កំណត់​រចនាសម្ព័ន្ធ​កណ្ដឹង​ប្រព័ន្ធ +Comment[kn]=ವ್ಯವಸ್ಥಾ ಗಂಟೆ ಸಂರಚನೆ +Comment[ko]=시스템 종소리 설정 +Comment[ku]=Veavakirina Zingila Pergalê +Comment[lt]=Sistemos skambučio derinimas +Comment[lv]=Sistēmas zvana konfigurācija +Comment[mai]=तंत्र घंटी कान्फिगरेशन +Comment[mk]=Конфигурација на системското ѕвонче +Comment[ml]=സിസ്റ്റത്തിന്റെ മണിയ്ക്കുള്ള ക്രമീകരണം +Comment[mr]=प्रणाली घंटी संयोजना +Comment[ms]=Konfigurasi Loceng Sistem +Comment[nb]=Oppsett av systemlyd +Comment[nds]=Systeempingel instellen +Comment[ne]=प्रणाली बेल कन्फिगरेसन +Comment[nl]=Systeemgeluiden instellen +Comment[nn]=Systemlydoppsett +Comment[or]=ତନ୍ତ୍ର ଘଣ୍ଟି ସଂରଚନା +Comment[pa]=ਸਿਸਟਮ ਘੰਟੀ ਸੰਰਚਨਾ +Comment[pl]=Konfiguracja brzęczka systemowego +Comment[pt]=Configuração da Campainha do Sistema +Comment[pt_BR]=Configuração da campainha do sistema +Comment[ro]=Configurare Clopoțel de sistem +Comment[ru]=Настройка системного звукового сигнала +Comment[se]=Vuogádatjietnaheivehusat +Comment[si]=පද්ධති සීනු සැකසුම් +Comment[sk]=Nastavenie zvončeka +Comment[sl]=Nastavitve sistemskega zvonca +Comment[sr]=Постава системског звона +Comment[sr@ijekavian]=Постава системског звона +Comment[sr@ijekavianlatin]=Postava sistemskog zvona +Comment[sr@latin]=Postava sistemskog zvona +Comment[sv]=Anpassa systemets summer +Comment[ta]=அமைப்பின் மணி வடிவமைப்பு +Comment[te]=సిస్టమ్ బెల్ సాధనం +Comment[tg]=Танзимоти системаи занг +Comment[th]=ปรับแต่งออดระบบ +Comment[tr]=Sistem Zili Yapılandırması +Comment[ug]=سىستېما قوڭغۇرىقى سەپلىمىسى +Comment[uk]=Налаштування системного дзвінка +Comment[uz]=Tizim tovush signalini moslash +Comment[uz@cyrillic]=Тизим товуш сигналини мослаш +Comment[vi]=Cấu hình Chuông Hệ thống +Comment[wa]=Apontiaedje do xhuflet do sistinme +Comment[xh]=Uqwalaselo Lwendlela Yentsimbi +Comment[x-test]=xxSystem Bell Configurationxx +Comment[zh_CN]=系统铃声配置 +Comment[zh_TW]=系統鈴聲組態 + +X-KDE-Keywords=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker +X-KDE-Keywords[bs]=zvono,zvučni,zvuk,glasnoća,igralište,trajanje,visina tona,trajanje,PC zvučnici,unutarnji zvučnik,zvučnik,sustav zvona,sustav zvučnika,unutarnji PC zvučnik +X-KDE-Keywords[ca]=Campana,Àudio,So,Volum,To,Durada,Altaveu del PC,Altaveu intern,Altaveu,Campana del sistema,Altaveu del sistema,Altaveu intern del PC +X-KDE-Keywords[ca@valencia]=Campana,Àudio,So,Volum,To,Durada,Altaveu del PC,Altaveu intern,Altaveu,Campana del sistema,Altaveu del sistema,Altaveu intern del PC +X-KDE-Keywords[da]=Klokke,lyd,lydstyrke,volume,tone,varighed,pc-højtaler,intern højtaler,højtaler,systemklokke,systemhøjtaler,intern pc-højtaler +X-KDE-Keywords[de]=Signalton,Systemton,Klänge,Audio,Sound,Dauer,Lautstärke,Höhen,PC-Lautsprecher,Interner Lautsprecher,Lautsprecher,Systemsignalton,System-Lautsprecher,Interner PC-Lautsprecher +X-KDE-Keywords[el]=μεγαφωνάκι,ήχος,ήχος,ένταση,τόνος,διάρκεια,ηχείο PC,εσωτερικό ηχείο,ηχείο,κουδούνι συστήματος,ηχείο συστήματος,εσωτερικό ηχείο PC +X-KDE-Keywords[es]=Campana,Audio,Sonido,Volumen,Pitch,Duración,Altavoz del PC,Altavoz interno,Altavoz,Campana del sistema,Altavoz del sistema,Altavoz interno del PC +X-KDE-Keywords[et]=Kell,audio,heli,helitugevus,toon,kestus,arvutikõlar,PC kõlar,kõlar,sisemine kõlar,süsteemne piiks,süsteemi piiks,süsteemi kõlar,PC sisemine kõlar +X-KDE-Keywords[eu]=kanpai,audio,soinu,bolumen,tonu,iraupen,PC bozgorailu,barneko bozgorailu,bozgorailu,sistemaren soinu,sistemaren bozgorailu, PC barneko bozgorailu +X-KDE-Keywords[fi]=varoitus,äänimerkki,ääni,äänenvoimakkuus,äänenkorkeus,kesto,PC-kaiutin,sisäinen kaiutin,kaiutin,järjestelmän äänimerkki,järjestelmäkaiutin,sisäinen PC-kaiutin +X-KDE-Keywords[fr]=Cloche, Audio, Son, Volume, Pas, Durée, Haut-parleur du PC, Haut-parleur interne, Haut parleur, Cloche du système, Haut-parleur du système, Haut-parleur interne du PC +X-KDE-Keywords[gl]=Badalada, campá, son, volume, altofalante, badalada do sistema +X-KDE-Keywords[he]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,ספיקר, שמע, משך, פעמון, גובה +X-KDE-Keywords[hu]=Csengő,Audio,Hang,Hangerő,Hangmagasság,Időtartam,PC hangszóró,Belső hangszóró,Hangszóró,Rendszercsengő,Rendszer hangszóró,Belső PC hangszóró +X-KDE-Keywords[ia]=Campana,Audio,Sono,Volumine,Accordatura,Duration,altoparlator de PC,altoparlator interne, Altoparlator,Campana de systema,altoparlator de systema,Altoparlator de PC interne +X-KDE-Keywords[it]=Campanella,Audio,Suono,Volume,Altezza,Durata,Altoparlanti PC,Altoparlanti interni,Altoparlante,Campanella di sistema,Altoparlanti di sistema,Altoparlanti interni pc +X-KDE-Keywords[kk]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker +X-KDE-Keywords[km]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker +X-KDE-Keywords[ko]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,오디오,사운드,음량,시간,스피커 +X-KDE-Keywords[mr]=घंटी, श्राव्य, ध्वनी, आवाज, आवाजाचा स्तर, अवधी, पी.सी.स्पीकर , इंटर्नल स्पीकर, स्पीकर प्रणाली घंटी, प्रणाली स्पीकर, अंतर्गत पी.सी. स्पीकर +X-KDE-Keywords[nb]=Bjelle, Lyd,Lydstyrke,Tone,Varighet,PC-høyttaler,Intern høyttaler,Høyttaler,Systembjelle,Systemhøyttaler, Intern PC-høyttaler +X-KDE-Keywords[nds]=Pingel,Kläng,Klang,Luutstärk,Toonhööchd,Duer,PC-Luutspreker,intern Luutspreker,Luutspreker,Systempingel,System-Luutspreker,intern PC-Luutspreker +X-KDE-Keywords[nl]=Bel,audio,geluid,volume,toonhoogte,duur,PC-speaker,interne speaker,speaker,systeembel,systeemspeaker,interne PC-speaker +X-KDE-Keywords[pl]=Dzwonek,Audio,Dźwięk,Głośność,Ton,Czas trwania +X-KDE-Keywords[pt]=Campainha,Áudio,Som,Volume,Frequência,Duração,Altifalante do PC,Altifalante Interno,Altifalante,Campainha do Sistema,Altifalante do Sistema,Altifalante Interno do PC +X-KDE-Keywords[pt_BR]=Campainha,Áudio,Som,Volume,Frequência,Duração,Alto-falante do PC,Alto-falante interno,Alto-falante,Campainha do sistema,Alto-falante do sistema,Alto-falante interno do PC +X-KDE-Keywords[ru]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,сигнал,аудио,звук,громкость,высота тона,длительность,колонки,динамики,встроенный динамик,сигнал системы,акустическая система,встроенная акустическая система +X-KDE-Keywords[sk]=Zvonček,zvuk,audio,hlasitosť,výška tónu,trvanie,PC speaker,vnútorný reproduktor,speaker,systémový zvonček,systémový reproduktor,vnútorný PC speaker +X-KDE-Keywords[sl]=zvonec,audio,avdio,zvok,glasnost,ton,višina tona,trajanje,zvočnik,notranji zvočnik,sistemski zvonec,sistemski zvočnik,piskanje,notranji PC zvočnik +X-KDE-Keywords[sr]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,звоно,аудио,звук,јачина,висина,трајање,системско звоно,системски звучник,унутрашњи звучник +X-KDE-Keywords[sr@ijekavian]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,звоно,аудио,звук,јачина,висина,трајање,системско звоно,системски звучник,унутрашњи звучник +X-KDE-Keywords[sr@ijekavianlatin]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,zvono,audio,zvuk,jačina,visina,trajanje,sistemsko zvono,sistemski zvučnik,unutrašnji zvučnik +X-KDE-Keywords[sr@latin]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,zvono,audio,zvuk,jačina,visina,trajanje,sistemsko zvono,sistemski zvučnik,unutrašnji zvučnik +X-KDE-Keywords[sv]=Summer,Ljud,Volym,Tonhöjd,Längd,PC-högtalare,Intern högtalare,Högtalare,Systemsummer,Systemhögtalare,Intern PC-högtalare +X-KDE-Keywords[tr]=Zil,Ses,Ses Düzeyi,Akort,Süre,PC Hoparlörü,İç Hoparlör,Hoparlör,Sistem Zili,Sistem Hoparlörü,Dahili PC Hoparlörü +X-KDE-Keywords[uk]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,дзвінок,гудок,звук,гучність,тон,тривалість,гучномовець,колонки,вбудовані колонки,системний дзвінок,вбудований гучномовець +X-KDE-Keywords[vi]=Chuông,âm thanh,âm lượng,thời lượng,loa PC,loa trong,loa,chuông hệ thống,loa hệ thống, loa PC trong +X-KDE-Keywords[x-test]=xxBell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speakerxx +X-KDE-Keywords[zh_CN]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker,铃声,声音,音量,音调,持续时间,PC 扬声器,内部扬声器,扬声器,PC 喇叭,内部喇叭,喇叭,系统铃声,系统扬声器,系统喇叭,内部 PC 扬声器,内部 PC 喇叭 +X-KDE-Keywords[zh_TW]=Bell,Audio,Sound,Volume,Pitch,Duration,PC Speaker,Internal Speaker,Speaker,System Bell,System Speaker,Internal PC Speaker + diff --git a/kcms/bell/bell.h b/kcms/bell/bell.h new file mode 100644 index 0000000000..fda09b5556 --- /dev/null +++ b/kcms/bell/bell.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) + 1998 Bernd Wuebben + 2000 Matthias Elter + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 __bell_h__ +#define __bell_h__ + +#include "kcmodule.h" + +class QCheckBox; +class KIntNumInput; +class QPushButton; + +class KBellConfig : public KCModule +{ + Q_OBJECT + + public: + KBellConfig(QWidget *parent, const QVariantList &args); + + void load(); + void save(); + void defaults(); + + protected Q_SLOTS: + void ringBell(); + void useBell( bool ); + + private: + QPushButton *m_testButton; + KIntNumInput *m_volume; + KIntNumInput *m_pitch; + KIntNumInput *m_duration; + QCheckBox *m_useBell; +}; + +#endif diff --git a/kcms/colors/CMakeLists.txt b/kcms/colors/CMakeLists.txt new file mode 100644 index 0000000000..ff0b537cfc --- /dev/null +++ b/kcms/colors/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(kcm_colors_SRCS ../krdb/krdb.cpp colorscm.cpp previewwidget.cpp setpreviewwidget.cpp) + +set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) +qt5_add_dbus_interface(kcm_colors_SRCS ${klauncher_xml} klauncher_iface) + +kde4_add_ui_files(kcm_colors_SRCS colorsettings.ui preview.ui setpreview.ui) + +add_library(kcm_colors MODULE ${kcm_colors_SRCS}) +target_link_libraries(kcm_colors + KF5::KCMUtils + KF5::GuiAddons + KF5::I18n + Qt5::DBus + KF5::NewStuff + KF5::KDE4Support + ${X11_LIBRARIES}) + +if(X11_FOUND) + set_target_properties(kcm_colors PROPERTIES COMPILE_FLAGS -DHAVE_X11=1) + target_link_libraries(kcm_colors Qt5::X11Extras) +endif() + +install(TARGETS kcm_colors DESTINATION ${PLUGIN_INSTALL_DIR}) +install( FILES colors.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES colorschemes.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) + +# built-in color schemes +file(GLOB schemefiles schemes/*.colors) +install( FILES ${schemefiles} DESTINATION ${DATA_INSTALL_DIR}/color-schemes ) diff --git a/kcms/colors/Messages.sh b/kcms/colors/Messages.sh new file mode 100644 index 0000000000..71fb50becd --- /dev/null +++ b/kcms/colors/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC *.ui >> rc.cpp +$XGETTEXT *.cpp -o $podir/kcmcolors.pot +rm -f rc.cpp diff --git a/kcms/colors/README.i18n b/kcms/colors/README.i18n new file mode 100644 index 0000000000..1033fcb9b4 --- /dev/null +++ b/kcms/colors/README.i18n @@ -0,0 +1,54 @@ +There are two sets of preview strings in the color kcm, with special translation needs. In general, length of the translations, and "gist"-level clarity is more important than precise translation. It should be easy to identify what color role a string represents, but there are size considerations that should be taken into account. The tooltips should be translated normally. + + + +When translating the color kcm, it is helpful to understand the intended meaning of the various color roles in order to chose the best possible translation if more than one would be possible. Hopefully the sets (view, window, button, selection, tooltip) are obvious, as well as normal background/foreground. The others are as follows: + +Alternate [Background]: used in lists when every other row uses a different color; "different". +Inactive: comments, something which is old, unimportant/uninteresting/secondary text +Active: e.g. something new, something active (currently engaged in activity), something requesting attention, a hovered hyperlink +Link: hyperlink, somewhere the user can go, new history +Visited: visited hyperlinks, somewhere the user has been, old history +Negative: "bad", untrusted, unreliable, a mistake, an error the user made, an error that occurred +Neutral: warning, encrypted, anything "between" negative and positive +Positive: success, completion messages, trusted content + +For Link, although other uses are possible, translate as referring to hyperlinks to minimize user confusion. + + + +The "generic" preview uses these strings (all with disambiguation "color-kcm-preview"): +- Window Text +- Push Button +- Normal Text +- Selected Text +- link +- visited +- a +- i +- ! +- = +- + + +The two-word strings may be translated normally, though it is suggested to omit the translation of "Text" if the strings would be excessively (around 20+ characters) long and doing so does not cause confusion (i.e. substantially change the conveyed meaning). The "link" and "visited" strings should be translated according to the notes above, ideally keeping the length to four to eight characters; abbreviation (to not less than four characters if possible) is acceptable as the tooltips will provide more complete descriptions. + +The remaining one-character strings represent (respectively) the text roles active (a), inactive (i), negative (!), neutral (=) and positive (+). These should be translated as one- or two-character strings which uniquely correspond to the aforementioned text roles, ideally taking the first letter of the corresponding translation, or maintaining the symbols (!, =, +) as-is if culturally appropriate. + +Ideographic languages (e.g. Japanese, Mandarin, etc.) where the single-character strings can be replaced with one or two characters representing the full word should do so. These should also, if needed, consider a phonetic representation or relevant phrase for the longer elements, to keep the translations close to the same number of characters as the English. + + + +The "set" preview uses these strings (all with disambiguation "color-kcm-set-preview"): +- normal +- link +- visited +- active +- inactive +- alternate +- negative +- neutral +- positive +- hover +- focus + +These live in a preview widget that is two rows tall by nine items wide, and is often the determining factor in the minimum width of the dialog. For this reason, it is important to keep the strings SHORT. To ensure each text block is of sufficient size to provide an adequate preview, each should be at least a few characters long, but please try to limit them to no more than eight or ten characters on average. Abbreviation is fine and encouraged if necessary to achieve this average. In particular, PLEASE avoid adding the translated equivalent of " text" to these strings if at all possible; the tooltips will disambiguate if required. If these objectives cannot be achieved via direct translation, semantic translation (e.g. "negative" -> i18n("oops!"), "neutral" -> i18n("meh")) would be better. (Ideographic languages, which may need to ADD text to achieve a minimum length, should ignore the previous two sentences.) Note also that "hover" and "focus" are actually "decoration" roles, so e.g. "hover text" is incorrect (should be "hover decoration"). diff --git a/kcms/colors/TODO b/kcms/colors/TODO new file mode 100644 index 0000000000..a0695b9ffd --- /dev/null +++ b/kcms/colors/TODO @@ -0,0 +1,3 @@ +query kwin for what WM colors should be shown for configuring(?) +options (i.e. "things on the first tab") not saved in schemes (in kdeglobals only) +sort schemes list, 'current' at 0, 'default' at 1, everything else sorted (possibly kde3-style, user schemes on top?) diff --git a/kcms/colors/colors.desktop b/kcms/colors/colors.desktop new file mode 100644 index 0000000000..adc2d4e61d --- /dev/null +++ b/kcms/colors/colors.desktop @@ -0,0 +1,194 @@ +[Desktop Entry] +Exec=kcmshell5 colors +Icon=preferences-desktop-color +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/colors/index.html + +X-KDE-Library=kcm_colors +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=application-appearance +X-KDE-Weight=60 + +Name=Colors +Name[af]=Kleure +Name[ar]=الألوان +Name[ast]=Colores +Name[be]=Колеры +Name[be@latin]=Kolery +Name[bg]=Цветове +Name[bn]=রং +Name[bn_IN]=রং +Name[br]=Livioù +Name[bs]=Boje +Name[ca]=Colors +Name[ca@valencia]=Colors +Name[cs]=Barvy +Name[csb]=Farwë +Name[cy]=Lliwiau +Name[da]=Farver +Name[de]=Farben +Name[el]=Χρώματα +Name[en_GB]=Colours +Name[eo]=Koloroj +Name[es]=Colores +Name[et]=Värvid +Name[eu]=Koloreak +Name[fa]=رنگها +Name[fi]=Värit +Name[fr]=Couleurs +Name[fy]=Kleuren +Name[ga]=Dathanna +Name[gl]=Cores +Name[gu]=રંગો +Name[he]=צבעים +Name[hi]=रंग +Name[hne]=रंग +Name[hr]=Boje +Name[hsb]=Barby +Name[hu]=Színek +Name[ia]=Colores +Name[id]=Warna +Name[is]=Litir +Name[it]=Colori +Name[ja]=色 +Name[ka]=ცვეტები +Name[kk]=Түстер +Name[km]=ពណ៌ +Name[kn]=ಬಣ್ಣಗಳು +Name[ko]=색 +Name[ku]=Reng +Name[lt]=Spalvos +Name[lv]=Krāsas +Name[mai]=रँग +Name[mk]=Бои +Name[ml]=നിറങ്ങള്‍ +Name[mr]=रंग +Name[ms]=Warna +Name[nb]=Farger +Name[nds]=Klören +Name[ne]=रङ +Name[nl]=Kleuren +Name[nn]=Fargar +Name[oc]=Colors +Name[or]=ରଙ୍ଗ +Name[pa]=ਰੰਗ +Name[pl]=Kolory +Name[pt]=Cores +Name[pt_BR]=Cores +Name[ro]=Culori +Name[ru]=Цвета +Name[se]=Ivnnit +Name[si]=වර්‍ණ +Name[sk]=Farby +Name[sl]=Barve +Name[sr]=Боје +Name[sr@ijekavian]=Боје +Name[sr@ijekavianlatin]=Boje +Name[sr@latin]=Boje +Name[sv]=Färger +Name[ta]=வண்ணங்கள் +Name[te]=రంగులు +Name[tg]=Рангҳо +Name[th]=สี +Name[tr]=Renkler +Name[ug]=رەڭلەر +Name[uk]=Кольори +Name[uz]=Ranglar +Name[uz@cyrillic]=Ранглар +Name[vi]=Màu sắc +Name[wa]=Coleurs +Name[xh]=Imibala +Name[x-test]=xxColorsxx +Name[zh_CN]=颜色 +Name[zh_TW]=顏色 + +Comment=Change the colors used in applications +Comment[bs]=Promjeni boje koristene u aplikaciji +Comment[ca]=Canvia els colors utilitzats en les aplicacions +Comment[ca@valencia]=Canvia els colors utilitzats en les aplicacions +Comment[cs]=Změňte barvy použité v aplikacích +Comment[da]=Ændr de farver der bruges i programmer +Comment[de]=Änderung der von Programmen verwendeten Farben +Comment[el]=Αλλαγή των χρωμάτων που χρησιμοποιούνται στις εφαρμογές +Comment[es]=Cambiar los colores que usan las aplicaciones +Comment[et]=Rakendustes kasutatavate värvide muutmine +Comment[eu]=Aldatu aplikazioetan erabiltzen diren koloreak +Comment[fi]=Sovellusten värien asetukset +Comment[fr]=Modifier les couleurs utilisées dans les applications +Comment[gl]=Cambia as cores usadas nos programas +Comment[he]=שנה את הצבעים בשימוש ביישומים +Comment[hu]=Az alkalmazásokban használt színek megváltoztatása +Comment[ia]=Modifica le colores usate in applicationes +Comment[it]=Cambia il colore usato nelle applicazioni +Comment[kk]=Қолданбада пайдаланатын түстерін өзгерту +Comment[km]=ផ្លាស់ប្ដូរ​ពណ៌​ដែល​បាន​ប្រើ​ក្នុង​កម្មវិធី +Comment[ko]=프로그램에 사용되는 색을 변경합니다 +Comment[lt]=Keisti spalvas naudojamas programose +Comment[mr]=अनुप्रयोगांत वापरण्यात आलेले रंग बदला +Comment[nb]=Endre fargene som brukes i programmer +Comment[nds]=De Programmklören ännern +Comment[nl]=De in toepassingen gebruikte kleuren wijzigen +Comment[pa]=ਐਪਲੀਕੇਸ਼ਨ ਵਿੱਚ ਵਰਤੇ ਜਾਂਦੇ ਰੰਗ ਬਦਲੋ +Comment[pl]=Zmiana kolorów używanych w programach +Comment[pt]=Mudar as cores usadas nas aplicações +Comment[pt_BR]=Alterar as cores usadas nos aplicativos +Comment[ro]=Schimbă culorile folosite în aplicații +Comment[ru]=Изменение цветов, используемых в приложениях +Comment[sk]=Zmeniť farby použité v aplikáciách +Comment[sl]=Spremenite barve, ki se uporabljajo v programih +Comment[sr]=Промените боје коришћене у програмима +Comment[sr@ijekavian]=Промените боје коришћене у програмима +Comment[sr@ijekavianlatin]=Promenite boje korišćene u programima +Comment[sr@latin]=Promenite boje korišćene u programima +Comment[sv]=Ändra färgerna som används av program +Comment[tr]=Uygulamalarda kullanılacak renkleri yapılandır +Comment[uk]=Зміна кольорів, що використовуються у інтерфейсах програм +Comment[vi]=Thay đổi màu sắc được sử dụng trong các ứng dụng +Comment[x-test]=xxChange the colors used in applicationsxx +Comment[zh_CN]=更改应用程序所使用的颜色 +Comment[zh_TW]=變更用於應用程式的顏色 + +X-KDE-Keywords=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme +X-KDE-Keywords[bs]=boje,boje,tema,kontrast,dodatak bojama,tema u boji,stil boja,tema boja +X-KDE-Keywords[ca]=colors,esquema,contrast,colors d'estris,Esquema de color,estil de color, tema de color +X-KDE-Keywords[ca@valencia]=colors,esquema,contrast,colors d'estris,Esquema de color,estil de color, tema de color +X-KDE-Keywords[da]=farver,tema,kontrast,widget-farver,farvetema,farvestil,farveskema +X-KDE-Keywords[de]=Farben,Schema,Kontrast,Farbschema,Elemente +X-KDE-Keywords[el]=χρώματα,χρώματα,σχήμα,αντίθεση,χρώματα γραφικών συστατικών,χρωματικό σχήμα,χρωματικό στιλ,θέμα χρώματος +X-KDE-Keywords[es]=colores,esquema,contraste,colores de elementos gráficos,Esquema de color,estilo de color,tema de color +X-KDE-Keywords[et]=värv,värvid,skeem,kontrast,vidina värvid,värviskeem,värvistiil,värviteema +X-KDE-Keywords[eu]=kolore,koloreak,eskema,kontraste,trepetaren koloreak,kolore-eskema,kolore-estilo, kolorearen gai +X-KDE-Keywords[fi]=värit,teema,kontrasti,käyttöliittymäelementtien värit,elementtien värit,väriteema,värityyli +X-KDE-Keywords[fr]=couleurs, couleurs, schéma, contraste, couleur des composants graphiques, schéma de couleur, style de couleur, thème de couleur +X-KDE-Keywords[ga]=dathanna,scéim,codarsnacht,dathanna Giuirléidí,Scéim Datha,téama datha +X-KDE-Keywords[gl]=cores,esquema,contraste,cores do widget,esquema de cores, tema de cores +X-KDE-Keywords[hu]=színek,színek,séma,kontraszt,Grafikai elemek színei,Színséma,színstílus,színtéma +X-KDE-Keywords[ia]=colores,colores,schema,contrasto,colores de Widget,Schema de Color,stilo de color, thema de color +X-KDE-Keywords[it]=colori,schema,contrasto,colore degli oggetti,schema di colore,stile colore,tema colore +X-KDE-Keywords[kk]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme +X-KDE-Keywords[km]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme +X-KDE-Keywords[ko]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,색,색 배열,고대비 +X-KDE-Keywords[mr]=रंग, रंग, योजना, कॉन्ट्रास्ट, विजेट रंग, रंगयोजना, रंगप्रकार, रंगशैली +X-KDE-Keywords[nb]=farger,oppsett,kontrast,elementfarger,fargeoppsett,fargestil,fargetema +X-KDE-Keywords[nds]=Klöör,Klören,Schema,Kontrast,Lüttprogramm-Klören,Klöörschema,Klöörstil,Klöörmuster +X-KDE-Keywords[nl]=colors,colours, kleuren,scheme,schema,contrast,Widget colors,Widgetkleuren,Color Scheme,kleurschema,kleurstijl,kleurthema +X-KDE-Keywords[pl]=kolory,schemat,kontrast,kolory elementów interfejsu,zestaw kolorów,styl kolorów,motyw kolorów +X-KDE-Keywords[pt]=cores,esquema,contraste,cores dos elementos,esquema de cores,estilo de cores,tema de cores +X-KDE-Keywords[pt_BR]=cor,cores,esquema,contraste,Cores do widget,Esquema de cores,estilo de cores,tema de cores +X-KDE-Keywords[ru]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,цвет,цвета,схема,контраст,цвета виджета,цветовая схема,цветовой стиль,цветовая тема +X-KDE-Keywords[sk]=farba,farby,schéma,kontrast,farby widgetov,Farebná schéma,štýl farieb,téma farieb +X-KDE-Keywords[sl]=barve,shema,tema,kontrast,barve gradnikov,barvna shema,barvna tema,barvni slog +X-KDE-Keywords[sr]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,боје,шема,контраст,боје виџета,шема боја,стил боја,тема боја +X-KDE-Keywords[sr@ijekavian]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,боје,шема,контраст,боје виџета,шема боја,стил боја,тема боја +X-KDE-Keywords[sr@ijekavianlatin]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,boje,šema,kontrast,boje vidžeta,šema boja,stil boja,tema boja +X-KDE-Keywords[sr@latin]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,boje,šema,kontrast,boje vidžeta,šema boja,stil boja,tema boja +X-KDE-Keywords[sv]=färger,schema,kontrast,Komponentfärger,Färgschema,färgstil,färgtema +X-KDE-Keywords[tr]=renkler,renk,şema,karşıtlık,kontrast,Parçacık renkleri,RenkŞeması,renk biçimi,renk teması +X-KDE-Keywords[uk]=кольори,кольори,схема,контраст,кольори віджетів,схема кольорів,стиль кольорів,тема кольорів,colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme +X-KDE-Keywords[x-test]=xxcolors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color themexx +X-KDE-Keywords[zh_CN]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme,颜色,配色方案,对比度,部件颜色,颜色方案,颜色风格,颜色主题 +X-KDE-Keywords[zh_TW]=colors,colours,scheme,contrast,Widget colors,Color Scheme,color style,color theme + +Categories=Qt;KDE;X-KDE-settings-looknfeel; diff --git a/kcms/colors/colorschemes.knsrc b/kcms/colors/colorschemes.knsrc new file mode 100644 index 0000000000..cc4852d641 --- /dev/null +++ b/kcms/colors/colorschemes.knsrc @@ -0,0 +1,6 @@ +[KNewStuff3] +ProvidersUrl=http://download.kde.org/ocs/providers.xml +TargetDir=color-schemes +Uncompress=archive +Categories=KDE Color Scheme KDE4 +UploadCategories=KDE Color Scheme KDE4 diff --git a/kcms/colors/colorscm.cpp b/kcms/colors/colorscm.cpp new file mode 100644 index 0000000000..c38811bc78 --- /dev/null +++ b/kcms/colors/colorscm.cpp @@ -0,0 +1,1470 @@ +/* KDE Display color scheme setup module + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 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. + * + * 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 "colorscm.h" + +#include "../krdb/krdb.h" + +#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( KolorFactory, registerPlugin(); ) +K_EXPORT_PLUGIN( KolorFactory("kcmcolors") ) + +//BEGIN WindecoColors +KColorCm::WindecoColors::WindecoColors(const KSharedConfigPtr &config) +{ + load(config); +} + +void KColorCm::WindecoColors::load(const KSharedConfigPtr &config) +{ + // NOTE: keep this in sync with kdelibs/kdeui/kernel/kglobalsettings.cpp + KConfigGroup group(config, "WM"); + m_colors[ActiveBackground] = group.readEntry("activeBackground", QColor(48, 174, 232)); + m_colors[ActiveForeground] = group.readEntry("activeForeground", QColor(255, 255, 255)); + m_colors[InactiveBackground] = group.readEntry("inactiveBackground", QColor(224, 223, 222)); + m_colors[InactiveForeground] = group.readEntry("inactiveForeground", QColor(75, 71, 67)); + m_colors[ActiveBlend] = group.readEntry("activeBlend", m_colors[ActiveForeground]); + m_colors[InactiveBlend] = group.readEntry("inactiveBlend", m_colors[InactiveForeground]); +} + +QColor KColorCm::WindecoColors::color(WindecoColors::Role role) const +{ + return m_colors[role]; +} +//END WindecoColors + +KColorCm::KColorCm(QWidget *parent, const QVariantList &) + : KCModule( parent ), m_disableUpdates(false), + m_loadedSchemeHasUnsavedChanges(false), m_dontLoadSelectedScheme(false), + m_previousSchemeItem(0) +{ + KAboutData* about = new KAboutData( + QStringLiteral("kcmcolors"), QString(), i18n("Colors"), QString(), QString(), + KAboutData::License_GPL, + i18n("(c) 2007 Matthew Woehlke") + ); + about->addAuthor( i18n("Matthew Woehlke"), QString(), + QStringLiteral("mw_triad@users.sourceforge.net") ); + about->addAuthor( i18n("Jeremy Whiting"), QString(), QStringLiteral("jpwhiting@kde.org")); + setAboutData( about ); + + m_config = KSharedConfig::openConfig("kdeglobals"); + + setupUi(this); + schemeKnsButton->setIcon( QIcon::fromTheme("get-hot-new-stuff") ); + schemeKnsUploadButton->setIcon( QIcon::fromTheme("get-hot-new-stuff") ); + connect(colorSet, SIGNAL(currentIndexChanged(int)), this, SLOT(updateColorTable())); + connect(schemeList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), + this, SLOT(loadScheme(QListWidgetItem*,QListWidgetItem*))); + connect(applyToAlien, SIGNAL(toggled(bool)), this, SLOT(emitChanged())); + + // only needs to be called once + setupColorTable(); +} + +KColorCm::~KColorCm() +{ + m_config->markAsClean(); +} + +void KColorCm::populateSchemeList() +{ + // clear the list in case this is being called from reset button click + schemeList->clear(); + + // add entries + QIcon icon; + const QStringList schemeFiles = KGlobal::dirs()->findAllResources("data", "color-schemes/*.colors", KStandardDirs::NoDuplicates); + for (int i = 0; i < schemeFiles.size(); ++i) + { + // get the file name + const QString filename = schemeFiles.at(i); + const QFileInfo info(filename); + + // add the entry + KSharedConfigPtr config = KSharedConfig::openConfig(filename); + icon = createSchemePreviewIcon(config); + KConfigGroup group(config, "General"); + const QString name = group.readEntry("Name", info.baseName()); + QListWidgetItem * newItem = new QListWidgetItem(icon, name); + // stash the file basename for use later + newItem->setData(Qt::UserRole, info.baseName()); + schemeList->addItem(newItem); + } + schemeList->sortItems(); + + // add default entry (do this here so that the current and default entry appear at the top) + m_config->setReadDefaults(true); + icon = createSchemePreviewIcon(m_config); + schemeList->insertItem(0, new QListWidgetItem(icon, i18nc("Default color scheme", "Default"))); + m_config->setReadDefaults(false); + + // add current scheme entry + icon = createSchemePreviewIcon(m_config); + QListWidgetItem *currentitem = new QListWidgetItem(icon, i18nc("Current color scheme", "Current")); + schemeList->insertItem(0, currentitem); + schemeList->blockSignals(true); // don't emit changed signals + schemeList->setCurrentItem(currentitem); + schemeList->blockSignals(false); +} + +void KColorCm::updatePreviews() +{ + schemePreview->setPalette(m_config); + colorPreview->setPalette(m_config); + setPreview->setPalette(m_config, (KColorScheme::ColorSet)(colorSet->currentIndex() - 1)); + inactivePreview->setPalette(m_config, QPalette::Inactive); + disabledPreview->setPalette(m_config, QPalette::Disabled); +} + +void KColorCm::updateEffectsPage() +{ + m_disableUpdates = true; + + // NOTE: keep this in sync with kdelibs/kdeui/colors/kcolorscheme.cpp + KConfigGroup groupI(m_config, "ColorEffects:Inactive"); + inactiveIntensityBox->setCurrentIndex(abs(groupI.readEntry("IntensityEffect", 0))); + inactiveIntensitySlider->setValue(int(groupI.readEntry("IntensityAmount", 0.0) * 20.0) + 20); + inactiveColorBox->setCurrentIndex(abs(groupI.readEntry("ColorEffect", 2))); + if (inactiveColorBox->currentIndex() > 1) + { + inactiveColorSlider->setValue(int(groupI.readEntry("ColorAmount", 0.025) * 40.0)); + } + else + { + inactiveColorSlider->setValue(int(groupI.readEntry("ColorAmount", 0.05) * 20.0) + 20); + } + inactiveColorButton->setColor(groupI.readEntry("Color", QColor(112, 111, 110))); + inactiveContrastBox->setCurrentIndex(abs(groupI.readEntry("ContrastEffect", 2))); + inactiveContrastSlider->setValue(int(groupI.readEntry("ContrastAmount", 0.1) * 20.0)); + + // NOTE: keep this in sync with kdelibs/kdeui/colors/kcolorscheme.cpp + KConfigGroup groupD(m_config, "ColorEffects:Disabled"); + disabledIntensityBox->setCurrentIndex(groupD.readEntry("IntensityEffect", 2)); + disabledIntensitySlider->setValue(int(groupD.readEntry("IntensityAmount", 0.1) * 20.0) + 20); + disabledColorBox->setCurrentIndex(groupD.readEntry("ColorEffect", 0)); + if (disabledColorBox->currentIndex() > 1) + { + disabledColorSlider->setValue(int(groupD.readEntry("ColorAmount", 0.0) * 40.0)); + } + else + { + disabledColorSlider->setValue(int(groupD.readEntry("ColorAmount", 0.0) * 20.0) + 20); + } + disabledColorButton->setColor(groupD.readEntry("Color", QColor(56, 56, 56))); + disabledContrastBox->setCurrentIndex(groupD.readEntry("ContrastEffect", 1)); + disabledContrastSlider->setValue(int(groupD.readEntry("ContrastAmount", 0.65) * 20.0)); + + m_disableUpdates = false; + + // enable/disable controls + inactiveIntensitySlider->setDisabled(inactiveIntensityBox->currentIndex() == 0); + disabledIntensitySlider->setDisabled(disabledIntensityBox->currentIndex() == 0); + inactiveColorSlider->setDisabled(inactiveColorBox->currentIndex() == 0); + disabledColorSlider->setDisabled(disabledColorBox->currentIndex() == 0); + inactiveColorButton->setDisabled(inactiveColorBox->currentIndex() < 2); + disabledColorButton->setDisabled(disabledColorBox->currentIndex() < 2); + inactiveContrastSlider->setDisabled(inactiveContrastBox->currentIndex() == 0); + disabledContrastSlider->setDisabled(disabledContrastBox->currentIndex() == 0); +} + +void KColorCm::loadScheme(KSharedConfigPtr config) // const QString &path) +{ + KSharedConfigPtr temp = m_config; + m_config = config; + + updateColorSchemes(); + updateEffectsPage(); // intentionally before swapping back m_config + updatePreviews(); + + m_config = temp; + updateFromColorSchemes(); + updateFromEffectsPage(); + updateFromOptions(); + updateColorTable(); + + m_loadedSchemeHasUnsavedChanges = false; + //m_changed = false; +} + +void KColorCm::selectPreviousSchemeAgain() +{ + m_dontLoadSelectedScheme = true; + schemeList->setCurrentItem(m_previousSchemeItem); + m_dontLoadSelectedScheme = false; +} + +void KColorCm::loadScheme(QListWidgetItem *currentItem, QListWidgetItem *previousItem) +{ + m_previousSchemeItem = previousItem; + + if (m_dontLoadSelectedScheme) + { + return; + } + + if (currentItem != NULL) + { + if (m_loadedSchemeHasUnsavedChanges) // if changes made to loaded scheme + { + if (KMessageBox::Continue != KMessageBox::warningContinueCancel(this, + i18n("Selecting another scheme will discard any changes you have made"), + i18n("Are you sure?"), + KStandardGuiItem::cont(), + KStandardGuiItem::cancel(), + "noDiscardWarning")) // if the user decides to cancel + { + QTimer::singleShot(0, this, SLOT(selectPreviousSchemeAgain())); + return; + } + } + + // load it + + const QString name = currentItem->text(); + m_currentColorScheme = name; + const QString fileBaseName = currentItem->data(Qt::UserRole).toString(); + if (name == i18nc("Default color scheme", "Default")) + { + schemeRemoveButton->setEnabled(false); + schemeKnsUploadButton->setEnabled(false); + + KSharedConfigPtr config = m_config; + config->setReadDefaults(true); + loadScheme(config); + config->setReadDefaults(false); + // load the default scheme + emit changed(true); + } + else if (name == i18nc("Current color scheme", "Current")) + { + schemeRemoveButton->setEnabled(false); + schemeKnsUploadButton->setEnabled(false); + loadInternal(false); + } + else + { + const QString path = KGlobal::dirs()->findResource("data", + "color-schemes/" + fileBaseName + ".colors"); + + const int permissions = QFile(path).permissions(); + const bool canWrite = (permissions & QFile::WriteUser); + kDebug() << "checking permissions of " << path; + schemeRemoveButton->setEnabled(canWrite); + schemeKnsUploadButton->setEnabled(true); + + KSharedConfigPtr config = KSharedConfig::openConfig(path); + loadScheme(config); + + emit changed(true); + } + } +} + +void KColorCm::on_schemeRemoveButton_clicked() +{ + if (schemeList->currentItem() != NULL) + { + const QString path = KGlobal::dirs()->findResource("data", + "color-schemes/" + schemeList->currentItem()->data(Qt::UserRole).toString() + + ".colors"); + if (KIO::NetAccess::del(QUrl::fromLocalFile(path), this)) + { + delete schemeList->takeItem(schemeList->currentRow()); + } + else + { + // deletion failed, so show an error message + KMessageBox::error(this, i18n("You do not have permission to delete that scheme"), i18n("Error")); + } + } +} + +void KColorCm::on_schemeImportButton_clicked() +{ + // get the path to the scheme to import + QUrl url = QUrl::fromLocalFile(QFileDialog::getOpenFileName(this, i18n("Import Color Scheme"))); + + if(url.isValid()) + { + // TODO: possibly untar or uncompress it + // open it + + // load the scheme + KSharedConfigPtr config = KSharedConfig::openConfig(url.path()); + + if (config->groupList().contains("Color Scheme")) + { + if (KMessageBox::Continue != KMessageBox::warningContinueCancel(this, + i18n("The scheme you have selected appears to be a KDE3 scheme.\n\n" + "KDE will attempt to import this scheme, however many color roles have been added since KDE3. " + "Some manual work will likely be required.\n\n" + "This scheme will not be saved automatically."), + i18n("Notice"))) + { + return; + } + + // convert KDE3 scheme to KDE4 scheme + KConfigGroup g(config, "Color Scheme"); + + colorSet->setCurrentIndex(0); + contrastSlider->setValue(g.readEntry("contrast", KGlobalSettings::contrast())); + shadeSortedColumn->setChecked(g.readEntry("shadeSortColumn", KGlobalSettings::shadeSortColumn())); + + m_commonColorButtons[0]->setColor(g.readEntry("windowBackground", m_colorSchemes[KColorScheme::View].background().color())); + m_commonColorButtons[1]->setColor(g.readEntry("windowForeground", m_colorSchemes[KColorScheme::View].foreground().color())); + m_commonColorButtons[2]->setColor(g.readEntry("background", m_colorSchemes[KColorScheme::Window].background().color())); + m_commonColorButtons[3]->setColor(g.readEntry("foreground", m_colorSchemes[KColorScheme::Window].foreground().color())); + m_commonColorButtons[4]->setColor(g.readEntry("buttonBackground", m_colorSchemes[KColorScheme::Button].background().color())); + m_commonColorButtons[5]->setColor(g.readEntry("buttonForeground", m_colorSchemes[KColorScheme::Button].foreground().color())); + m_commonColorButtons[6]->setColor(g.readEntry("selectBackground", m_colorSchemes[KColorScheme::Selection].background().color())); + m_commonColorButtons[7]->setColor(g.readEntry("selectForeground", m_colorSchemes[KColorScheme::Selection].foreground().color())); + m_commonColorButtons[8]->setColor(KColorUtils::mix(m_colorSchemes[KColorScheme::Selection].foreground().color(), + m_colorSchemes[KColorScheme::Selection].background().color())); + m_commonColorButtons[9]->setColor(KColorUtils::mix(m_colorSchemes[KColorScheme::View].foreground().color(), + m_colorSchemes[KColorScheme::View].background().color())); + // doesn't exist in KDE3: 10 ActiveText + m_commonColorButtons[11]->setColor(g.readEntry("linkColor", m_colorSchemes[KColorScheme::View].foreground(KColorScheme::LinkText).color())); + m_commonColorButtons[12]->setColor(g.readEntry("visitedLinkColor", m_colorSchemes[KColorScheme::View].foreground(KColorScheme::VisitedText).color())); + // doesn't exist in KDE3: 13-15 PositiveText, NeutralText, NegativeText + m_commonColorButtons[16]->setColor(g.readEntry("windowForeground", m_colorSchemes[KColorScheme::View].decoration(KColorScheme::FocusColor).color())); + m_commonColorButtons[17]->setColor(g.readEntry("selectBackground", m_colorSchemes[KColorScheme::View].decoration(KColorScheme::HoverColor).color())); + m_commonColorButtons[18]->setColor(g.readEntry("windowBackground", m_colorSchemes[KColorScheme::Tooltip].background().color())); + m_commonColorButtons[19]->setColor(g.readEntry("windowForeground", m_colorSchemes[KColorScheme::Tooltip].foreground().color())); + m_commonColorButtons[20]->setColor(g.readEntry("activeBackground", m_wmColors.color(WindecoColors::ActiveBackground))); + m_commonColorButtons[21]->setColor(g.readEntry("activeForeground", m_wmColors.color(WindecoColors::ActiveForeground))); + m_commonColorButtons[22]->setColor(g.readEntry("activeBlend", m_wmColors.color(WindecoColors::ActiveBlend))); + m_commonColorButtons[23]->setColor(g.readEntry("inactiveBackground", m_wmColors.color(WindecoColors::InactiveBackground))); + m_commonColorButtons[24]->setColor(g.readEntry("inactiveForeground", m_wmColors.color(WindecoColors::InactiveForeground))); + m_commonColorButtons[25]->setColor(g.readEntry("inactiveBlend", m_wmColors.color(WindecoColors::InactiveBlend))); + + colorSet->setCurrentIndex(1); + m_backgroundButtons[KColorScheme::AlternateBackground]->setColor(g.readEntry("alternateBackground", + m_colorSchemes[KColorScheme::View].background(KColorScheme::AlternateBackground).color())); + colorSet->setCurrentIndex(0); + } + else + { + // load KDE4 scheme + loadScheme(config); + + // save it + saveScheme(url.fileName()); + } + } +} + +void KColorCm::on_schemeKnsButton_clicked() +{ + KNS3::DownloadDialog dialog("colorschemes.knsrc", this); + dialog.exec(); + if ( ! dialog.changedEntries().isEmpty() ) + { + populateSchemeList(); + } +} + +void KColorCm::on_schemeKnsUploadButton_clicked() +{ + if (schemeList->currentItem() != NULL) + { + // check if the currently loaded scheme has unsaved changes + if (m_loadedSchemeHasUnsavedChanges) + { + KMessageBox::sorry(this, i18n("Please save the color scheme before uploading it."), + i18n("Please save")); + return; + } + + // find path + const QString basename = schemeList->currentItem()->data(Qt::UserRole).toString(); + const QString path = KGlobal::dirs()->findResource("data", + "color-schemes/" + basename + ".colors"); + if (path.isEmpty() ) // if the color scheme file wasn't found + { + kDebug() << "path for color scheme " << basename << " couldn't be found"; + return; + } + + // upload + KNS3::UploadDialog dialog("colorschemes.knsrc", this); + dialog.setUploadFile(QUrl::fromLocalFile(path) ); + dialog.exec(); + } +} + +void KColorCm::on_schemeSaveButton_clicked() +{ + QString previousName; + if (schemeList->currentItem() != NULL && schemeList->currentRow() > 1) + { + previousName = schemeList->currentItem()->data(Qt::DisplayRole).toString(); + } + // prompt for the name to save as + bool ok; + QString name = KInputDialog::getText(i18n("Save Color Scheme"), + i18n("&Enter a name for the color scheme:"), previousName, &ok, this); + if (ok) + { + saveScheme(name); + } +} + +void KColorCm::saveScheme(const QString &name) +{ + QString filename = name; + filename.remove('\''); // So Foo's does not become FooS + QRegExp fixer("[\\W,.-]+(.?)"); + int offset; + while ((offset = fixer.indexIn(filename)) >= 0) + filename.replace(offset, fixer.matchedLength(), fixer.cap(1).toUpper()); + filename.replace(0, 1, filename.at(0).toUpper()); + + // check if that name is already in the list + const QString path = KGlobal::dirs()->saveLocation("data", "color-schemes/") + + filename + ".colors"; + + QFile file(path); + const int permissions = file.permissions(); + const bool canWrite = (permissions & QFile::WriteUser); + // or if we can overwrite it if it exists + if (path.isEmpty() || !file.exists() || canWrite) + { + if(canWrite){ + int ret = KMessageBox::questionYesNo(this, + i18n("A color scheme with that name already exists.\nDo you want to overwrite it?"), + i18n("Save Color Scheme"), + KStandardGuiItem::overwrite(), + KStandardGuiItem::cancel()); + //on don't overwrite, select the already existing name. + if(ret == KMessageBox::No){ + QList foundItems = schemeList->findItems(name, Qt::MatchExactly); + if (foundItems.size() == 1) + schemeList->setCurrentRow(schemeList->row(foundItems[0])); + return; + } + } + + // go ahead and save it + QString newpath = KGlobal::dirs()->saveLocation("data", "color-schemes/"); + newpath += filename + ".colors"; + KSharedConfigPtr temp = m_config; + m_config = KSharedConfig::openConfig(newpath); + // then copy current colors into new config + updateFromColorSchemes(); + updateFromEffectsPage(); + KConfigGroup group(m_config, "General"); + group.writeEntry("Name", name); + // sync it + m_config->sync(); + + m_loadedSchemeHasUnsavedChanges = false; + + QList foundItems = schemeList->findItems(name, Qt::MatchExactly); + QIcon icon = createSchemePreviewIcon(m_config); + if (foundItems.size() < 1) + { + // add it to the list since it's not in there already + populateSchemeList(); + + // then select the new item + schemeList->setCurrentItem(schemeList->findItems(name, Qt::MatchExactly).at(0)); + } + else + { + // update the icon of the one that's in the list + foundItems[0]->setIcon(icon); + schemeList->setCurrentRow(schemeList->row(foundItems[0])); + } + + // set m_config back to the system one + m_config = temp; + + // store colorscheme name in global settings + m_currentColorScheme = name; + group = KConfigGroup(m_config, "General"); + group.writeEntry("ColorScheme", m_currentColorScheme); + + emit changed(true); + } + else if (!canWrite && file.exists()) + { + // give error message if !canWrite && file.exists() + KMessageBox::error(this, i18n("You do not have permission to overwrite that scheme"), i18n("Error")); + } +} + +void KColorCm::createColorEntry(const QString &text, const QString &key, QList &list, int index) +{ + KColorButton *button = new KColorButton(this); + button->setObjectName(QString::number(index)); + connect(button, SIGNAL(changed(QColor)), this, SLOT(colorChanged(QColor))); + list.append(button); + + m_colorKeys.insert(index, key); + + QTableWidgetItem *label = new QTableWidgetItem(text); + colorTable->setItem(index, 0, label); + colorTable->setCellWidget(index, 1, button); + colorTable->setRowHeight(index, button->sizeHint().height()); +} + +void KColorCm::variesClicked() +{ + // find which button was changed + const int row = sender()->objectName().toInt(); + + QColor color; + if(KColorDialog::getColor(color, this ) != QDialog::Rejected ) + { + changeColor(row, color); + m_stackedWidgets[row - 9]->setCurrentIndex(0); + } +} + +QPixmap KColorCm::createSchemePreviewIcon(const KSharedConfigPtr &config) +{ + const WindecoColors wm(config); + const uchar bits1[] = { 0xff, 0xff, 0xff, 0x2c, 0x16, 0x0b }; + const uchar bits2[] = { 0x68, 0x34, 0x1a, 0xff, 0xff, 0xff }; + const QSize bitsSize(24,2); + const QBitmap b1 = QBitmap::fromData(bitsSize, bits1); + const QBitmap b2 = QBitmap::fromData(bitsSize, bits2); + + QPixmap pixmap(23, 16); + pixmap.fill(Qt::black); // ### use some color other than black for borders? + + QPainter p(&pixmap); + + KColorScheme windowScheme(QPalette::Active, KColorScheme::Window, config); + p.fillRect( 1, 1, 7, 7, windowScheme.background()); + p.fillRect( 2, 2, 5, 2, QBrush(windowScheme.foreground().color(), b1)); + + KColorScheme buttonScheme(QPalette::Active, KColorScheme::Button, config); + p.fillRect( 8, 1, 7, 7, buttonScheme.background()); + p.fillRect( 9, 2, 5, 2, QBrush(buttonScheme.foreground().color(), b1)); + + p.fillRect(15, 1, 7, 7, wm.color(WindecoColors::ActiveBackground)); + p.fillRect(16, 2, 5, 2, QBrush(wm.color(WindecoColors::ActiveForeground), b1)); + + KColorScheme viewScheme(QPalette::Active, KColorScheme::View, config); + p.fillRect( 1, 8, 7, 7, viewScheme.background()); + p.fillRect( 2, 12, 5, 2, QBrush(viewScheme.foreground().color(), b2)); + + KColorScheme selectionScheme(QPalette::Active, KColorScheme::Selection, config); + p.fillRect( 8, 8, 7, 7, selectionScheme.background()); + p.fillRect( 9, 12, 5, 2, QBrush(selectionScheme.foreground().color(), b2)); + + p.fillRect(15, 8, 7, 7, wm.color(WindecoColors::InactiveBackground)); + p.fillRect(16, 12, 5, 2, QBrush(wm.color(WindecoColors::InactiveForeground), b2)); + + p.end(); + + return pixmap; +} + +void KColorCm::updateColorSchemes() +{ + m_colorSchemes.clear(); + + m_colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::View, m_config)); + m_colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Window, m_config)); + m_colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Button, m_config)); + m_colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Selection, m_config)); + m_colorSchemes.append(KColorScheme(QPalette::Active, KColorScheme::Tooltip, m_config)); + + m_wmColors.load(m_config); +} + +void KColorCm::updateFromColorSchemes() +{ + // store colorscheme name in global settings + KConfigGroup group(m_config, "General"); + group.writeEntry("ColorScheme", m_currentColorScheme); + + for (int i = KColorScheme::View; i <= KColorScheme::Tooltip; ++i) + { + KConfigGroup group(m_config, colorSetGroupKey(i)); + group.writeEntry("BackgroundNormal", m_colorSchemes[i].background(KColorScheme::NormalBackground).color()); + group.writeEntry("BackgroundAlternate", m_colorSchemes[i].background(KColorScheme::AlternateBackground).color()); + group.writeEntry("ForegroundNormal", m_colorSchemes[i].foreground(KColorScheme::NormalText).color()); + group.writeEntry("ForegroundInactive", m_colorSchemes[i].foreground(KColorScheme::InactiveText).color()); + group.writeEntry("ForegroundActive", m_colorSchemes[i].foreground(KColorScheme::ActiveText).color()); + group.writeEntry("ForegroundLink", m_colorSchemes[i].foreground(KColorScheme::LinkText).color()); + group.writeEntry("ForegroundVisited", m_colorSchemes[i].foreground(KColorScheme::VisitedText).color()); + group.writeEntry("ForegroundNegative", m_colorSchemes[i].foreground(KColorScheme::NegativeText).color()); + group.writeEntry("ForegroundNeutral", m_colorSchemes[i].foreground(KColorScheme::NeutralText).color()); + group.writeEntry("ForegroundPositive", m_colorSchemes[i].foreground(KColorScheme::PositiveText).color()); + group.writeEntry("DecorationFocus", m_colorSchemes[i].decoration(KColorScheme::FocusColor).color()); + group.writeEntry("DecorationHover", m_colorSchemes[i].decoration(KColorScheme::HoverColor).color()); + } + + KConfigGroup WMGroup(m_config, "WM"); + WMGroup.writeEntry("activeBackground", m_wmColors.color(WindecoColors::ActiveBackground)); + WMGroup.writeEntry("activeForeground", m_wmColors.color(WindecoColors::ActiveForeground)); + WMGroup.writeEntry("inactiveBackground", m_wmColors.color(WindecoColors::InactiveBackground)); + WMGroup.writeEntry("inactiveForeground", m_wmColors.color(WindecoColors::InactiveForeground)); + WMGroup.writeEntry("activeBlend", m_wmColors.color(WindecoColors::ActiveBlend)); + WMGroup.writeEntry("inactiveBlend", m_wmColors.color(WindecoColors::InactiveBlend)); +} + +void KColorCm::updateFromOptions() +{ + KConfigGroup groupK(m_config, "KDE"); + groupK.writeEntry("contrast", contrastSlider->value()); + + KConfigGroup groupG(m_config, "General"); + groupG.writeEntry("shadeSortColumn", shadeSortedColumn->isChecked()); + + KConfigGroup groupI(m_config, "ColorEffects:Inactive"); + groupI.writeEntry("Enable", useInactiveEffects->isChecked()); + // only write this setting if it is not the default; this way we can change the default more easily in later KDE + // the setting will still written by explicitly checking/unchecking the box + if (inactiveSelectionEffect->isChecked()) + { + groupI.writeEntry("ChangeSelectionColor", true); + } + else + { + groupI.deleteEntry("ChangeSelectionColor"); + } +} + +void KColorCm::updateFromEffectsPage() +{ + if (m_disableUpdates) + { + // don't write the config as we are reading it! + return; + } + + KConfigGroup groupI(m_config, "ColorEffects:Inactive"); + KConfigGroup groupD(m_config, "ColorEffects:Disabled"); + + // intensity + groupI.writeEntry("IntensityEffect", inactiveIntensityBox->currentIndex()); + groupD.writeEntry("IntensityEffect", disabledIntensityBox->currentIndex()); + groupI.writeEntry("IntensityAmount", qreal(inactiveIntensitySlider->value() - 20) * 0.05); + groupD.writeEntry("IntensityAmount", qreal(disabledIntensitySlider->value() - 20) * 0.05); + + // color + groupI.writeEntry("ColorEffect", inactiveColorBox->currentIndex()); + groupD.writeEntry("ColorEffect", disabledColorBox->currentIndex()); + if (inactiveColorBox->currentIndex() > 1) + { + groupI.writeEntry("ColorAmount", qreal(inactiveColorSlider->value()) * 0.025); + } + else + { + groupI.writeEntry("ColorAmount", qreal(inactiveColorSlider->value() - 20) * 0.05); + } + if (disabledColorBox->currentIndex() > 1) + { + groupD.writeEntry("ColorAmount", qreal(disabledColorSlider->value()) * 0.025); + } + else + { + groupD.writeEntry("ColorAmount", qreal(disabledColorSlider->value() - 20) * 0.05); + } + groupI.writeEntry("Color", inactiveColorButton->color()); + groupD.writeEntry("Color", disabledColorButton->color()); + + // contrast + groupI.writeEntry("ContrastEffect", inactiveContrastBox->currentIndex()); + groupD.writeEntry("ContrastEffect", disabledContrastBox->currentIndex()); + groupI.writeEntry("ContrastAmount", qreal(inactiveContrastSlider->value()) * 0.05); + groupD.writeEntry("ContrastAmount", qreal(disabledContrastSlider->value()) * 0.05); + + // enable/disable controls + inactiveIntensitySlider->setDisabled(inactiveIntensityBox->currentIndex() == 0); + disabledIntensitySlider->setDisabled(disabledIntensityBox->currentIndex() == 0); + inactiveColorSlider->setDisabled(inactiveColorBox->currentIndex() == 0); + disabledColorSlider->setDisabled(disabledColorBox->currentIndex() == 0); + inactiveColorButton->setDisabled(inactiveColorBox->currentIndex() < 2); + disabledColorButton->setDisabled(disabledColorBox->currentIndex() < 2); + inactiveContrastSlider->setDisabled(inactiveContrastBox->currentIndex() == 0); + disabledContrastSlider->setDisabled(disabledContrastBox->currentIndex() == 0); +} + +void KColorCm::setupColorTable() +{ + // first setup the common colors table + commonColorTable->verticalHeader()->hide(); + commonColorTable->horizontalHeader()->hide(); + commonColorTable->setShowGrid(false); + commonColorTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + int minWidth = QPushButton(i18n("Varies")).minimumSizeHint().width(); + commonColorTable->horizontalHeader()->setMinimumSectionSize(minWidth); + commonColorTable->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents); + + for (int i = 0; i < 26; ++i) + { + KColorButton * button = new KColorButton(this); + commonColorTable->setRowHeight(i, button->sizeHint().height()); + button->setObjectName(QString::number(i)); + connect(button, SIGNAL(changed(QColor)), this, SLOT(colorChanged(QColor))); + m_commonColorButtons << button; + + if (i > 8 && i < 18) + { + // Inactive Text row through Positive Text role all need a varies button + KPushButton * variesButton = new KPushButton(NULL); + variesButton->setText(i18n("Varies")); + variesButton->setObjectName(QString::number(i)); + connect(variesButton, SIGNAL(clicked()), this, SLOT(variesClicked())); + + QStackedWidget * widget = new QStackedWidget(this); + widget->addWidget(button); + widget->addWidget(variesButton); + m_stackedWidgets.append(widget); + + commonColorTable->setCellWidget(i, 1, widget); + } + else + { + commonColorTable->setCellWidget(i, 1, button); + } + } + + // then the colorTable that the colorSets will use + colorTable->verticalHeader()->hide(); + colorTable->horizontalHeader()->hide(); + colorTable->setShowGrid(false); + colorTable->setRowCount(12); + colorTable->horizontalHeader()->setMinimumSectionSize(minWidth); + colorTable->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents); + + createColorEntry(i18n("Normal Background"), "BackgroundNormal", m_backgroundButtons, 0); + createColorEntry(i18n("Alternate Background"), "BackgroundAlternate", m_backgroundButtons, 1); + createColorEntry(i18n("Normal Text"), "ForegroundNormal", m_foregroundButtons, 2); + createColorEntry(i18n("Inactive Text"), "ForegroundInactive", m_foregroundButtons, 3); + createColorEntry(i18n("Active Text"), "ForegroundActive", m_foregroundButtons, 4); + createColorEntry(i18n("Link Text"), "ForegroundLink", m_foregroundButtons, 5); + createColorEntry(i18n("Visited Text"), "ForegroundVisited", m_foregroundButtons, 6); + createColorEntry(i18n("Negative Text"), "ForegroundNegative", m_foregroundButtons, 7); + createColorEntry(i18n("Neutral Text"), "ForegroundNeutral", m_foregroundButtons, 8); + createColorEntry(i18n("Positive Text"), "ForegroundPositive", m_foregroundButtons, 9); + createColorEntry(i18n("Focus Decoration"), "DecorationFocus", m_decorationButtons, 10); + createColorEntry(i18n("Hover Decoration"), "DecorationHover", m_decorationButtons, 11); + + colorTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + colorTable->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents); + + updateColorSchemes(); + updateColorTable(); +} + +void KColorCm::setCommonForeground(KColorScheme::ForegroundRole role, int stackIndex, + int buttonIndex) +{ + QColor color = m_colorSchemes[KColorScheme::View].foreground(role).color(); + for (int i = KColorScheme::Window; i < KColorScheme::Tooltip; ++i) + { + if (i == KColorScheme::Selection && role == KColorScheme::InactiveText) + break; + + if (m_colorSchemes[i].foreground(role).color() != color) + { + m_stackedWidgets[stackIndex]->setCurrentIndex(1); + return; + } + } + + m_stackedWidgets[stackIndex]->setCurrentIndex(0); + m_commonColorButtons[buttonIndex]->setColor(color); + m_loadedSchemeHasUnsavedChanges = true; +} + +void KColorCm::setCommonDecoration(KColorScheme::DecorationRole role, int stackIndex, + int buttonIndex) +{ + QColor color = m_colorSchemes[KColorScheme::View].decoration(role).color(); + for (int i = KColorScheme::Window; i < KColorScheme::Tooltip; ++i) + { + if (m_colorSchemes[i].decoration(role).color() != color) + { + m_stackedWidgets[stackIndex]->setCurrentIndex(1); + return; + } + } + + m_stackedWidgets[stackIndex]->setCurrentIndex(0); + m_commonColorButtons[buttonIndex]->setColor(color); + m_loadedSchemeHasUnsavedChanges = true; +} + +void KColorCm::updateColorTable() +{ + // subtract one here since the 0 item is "Common Colors" + const int currentSet = colorSet->currentIndex() - 1; + + if (currentSet == -1) + { + // common colors is selected + stackColors->setCurrentIndex(0); + stackPreview->setCurrentIndex(0); + + KColorButton * button; + foreach (button, m_commonColorButtons) + { + button->blockSignals(true); + } + + m_commonColorButtons[0]->setColor(m_colorSchemes[KColorScheme::View].background(KColorScheme::NormalBackground).color()); + m_commonColorButtons[1]->setColor(m_colorSchemes[KColorScheme::View].foreground(KColorScheme::NormalText).color()); + m_commonColorButtons[2]->setColor(m_colorSchemes[KColorScheme::Window].background(KColorScheme::NormalBackground).color()); + m_commonColorButtons[3]->setColor(m_colorSchemes[KColorScheme::Window].foreground(KColorScheme::NormalText).color()); + m_commonColorButtons[4]->setColor(m_colorSchemes[KColorScheme::Button].background(KColorScheme::NormalBackground).color()); + m_commonColorButtons[5]->setColor(m_colorSchemes[KColorScheme::Button].foreground(KColorScheme::NormalText).color()); + m_commonColorButtons[6]->setColor(m_colorSchemes[KColorScheme::Selection].background(KColorScheme::NormalBackground).color()); + m_commonColorButtons[7]->setColor(m_colorSchemes[KColorScheme::Selection].foreground(KColorScheme::NormalText).color()); + m_commonColorButtons[8]->setColor(m_colorSchemes[KColorScheme::Selection].foreground(KColorScheme::InactiveText).color()); + + setCommonForeground(KColorScheme::InactiveText, 0, 9); + setCommonForeground(KColorScheme::ActiveText, 1, 10); + setCommonForeground(KColorScheme::LinkText, 2, 11); + setCommonForeground(KColorScheme::VisitedText, 3, 12); + setCommonForeground(KColorScheme::NegativeText, 4, 13); + setCommonForeground(KColorScheme::NeutralText, 5, 14); + setCommonForeground(KColorScheme::PositiveText, 6, 15); + + setCommonDecoration(KColorScheme::FocusColor, 7, 16); + setCommonDecoration(KColorScheme::HoverColor, 8, 17); + + m_commonColorButtons[18]->setColor(m_colorSchemes[KColorScheme::Tooltip].background(KColorScheme::NormalBackground).color()); + m_commonColorButtons[19]->setColor(m_colorSchemes[KColorScheme::Tooltip].foreground(KColorScheme::NormalText).color()); + + m_commonColorButtons[20]->setColor(m_wmColors.color(WindecoColors::ActiveBackground)); + m_commonColorButtons[21]->setColor(m_wmColors.color(WindecoColors::ActiveForeground)); + m_commonColorButtons[22]->setColor(m_wmColors.color(WindecoColors::ActiveBlend)); + m_commonColorButtons[23]->setColor(m_wmColors.color(WindecoColors::InactiveBackground)); + m_commonColorButtons[24]->setColor(m_wmColors.color(WindecoColors::InactiveForeground)); + m_commonColorButtons[25]->setColor(m_wmColors.color(WindecoColors::InactiveBlend)); + + foreach (button, m_commonColorButtons) + { + button->blockSignals(false); + } + } + else + { + // a real color set is selected + setPreview->setPalette(m_config, (KColorScheme::ColorSet)currentSet); + stackColors->setCurrentIndex(1); + stackPreview->setCurrentIndex(1); + + for (int i = KColorScheme::NormalBackground; i <= KColorScheme::AlternateBackground; ++i) + { + m_backgroundButtons[i]->blockSignals(true); + m_backgroundButtons[i]->setColor(m_colorSchemes[currentSet].background(KColorScheme::BackgroundRole(i)).color()); + m_backgroundButtons[i]->blockSignals(false); + } + + for (int i = KColorScheme::NormalText; i <= KColorScheme::PositiveText; ++i) + { + m_foregroundButtons[i]->blockSignals(true); + m_foregroundButtons[i]->setColor(m_colorSchemes[currentSet].foreground(KColorScheme::ForegroundRole(i)).color()); + m_foregroundButtons[i]->blockSignals(false); + } + + for (int i = KColorScheme::FocusColor; i <= KColorScheme::HoverColor; ++i) + { + m_decorationButtons[i]->blockSignals(true); + m_decorationButtons[i]->setColor(m_colorSchemes[currentSet].decoration(KColorScheme::DecorationRole(i)).color()); + m_decorationButtons[i]->blockSignals(false); + } + } +} + +void KColorCm::colorChanged( const QColor &newColor ) +{ + // find which button was changed + const int row = sender()->objectName().toInt(); + changeColor(row, newColor); +} + +void KColorCm::changeColor(int row, const QColor &newColor) +{ + // update the m_colorSchemes for the selected colorSet + const int currentSet = colorSet->currentIndex() - 1; + + if (currentSet == -1) + { + // common colors is selected + switch (row) + { + case 0: + // View Background button + KConfigGroup(m_config, "Colors:View").writeEntry("BackgroundNormal", newColor); + break; + case 1: + // View Text button + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundNormal", newColor); + break; + case 2: + // Window Background Button + KConfigGroup(m_config, "Colors:Window").writeEntry("BackgroundNormal", newColor); + break; + case 3: + // Window Text Button + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundNormal", newColor); + break; + case 4: + // Button Background button + KConfigGroup(m_config, "Colors:Button").writeEntry("BackgroundNormal", newColor); + break; + case 5: + // Button Text button + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundNormal", newColor); + break; + case 6: + // Selection Background Button + KConfigGroup(m_config, "Colors:Selection").writeEntry("BackgroundNormal", newColor); + break; + case 7: + // Selection Text Button + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundNormal", newColor); + break; + case 8: + // Selection Inactive Text Button + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundInactive", newColor); + break; + + // buttons that could have varies in their place + case 9: + // Inactive Text Button (set all but Selection Inactive Text color) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundInactive", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundInactive", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundInactive", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundInactive", newColor); + break; + case 10: + // Active Text Button (set all active text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundActive", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundActive", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundActive", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundActive", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundActive", newColor); + break; + case 11: + // Link Text Button (set all link text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundLink", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundLink", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundLink", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundLink", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundLink", newColor); + break; + case 12: + // Visited Text Button (set all visited text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundVisited", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundVisited", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundVisited", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundVisited", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundVisited", newColor); + break; + case 13: + // Negative Text Button (set all negative text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundNegative", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundNegative", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundNegative", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundNegative", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundNegative", newColor); + break; + case 14: + // Neutral Text Button (set all neutral text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundNeutral", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundNeutral", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundNeutral", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundNeutral", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundNeutral", newColor); + break; + case 15: + // Positive Text Button (set all positive text colors) + KConfigGroup(m_config, "Colors:View").writeEntry("ForegroundPositive", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("ForegroundPositive", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("ForegroundPositive", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("ForegroundPositive", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundPositive", newColor); + break; + + case 16: + // Focus Decoration Button (set all focus decoration colors) + KConfigGroup(m_config, "Colors:View").writeEntry("DecorationFocus", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("DecorationFocus", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("DecorationFocus", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("DecorationFocus", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("DecorationFocus", newColor); + break; + case 17: + // Hover Decoration Button (set all hover decoration colors) + KConfigGroup(m_config, "Colors:View").writeEntry("DecorationHover", newColor); + KConfigGroup(m_config, "Colors:Window").writeEntry("DecorationHover", newColor); + KConfigGroup(m_config, "Colors:Selection").writeEntry("DecorationHover", newColor); + KConfigGroup(m_config, "Colors:Button").writeEntry("DecorationHover", newColor); + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("DecorationHover", newColor); + break; + + case 18: + // Tooltip Background button + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("BackgroundNormal", newColor); + break; + case 19: + // Tooltip Text button + KConfigGroup(m_config, "Colors:Tooltip").writeEntry("ForegroundNormal", newColor); + break; + case 20: + // Active Title Background + KConfigGroup(m_config, "WM").writeEntry("activeBackground", newColor); + break; + case 21: + // Active Title Text + KConfigGroup(m_config, "WM").writeEntry("activeForeground", newColor); + break; + case 22: + // Active Title Secondary + KConfigGroup(m_config, "WM").writeEntry("activeBlend", newColor); + break; + case 23: + // Inactive Title Background + KConfigGroup(m_config, "WM").writeEntry("inactiveBackground", newColor); + break; + case 24: + // Inactive Title Text + KConfigGroup(m_config, "WM").writeEntry("inactiveForeground", newColor); + break; + case 25: + // Inactive Title Secondary + KConfigGroup(m_config, "WM").writeEntry("inactiveBlend", newColor); + break; + } + m_commonColorButtons[row]->blockSignals(true); + m_commonColorButtons[row]->setColor(newColor); + m_commonColorButtons[row]->blockSignals(false); + } + else + { + QString group = colorSetGroupKey(currentSet); + KConfigGroup(m_config, group).writeEntry(m_colorKeys[row], newColor); + } + + QIcon icon = createSchemePreviewIcon(m_config); + schemeList->item(0)->setIcon(icon); + updateColorSchemes(); + updatePreviews(); + + m_loadedSchemeHasUnsavedChanges = true; + m_currentColorScheme = i18nc("Current color scheme", "Current"); + KConfigGroup group(m_config, "General"); + group.writeEntry("ColorScheme", m_currentColorScheme); + schemeRemoveButton->setEnabled(false); + schemeKnsUploadButton->setEnabled(false); + schemeList->blockSignals(true); // don't emit changed signals + schemeList->setCurrentRow(0); + schemeList->blockSignals(false); + + emit changed(true); +} + +QString KColorCm::colorSetGroupKey(int colorSet) +{ + QString group; + switch (colorSet) { + case KColorScheme::Window: + group = "Colors:Window"; + break; + case KColorScheme::Button: + group = "Colors:Button"; + break; + case KColorScheme::Selection: + group = "Colors:Selection"; + break; + case KColorScheme::Tooltip: + group = "Colors:Tooltip"; + break; + default: + group = "Colors:View"; + } + return group; +} + +void KColorCm::on_contrastSlider_valueChanged(int value) +{ + KConfigGroup group(m_config, "KDE"); + group.writeEntry("contrast", value); + + updatePreviews(); + + emit changed(true); +} + +void KColorCm::on_shadeSortedColumn_stateChanged(int state) +{ + KConfigGroup group(m_config, "General"); + group.writeEntry("shadeSortColumn", bool(state != Qt::Unchecked)); + + emit changed(true); +} + +void KColorCm::on_useInactiveEffects_stateChanged(int state) +{ + KConfigGroup group(m_config, "ColorEffects:Inactive"); + group.writeEntry("Enable", bool(state != Qt::Unchecked)); + + m_disableUpdates = true; + printf("re-init\n"); + inactiveSelectionEffect->setChecked(group.readEntry("ChangeSelectionColor", bool(state != Qt::Unchecked))); + m_disableUpdates = false; + + emit changed(true); +} + +void KColorCm::on_inactiveSelectionEffect_stateChanged(int state) +{ + if (m_disableUpdates) + { + // don't write the config as we are reading it! + return; + } + + KConfigGroup group(m_config, "ColorEffects:Inactive"); + group.writeEntry("ChangeSelectionColor", bool(state != Qt::Unchecked)); + + emit changed(true); +} + +void KColorCm::load() +{ + loadInternal(true); + + // get colorscheme name from global settings + KConfigGroup group(m_config, "General"); + m_currentColorScheme = group.readEntry("ColorScheme"); + if (m_currentColorScheme == i18nc("Current color scheme", "Current")) + { + m_loadedSchemeHasUnsavedChanges = true; + } + QList itemList = schemeList->findItems(m_currentColorScheme, Qt::MatchExactly); + if(!itemList.isEmpty()) // "Current" is already selected, so don't handle the case that itemList is empty + schemeList->setCurrentItem(itemList.at(0)); + + KConfig cfg("kcmdisplayrc", KConfig::NoGlobals); + group = KConfigGroup(&cfg, "X11"); + + applyToAlien->blockSignals(true); // don't emit SIGNAL(toggled(bool)) which would call SLOT(emitChanged()) + applyToAlien->setChecked(group.readEntry("exportKDEColors", true)); + applyToAlien->blockSignals(false); +} + +void KColorCm::loadOptions() +{ + contrastSlider->setValue(KGlobalSettings::contrast()); + shadeSortedColumn->setChecked(KGlobalSettings::shadeSortColumn()); + + KConfigGroup group(m_config, "ColorEffects:Inactive"); + useInactiveEffects->setChecked(group.readEntry("Enable", false)); + // NOTE: keep this in sync with kdelibs/kdeui/colors/kcolorscheme.cpp + // NOTE: remove extra logic from updateFromOptions and on_useInactiveEffects_stateChanged when this changes! + inactiveSelectionEffect->setChecked(group.readEntry("ChangeSelectionColor", group.readEntry("Enable", true))); +} + +void KColorCm::loadInternal(bool loadOptions_) +{ + // clean the config, in case we have changed the in-memory kconfig + m_config->markAsClean(); + m_config->reparseConfiguration(); + + // update the color table + updateColorSchemes(); + updateColorTable(); + + // fill in the color scheme list + populateSchemeList(); + + if (loadOptions_) + loadOptions(); + + updateEffectsPage(); + + updatePreviews(); + + m_loadedSchemeHasUnsavedChanges = false; + + emit changed(false); +} + +void KColorCm::save() +{ + QIcon icon = createSchemePreviewIcon(m_config); + schemeList->item(0)->setIcon(icon); + + KConfigGroup groupI(m_config, "ColorEffects:Inactive"); + + groupI.writeEntry("Enable", useInactiveEffects->isChecked()); + groupI.writeEntry("IntensityEffect", inactiveIntensityBox->currentIndex()); + groupI.writeEntry("ColorEffect", inactiveColorBox->currentIndex()); + groupI.writeEntry("ContrastEffect", inactiveContrastBox->currentIndex()); + + m_config->sync(); + KGlobalSettings::self()->emitChange(KGlobalSettings::PaletteChanged); + if (qApp->platformName() == QStringLiteral("xcb")) { + // Send signal to all kwin instances + QDBusMessage message = + QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); + QDBusConnection::sessionBus().send(message); + } + + KConfig cfg("kcmdisplayrc", KConfig::NoGlobals); + KConfigGroup displayGroup(&cfg, "X11"); + + displayGroup.writeEntry("exportKDEColors", applyToAlien->isChecked()); + cfg.sync(); + + runRdb(KRdbExportQtColors | KRdbExportGtkTheme | ( applyToAlien->isChecked() ? KRdbExportColors : 0 ) ); + + emit changed(false); +} + +void KColorCm::defaults() +{ + // Switch to default scheme + for(int i = 0; i < schemeList->count(); ++i) { + QListWidgetItem *item = schemeList->item(i); + if(item->text() == i18nc("Default color scheme", "Default")) { + // If editing the default scheme, force a reload, else select the default scheme + if(schemeList->currentItem() == item) + loadScheme(item, item); + else + schemeList->setCurrentItem(item); + m_currentColorScheme = item->text(); + break; + } + } + + // Reset options (not part of scheme) + m_config->setReadDefaults(true); + loadOptions(); + m_config->setReadDefaults(false); + applyToAlien->setChecked(Qt::Checked); + + KCModule::defaults(); + emit changed(true); +} + +void KColorCm::emitChanged() +{ + emit changed(true); +} + +// inactive effects slots +void KColorCm::on_inactiveIntensityBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveIntensitySlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveColorBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveColorSlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveColorButton_changed(const QColor& color) +{ + Q_UNUSED( color ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveContrastBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_inactiveContrastSlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + inactivePreview->setPalette(m_config, QPalette::Inactive); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +// disabled effects slots +void KColorCm::on_disabledIntensityBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledIntensitySlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledColorBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledColorSlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledColorButton_changed(const QColor& color) +{ + Q_UNUSED( color ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledContrastBox_currentIndexChanged(int index) +{ + Q_UNUSED( index ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +void KColorCm::on_disabledContrastSlider_valueChanged(int value) +{ + Q_UNUSED( value ); + + updateFromEffectsPage(); + disabledPreview->setPalette(m_config, QPalette::Disabled); + + m_loadedSchemeHasUnsavedChanges = true; + + emit changed(true); +} + +#include "colorscm.moc" diff --git a/kcms/colors/colorscm.h b/kcms/colors/colorscm.h new file mode 100644 index 0000000000..376a112be2 --- /dev/null +++ b/kcms/colors/colorscm.h @@ -0,0 +1,216 @@ +/* KDE Display color scheme setup module + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 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. + * + * 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 __COLORSCM_H__ +#define __COLORSCM_H__ + +#include +#include +#include + +#include "ui_colorsettings.h" + +class QStackedWidget; +class QListWidgetItem; + +/** + * The Desktop/Colors tab in kcontrol. + */ +class KColorCm : public KCModule, public Ui::colorSettings +{ + Q_OBJECT + +public: + KColorCm(QWidget *parent, const QVariantList &); + ~KColorCm(); + +public Q_SLOTS: + + /// load the settings from the config + virtual void load(); + + /// save the current settings + virtual void save(); + + /// sets the configuration to sensible default values. + virtual void defaults(); + +private Q_SLOTS: + + /** set the colortable color buttons up according to the current colorset */ + void updateColorTable(); + + /** slot called when color on a KColorButton changes */ + void colorChanged( const QColor &newColor ); + + /** slot called when any varies button is clicked */ + void variesClicked(); + + /** slot called when the schemeList selection changes */ + void loadScheme(QListWidgetItem *currentItem, QListWidgetItem *previousItem); + + /** reselect the previously selected scheme in schemeList without loading it */ + void selectPreviousSchemeAgain(); + + /** slot called when the remove button is clicked*/ + void on_schemeRemoveButton_clicked(); + + /** slot called when the save button is clicked */ + void on_schemeSaveButton_clicked(); + + /** slot called when the import button is clicked */ + void on_schemeImportButton_clicked(); + + /** slot called when the get new schemes button is clicked */ + void on_schemeKnsButton_clicked(); + + /** slot called when the upload scheme button is clicked */ + void on_schemeKnsUploadButton_clicked(); + + /** null slot to emit changed(true) */ + void emitChanged(); + + // options slots + void on_contrastSlider_valueChanged(int value); + void on_shadeSortedColumn_stateChanged(int state); + void on_inactiveSelectionEffect_stateChanged(int state); + void on_useInactiveEffects_stateChanged(int state); + + // effects page slots + void on_inactiveIntensityBox_currentIndexChanged(int index); + void on_inactiveIntensitySlider_valueChanged(int value); + void on_inactiveColorBox_currentIndexChanged(int index); + void on_inactiveColorSlider_valueChanged(int value); + void on_inactiveColorButton_changed(const QColor & color); + void on_inactiveContrastBox_currentIndexChanged(int index); + void on_inactiveContrastSlider_valueChanged(int value); + + void on_disabledIntensityBox_currentIndexChanged(int index); + void on_disabledIntensitySlider_valueChanged(int value); + void on_disabledColorBox_currentIndexChanged(int index); + void on_disabledColorSlider_valueChanged(int value); + void on_disabledColorButton_changed(const QColor & color); + void on_disabledContrastBox_currentIndexChanged(int index); + void on_disabledContrastSlider_valueChanged(int value); + +private: + class WindecoColors { + public: + enum Role { + ActiveForeground = 0, + ActiveBackground = 1, + InactiveForeground = 2, + InactiveBackground = 3, + ActiveBlend = 4, + InactiveBlend = 5 + }; + + WindecoColors() {} + WindecoColors(const KSharedConfigPtr&); + virtual ~WindecoColors() {} + + void load(const KSharedConfigPtr&); + QColor color(Role) const; + private: + QColor m_colors[6]; + }; + + /** create a preview of a color scheme */ + static QPixmap createSchemePreviewIcon(const KSharedConfigPtr &config); + + /** load options from global */ + void loadOptions(); + + /** load from global */ + void loadInternal(bool loadOptions); + + /** load a scheme from a config file at a given path */ + void loadScheme(KSharedConfigPtr config); + + /** populate the schemeList with color schemes found on the system */ + void populateSchemeList(); + + /** update m_colorSchemes contents from the values in m_config */ + void updateColorSchemes(); + + /** update the effects page from the values in m_config */ + void updateEffectsPage(); + + /** update all preview panes from the values in m_config */ + void updatePreviews(); + + /** setup the colortable with its buttons and labels */ + void setupColorTable(); + + /** helper to create color entries */ + void createColorEntry(const QString &text, + const QString &key, + QList &list, + int index); + + /** copy color entries from color schemes into m_config */ + void updateFromColorSchemes(); + + /** copy effects page entries from controls into m_config */ + void updateFromEffectsPage(); + + /** copy options from controls into m_config */ + void updateFromOptions(); + + void changeColor(int row, const QColor &newColor); + + /** get the groupKey for the given colorSet */ + static QString colorSetGroupKey(int colorSet); + + /** save the current scheme with the given name + @param name name to save the scheme as + */ + void saveScheme(const QString &name); + + void setCommonForeground(KColorScheme::ForegroundRole role, + int stackIndex, + int buttonIndex); + void setCommonDecoration(KColorScheme::DecorationRole role, + int stackIndex, + int buttonIndex); + + QList m_backgroundButtons; + QList m_foregroundButtons; + QList m_decorationButtons; + QList m_commonColorButtons; + QList m_stackedWidgets; + QStringList m_colorKeys; + + QList m_colorSchemes; + WindecoColors m_wmColors; + QString m_currentColorScheme; + + KSharedConfigPtr m_config; + + bool m_disableUpdates; + bool m_loadedSchemeHasUnsavedChanges; + // don't (re)load the scheme, only select it in schemeList + bool m_dontLoadSelectedScheme; + + // the item previously selected in schemeList + QListWidgetItem *m_previousSchemeItem; +}; + +#endif diff --git a/kcms/colors/colorsettings.ui b/kcms/colors/colorsettings.ui new file mode 100644 index 0000000000..cbc2e84d36 --- /dev/null +++ b/kcms/colors/colorsettings.ui @@ -0,0 +1,1298 @@ + + + colorSettings + + + + 0 + 0 + 477 + 422 + + + + + 0 + + + + + 0 + + + + &Scheme + + + + + + + 0 + 0 + + + + + 23 + 16 + + + + + + + + + + Get new color schemes from the Internet + + + Get &New Schemes... + + + + + + + false + + + Share the selected scheme on the Internet + + + &Upload Scheme... + + + + + + + Import a color scheme from a file + + + Import Scheme... + + + + + + + Save the current color scheme + + + Save Scheme... + + + + + + + false + + + Remove the selected scheme + + + Remove Scheme + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + Preview + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + + + + + + + + Options + + + + + + Apply inactive window color &effects + + + + + + + In&active selection changes color + + + + + + + Shade sorted column &in lists + + + + + + + true + + + Apply colors to &non-KDE4 applications + + + + + + + Shading of frames and lighting ("3D") effects + + + Shading + + + + 12 + + + 0 + + + + + Minimum + + + + + + + Qt::Horizontal + + + + 198 + 20 + + + + + + + + Maximum + + + + + + + Contrast + + + + + + + 10 + + + 5 + + + Qt::Horizontal + + + + + + + + + + Qt::Vertical + + + + 20 + 141 + + + + + + + + + Colors + + + + + + + 0 + 0 + + + + Color set: + + + + + + + + 0 + 0 + + + + Colorset to view/modify + + + + Common Colors + + + + + View + + + + + Window + + + + + Button + + + + + Selection + + + + + Tooltip + + + + + + + + 0 + + + + + 0 + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + 2 + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + New Row + + + + + 0 + + + + + 1 + + + + + View Background + + + + + View Text + + + + + Window Background + + + + + Window Text + + + + + Button Background + + + + + Button Text + + + + + Selection Background + + + + + Selection Text + + + + + Selection Inactive Text + + + + + Inactive Text + + + + + Active Text + + + + + Link Text + + + + + Visited Text + + + + + Negative Text + + + + + Neutral Text + + + + + Positive Text + + + + + Focus Decoration + + + + + Hover Decoration + + + + + Tooltip Background + + + + + Tooltip Text + + + + + Active Titlebar + + + + + Active Titlebar Text + + + + + Active Titlebar Secondary + + + + + Inactive Titlebar + + + + + Inactive Titlebar Text + + + + + Inactive Titlebar Secondary + + + + + + + + + + 0 + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + 2 + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Preview + + + + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + + + + + + + + + + + + Inactive + + + + + + Intensity: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Inactive intensity effect type + + + + None + + + + + Shade + + + + + Darken + + + + + Lighten + + + + + + + + false + + + Inactive intensity effect amount + + + 40 + + + 10 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 69 + 22 + + + + + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Inactive color effect type + + + + None + + + + + Desaturate + + + + + Fade + + + + + Tint + + + + + + + + false + + + Inactive color amount + + + 40 + + + 10 + + + Qt::Horizontal + + + + + + + false + + + Inactive color + + + + + + + Contrast: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Inactive contrast effect type + + + + None + + + + + Fade + + + + + Tint + + + + + + + + false + + + Inactive contrast effect amount + + + 20 + + + 5 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 69 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Preview + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + + + + + + + + Disabled + + + + + + Intensity: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Disabled intensity effect type + + + + None + + + + + Shade + + + + + Darken + + + + + Lighten + + + + + + + + false + + + Disabled intensity effect amount + + + 40 + + + 10 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 69 + 22 + + + + + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Disabled color effect type + + + + None + + + + + Desaturate + + + + + Fade + + + + + Tint + + + + + + + + false + + + Disabled color effect amount + + + 40 + + + 10 + + + Qt::Horizontal + + + + + + + false + + + Disabled color + + + + + + + Contrast: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Disabled contrast type + + + + None + + + + + Fade + + + + + Tint + + + + + + + + false + + + Disabled contrast amount + + + 20 + + + 10 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 69 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Preview + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + + + + + + + + + + + + KListWidget + QListWidget +
    klistwidget.h
    +
    + + KPushButton + QPushButton +
    kpushbutton.h
    +
    + + KColorButton + QPushButton +
    kcolorbutton.h
    +
    + + PreviewWidget + QWidget +
    previewwidget.h
    + 1 +
    + + SetPreviewWidget + QWidget +
    setpreviewwidget.h
    + 1 +
    +
    + + tabWidget + schemeList + schemeKnsButton + schemeImportButton + schemeSaveButton + schemeRemoveButton + useInactiveEffects + inactiveSelectionEffect + shadeSortedColumn + applyToAlien + contrastSlider + colorSet + commonColorTable + inactiveIntensityBox + inactiveIntensitySlider + inactiveColorBox + inactiveColorSlider + inactiveContrastBox + inactiveContrastSlider + inactiveColorButton + disabledIntensityBox + disabledIntensitySlider + disabledColorBox + disabledColorSlider + disabledContrastBox + disabledContrastSlider + disabledColorButton + colorTable + + + +
    diff --git a/kcms/colors/preview.ui b/kcms/colors/preview.ui new file mode 100644 index 0000000000..8dde5c139c --- /dev/null +++ b/kcms/colors/preview.ui @@ -0,0 +1,336 @@ + + + preview + + + + 0 + 0 + 467 + 100 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Window text on Window Background + + + Window text + + + + + + + true + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + + + + 2 + + + + + View Normal Text against View Normal Background + + + Normal text + + + + + + + + true + + + + View Link Text against View Normal Background + + + link + + + + + + + + true + + + + View Visited Text against View Normal Background + + + visited + + + + + + + View Active Text against View Normal Background + + + a + + + + + + + View Inactive Text against View Normal Background + + + i + + + + + + + View Negative Text against View Normal Background + + + ! + + + + + + + View Neutral Text against View Normal Background + + + = + + + + + + + View Positive Text against View Normal Background + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 4 + 51 + + + + + + + + true + + + + 2 + + + + + Selection Normal Text against Selection Normal Background + + + Selected text + + + + + + + + true + + + + Selection Link Text against Selection Normal Background + + + link + + + + + + + + true + + + + Selection Visited Text against Selection Normal Background + + + visited + + + + + + + Selection Active Text against Selection Normal Background + + + a + + + + + + + Selection Inactive Text against Selection Normal Background + + + i + + + + + + + Selection Negative Text against Selection Normal Background + + + ! + + + + + + + Selection Neutral Text against Selection Normal Background + + + = + + + + + + + Selection Positive Text against Selection Normal Background + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 141 + 0 + + + + + + + + + + + Button text on Button Background + + + Push Button + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + + + + diff --git a/kcms/colors/previewwidget.cpp b/kcms/colors/previewwidget.cpp new file mode 100644 index 0000000000..5be7567a6c --- /dev/null +++ b/kcms/colors/previewwidget.cpp @@ -0,0 +1,168 @@ +/* Preview widget for KDE Display color scheme setup module + * Copyright (C) 2007 Matthew Woehlke + * eventFilter code Copyright (C) 2007 Urs Wolfer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "previewwidget.h" + +#include +#include + +#include + +PreviewWidget::PreviewWidget(QWidget *parent) : QFrame(parent) +{ + setupUi(this); + + // set correct colors on... lots of things + setAutoFillBackground(true); + frame->setBackgroundRole(QPalette::Base); + viewWidget->setBackgroundRole(QPalette::Base); + labelView0->setBackgroundRole(QPalette::Base); + labelView3->setBackgroundRole(QPalette::Base); + labelView4->setBackgroundRole(QPalette::Base); + labelView2->setBackgroundRole(QPalette::Base); + labelView1->setBackgroundRole(QPalette::Base); + labelView5->setBackgroundRole(QPalette::Base); + labelView6->setBackgroundRole(QPalette::Base); + labelView7->setBackgroundRole(QPalette::Base); + selectionWidget->setBackgroundRole(QPalette::Highlight); + labelSelection0->setBackgroundRole(QPalette::Highlight); + labelSelection3->setBackgroundRole(QPalette::Highlight); + labelSelection4->setBackgroundRole(QPalette::Highlight); + labelSelection2->setBackgroundRole(QPalette::Highlight); + labelSelection1->setBackgroundRole(QPalette::Highlight); + labelSelection5->setBackgroundRole(QPalette::Highlight); + labelSelection6->setBackgroundRole(QPalette::Highlight); + labelSelection7->setBackgroundRole(QPalette::Highlight); + + QList widgets = findChildren(); + foreach (QWidget* widget, widgets) + { + widget->installEventFilter(this); + widget->setFocusPolicy(Qt::NoFocus); + } +} + +PreviewWidget::~PreviewWidget() +{ +} + +bool PreviewWidget::eventFilter(QObject *, QEvent *ev) +{ + switch (ev->type()) + { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::Enter: + case QEvent::Leave: + case QEvent::Wheel: + case QEvent::ContextMenu: + return true; // ignore + default: + break; + } + return false; +} + +inline void copyPaletteBrush(QPalette &palette, QPalette::ColorGroup state, + QPalette::ColorRole role) +{ + palette.setBrush(QPalette::Active, role, palette.brush(state, role)); + if (state == QPalette::Disabled) + // ### hack, while Qt has no inactive+disabled state + // TODO copy from Inactive+Disabled to Inactive instead + palette.setBrush(QPalette::Inactive, role, + palette.brush(QPalette::Disabled, role)); +} + +void PreviewWidget::setPaletteRecursive(QWidget *widget, + const QPalette &palette) +{ + widget->setPalette(palette); + + const QObjectList children = widget->children(); + foreach (QObject *child, children) { + if (child->isWidgetType()) + setPaletteRecursive((QWidget*)child, palette); + } +} + +inline void adjustWidgetForeground(QWidget *widget, QPalette::ColorGroup state, + const KSharedConfigPtr &config, + QPalette::ColorRole color, + KColorScheme::ColorSet set, + KColorScheme::ForegroundRole role) +{ + QPalette palette = widget->palette(); + KColorScheme::adjustForeground(palette, role, color, set, config); + copyPaletteBrush(palette, state, color); + widget->setPalette(palette); +} + +void PreviewWidget::setPalette(const KSharedConfigPtr &config, + QPalette::ColorGroup state) +{ + QPalette palette = KGlobalSettings::createNewApplicationPalette(config); + + if (state != QPalette::Active) { + copyPaletteBrush(palette, state, QPalette::Base); + copyPaletteBrush(palette, state, QPalette::Text); + copyPaletteBrush(palette, state, QPalette::Window); + copyPaletteBrush(palette, state, QPalette::WindowText); + copyPaletteBrush(palette, state, QPalette::Button); + copyPaletteBrush(palette, state, QPalette::ButtonText); + copyPaletteBrush(palette, state, QPalette::Highlight); + copyPaletteBrush(palette, state, QPalette::HighlightedText); + copyPaletteBrush(palette, state, QPalette::AlternateBase); + copyPaletteBrush(palette, state, QPalette::Link); + copyPaletteBrush(palette, state, QPalette::LinkVisited); + copyPaletteBrush(palette, state, QPalette::Light); + copyPaletteBrush(palette, state, QPalette::Midlight); + copyPaletteBrush(palette, state, QPalette::Mid); + copyPaletteBrush(palette, state, QPalette::Dark); + copyPaletteBrush(palette, state, QPalette::Shadow); + } + + setPaletteRecursive(this, palette); + +#define ADJUST_WIDGET_FOREGROUND(w,c,s,r) \ + adjustWidgetForeground(w, state, config, QPalette::c, KColorScheme::s, KColorScheme::r); + + ADJUST_WIDGET_FOREGROUND(labelView1, Text, View, InactiveText); + ADJUST_WIDGET_FOREGROUND(labelView2, Text, View, ActiveText); + ADJUST_WIDGET_FOREGROUND(labelView3, Text, View, LinkText); + ADJUST_WIDGET_FOREGROUND(labelView4, Text, View, VisitedText); + ADJUST_WIDGET_FOREGROUND(labelView5, Text, View, NegativeText); + ADJUST_WIDGET_FOREGROUND(labelView6, Text, View, NeutralText); + ADJUST_WIDGET_FOREGROUND(labelView7, Text, View, PositiveText); + + ADJUST_WIDGET_FOREGROUND(labelSelection1, HighlightedText, Selection, InactiveText); + ADJUST_WIDGET_FOREGROUND(labelSelection2, HighlightedText, Selection, ActiveText); + ADJUST_WIDGET_FOREGROUND(labelSelection3, HighlightedText, Selection, LinkText); + ADJUST_WIDGET_FOREGROUND(labelSelection4, HighlightedText, Selection, VisitedText); + ADJUST_WIDGET_FOREGROUND(labelSelection5, HighlightedText, Selection, NegativeText); + ADJUST_WIDGET_FOREGROUND(labelSelection6, HighlightedText, Selection, NeutralText); + ADJUST_WIDGET_FOREGROUND(labelSelection7, HighlightedText, Selection, PositiveText); +} + +#include "previewwidget.moc" diff --git a/kcms/colors/previewwidget.h b/kcms/colors/previewwidget.h new file mode 100644 index 0000000000..44b1d541cf --- /dev/null +++ b/kcms/colors/previewwidget.h @@ -0,0 +1,49 @@ +/* Preview widget for KDE Display color scheme setup module + * Copyright (C) 2007 Matthew Woehlke + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __SCHEMEPREVIEW_H__ +#define __SCHEMEPREVIEW_H__ + +#include +#include + +#include + +#include "ui_preview.h" + +/** + * The Desktop/Colors tab in kcontrol. + */ +class PreviewWidget : public QFrame, Ui::preview +{ + Q_OBJECT + +public: + PreviewWidget(QWidget *parent); + virtual ~PreviewWidget(); + + void setPalette(const KSharedConfigPtr &config, + QPalette::ColorGroup state = QPalette::Active); + +protected: + void setPaletteRecursive(QWidget*, const QPalette&); + bool eventFilter(QObject *, QEvent *); +}; + +#endif diff --git a/kcms/colors/schemes/Honeycomb.colors b/kcms/colors/schemes/Honeycomb.colors new file mode 100644 index 0000000000..2db8c570bb --- /dev/null +++ b/kcms/colors/schemes/Honeycomb.colors @@ -0,0 +1,96 @@ +[ColorEffects:Disabled] +Color=48,43,30 +ColorAmount=0.125 +ColorEffect=2 +ContrastAmount=0.5 +ContrastEffect=1 +IntensityAmount=0.05 +IntensityEffect=0 + +[ColorEffects:Inactive] +Color=227,170,0 +ColorAmount=0.025 +ColorEffect=2 +ContrastAmount=0.25 +ContrastEffect=1 +IntensityAmount=0.05 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=136,138,133 +BackgroundNormal=186,189,183 +DecorationFocus=85,85,85 +DecorationHover=243,195,0 +ForegroundActive=191,92,0 +ForegroundInactive=117,80,25 +ForegroundLink=232,82,144 +ForegroundNegative=191,3,3 +ForegroundNeutral=43,116,199 +ForegroundNormal=0,0,0 +ForegroundPositive=0,137,43 +ForegroundVisited=100,74,155 + +[Colors:Selection] +BackgroundAlternate=243,195,0 +BackgroundNormal=227,170,0 +DecorationFocus=85,85,85 +DecorationHover=243,195,0 +ForegroundActive=191,92,0 +ForegroundInactive=255,235,85 +ForegroundLink=232,82,144 +ForegroundNegative=191,3,3 +ForegroundNeutral=43,116,199 +ForegroundNormal=255,255,255 +ForegroundPositive=0,137,43 +ForegroundVisited=100,74,155 + +[Colors:Tooltip] +BackgroundAlternate=255,235,85 +BackgroundNormal=255,242,153 +DecorationFocus=85,85,85 +DecorationHover=243,195,0 +ForegroundActive=191,92,0 +ForegroundInactive=117,80,25 +ForegroundLink=232,82,144 +ForegroundNegative=191,3,3 +ForegroundNeutral=43,116,199 +ForegroundNormal=64,48,0 +ForegroundPositive=0,137,43 +ForegroundVisited=100,74,155 + +[Colors:View] +BackgroundAlternate=255,251,231 +BackgroundNormal=255,255,255 +DecorationFocus=85,85,85 +DecorationHover=243,195,0 +ForegroundActive=191,92,0 +ForegroundInactive=117,80,25 +ForegroundLink=232,82,144 +ForegroundNegative=191,3,3 +ForegroundNeutral=43,116,199 +ForegroundNormal=0,0,0 +ForegroundPositive=0,137,43 +ForegroundVisited=100,74,155 + +[Colors:Window] +BackgroundAlternate=186,189,183 +BackgroundNormal=212,215,208 +DecorationFocus=85,85,85 +DecorationHover=243,195,0 +ForegroundActive=191,92,0 +ForegroundInactive=117,80,25 +ForegroundLink=232,82,144 +ForegroundNegative=191,3,3 +ForegroundNeutral=43,116,199 +ForegroundNormal=0,0,0 +ForegroundPositive=0,137,43 +ForegroundVisited=100,74,155 + +[General] +Name=Honeycomb + +[WM] +activeBackground=227,170,0 +activeForeground=255,255,255 +inactiveBackground=136,138,133 +inactiveForeground=46,52,54 diff --git a/kcms/colors/schemes/Norway.colors b/kcms/colors/schemes/Norway.colors new file mode 100644 index 0000000000..abf78bcd84 --- /dev/null +++ b/kcms/colors/schemes/Norway.colors @@ -0,0 +1,96 @@ +[ColorEffects:Disabled] +Color=197,179,153 +ColorAmount=0.5 +ColorEffect=2 +ContrastAmount=0.25 +ContrastEffect=1 +IntensityAmount=0.25 +IntensityEffect=0 + +[ColorEffects:Inactive] +Color=213,198,176 +ColorAmount=0.1 +ColorEffect=2 +ContrastAmount=0.25 +ContrastEffect=1 +IntensityAmount=-0.05 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=246,240,227 +BackgroundNormal=247,242,232 +DecorationFocus=128,112,96 +DecorationHover=29,135,205 +ForegroundActive=0,197,204 +ForegroundInactive=197,179,153 +ForegroundLink=0,87,174 +ForegroundNegative=232,87,82 +ForegroundNeutral=227,170,0 +ForegroundNormal=0,0,0 +ForegroundPositive=120,183,83 +ForegroundVisited=100,74,155 + +[Colors:Selection] +BackgroundAlternate=27,131,196 +BackgroundNormal=29,132,205 +DecorationFocus=128,112,96 +DecorationHover=29,135,205 +ForegroundActive=0,197,204 +ForegroundInactive=144,192,232 +ForegroundLink=0,87,174 +ForegroundNegative=232,87,82 +ForegroundNeutral=227,170,0 +ForegroundNormal=255,255,255 +ForegroundPositive=120,183,83 +ForegroundVisited=100,74,155 + +[Colors:Tooltip] +BackgroundAlternate=250,248,241 +BackgroundNormal=253,252,251 +DecorationFocus=128,112,96 +DecorationHover=29,135,205 +ForegroundActive=0,197,204 +ForegroundInactive=197,179,153 +ForegroundLink=0,87,174 +ForegroundNegative=232,87,82 +ForegroundNeutral=227,170,0 +ForegroundNormal=0,0,0 +ForegroundPositive=120,183,83 +ForegroundVisited=100,74,155 + +[Colors:View] +BackgroundAlternate=250,246,239 +BackgroundNormal=253,252,250 +DecorationFocus=128,112,96 +DecorationHover=29,135,205 +ForegroundActive=0,197,204 +ForegroundInactive=197,179,153 +ForegroundLink=0,87,174 +ForegroundNegative=232,87,82 +ForegroundNeutral=227,170,0 +ForegroundNormal=0,0,0 +ForegroundPositive=120,183,83 +ForegroundVisited=100,74,155 + +[Colors:Window] +BackgroundAlternate=233,223,206 +BackgroundNormal=235,226,210 +DecorationFocus=128,112,96 +DecorationHover=29,135,205 +ForegroundActive=0,197,204 +ForegroundInactive=197,179,153 +ForegroundLink=0,87,174 +ForegroundNegative=232,87,82 +ForegroundNeutral=227,170,0 +ForegroundNormal=0,0,0 +ForegroundPositive=120,183,83 +ForegroundVisited=100,74,155 + +[General] +Name=Norway + +[WM] +activeBackground=29,135,205 +activeForeground=255,255,255 +inactiveBackground=128,112,96 +inactiveForeground=253,252,251 diff --git a/kcms/colors/schemes/ObsidianCoast.colors b/kcms/colors/schemes/ObsidianCoast.colors new file mode 100644 index 0000000000..0245ee1805 --- /dev/null +++ b/kcms/colors/schemes/ObsidianCoast.colors @@ -0,0 +1,95 @@ +[ColorEffects:Disabled] +ColorAmount=-0.8 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0.25 +IntensityEffect=2 + +[ColorEffects:Inactive] +Color=0,0,0 +ColorAmount=0.025 +ColorEffect=2 +ContrastAmount=0.4 +ContrastEffect=2 +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=66,65,64 +BackgroundNormal=64,63,62 +DecorationFocus=39,94,160 +DecorationHover=87,129,176 +ForegroundActive=150,191,240 +ForegroundInactive=120,119,117 +ForegroundLink=80,142,216 +ForegroundNegative=232,88,72 +ForegroundNeutral=192,162,95 +ForegroundNormal=232,230,227 +ForegroundPositive=120,183,83 +ForegroundVisited=142,121,165 + +[Colors:Selection] +BackgroundAlternate=22,68,120 +BackgroundNormal=24,72,128 +DecorationFocus=39,94,160 +DecorationHover=87,129,176 +ForegroundActive=150,191,240 +ForegroundInactive=81,119,166 +ForegroundLink=80,142,216 +ForegroundNegative=232,88,72 +ForegroundNeutral=192,162,95 +ForegroundNormal=255,255,255 +ForegroundPositive=120,183,83 +ForegroundVisited=142,121,165 + +[Colors:Tooltip] +BackgroundAlternate=17,51,86 +BackgroundNormal=16,48,80 +DecorationFocus=39,94,160 +DecorationHover=87,129,176 +ForegroundActive=150,191,240 +ForegroundInactive=120,119,117 +ForegroundLink=80,142,216 +ForegroundNegative=232,88,72 +ForegroundNeutral=192,162,95 +ForegroundNormal=196,209,224 +ForegroundPositive=120,183,83 +ForegroundVisited=142,121,165 + +[Colors:View] +BackgroundAlternate=36,35,35 +BackgroundNormal=32,31,31 +DecorationFocus=39,94,160 +DecorationHover=87,129,176 +ForegroundActive=150,191,240 +ForegroundInactive=120,119,117 +ForegroundLink=80,142,216 +ForegroundNegative=232,88,72 +ForegroundNeutral=192,162,95 +ForegroundNormal=212,210,207 +ForegroundPositive=120,183,83 +ForegroundVisited=142,121,165 + +[Colors:Window] +BackgroundAlternate=52,51,50 +BackgroundNormal=48,47,47 +DecorationFocus=39,94,160 +DecorationHover=87,129,176 +ForegroundActive=150,191,240 +ForegroundInactive=120,119,117 +ForegroundLink=80,142,216 +ForegroundNegative=232,88,72 +ForegroundNeutral=192,162,95 +ForegroundNormal=224,222,219 +ForegroundPositive=120,183,83 +ForegroundVisited=142,121,165 + +[General] +Name=Obsidian Coast + +[WM] +activeBackground=19,47,80 +activeForeground=255,255,255 +inactiveBackground=64,63,62 +inactiveForeground=128,127,125 diff --git a/kcms/colors/schemes/Oxygen.colors b/kcms/colors/schemes/Oxygen.colors new file mode 100644 index 0000000000..da9116b39a --- /dev/null +++ b/kcms/colors/schemes/Oxygen.colors @@ -0,0 +1,103 @@ +[ColorEffects:Disabled] +Color=56,56,56 +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0.1 +IntensityEffect=2 + +[ColorEffects:Inactive] +ChangeSelectionColor=true +Color=112,111,110 +ColorAmount=-0.9 +ColorEffect=1 +ContrastAmount=0.25 +ContrastEffect=2 +Enable=true +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=224,223,222 +BackgroundNormal=223,220,217 +DecorationFocus=58,167,221 +DecorationHover=110,214,255 +ForegroundActive=146,76,157 +ForegroundInactive=137,136,135 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=34,31,30 +ForegroundPositive=0,110,40 +ForegroundVisited=100,74,155 + +[Colors:Selection] +BackgroundAlternate=62,138,204 +BackgroundNormal=67,172,232 +DecorationFocus=58,167,221 +DecorationHover=110,214,255 +ForegroundActive=108,36,119 +ForegroundInactive=199,226,248 +ForegroundLink=0,49,110 +ForegroundNegative=156,14,14 +ForegroundNeutral=255,221,0 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=69,40,134 + +[Colors:Tooltip] +BackgroundAlternate=196,224,255 +BackgroundNormal=24,21,19 +DecorationFocus=58,167,221 +DecorationHover=110,214,255 +ForegroundActive=255,128,224 +ForegroundInactive=137,136,135 +ForegroundLink=88,172,255 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=231,253,255 +ForegroundPositive=0,110,40 +ForegroundVisited=150,111,232 + +[Colors:View] +BackgroundAlternate=248,247,246 +BackgroundNormal=255,255,255 +DecorationFocus=58,167,221 +DecorationHover=110,214,255 +ForegroundActive=146,76,157 +ForegroundInactive=137,136,135 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=31,28,27 +ForegroundPositive=0,110,40 +ForegroundVisited=100,74,155 + +[Colors:Window] +BackgroundAlternate=218,217,216 +BackgroundNormal=214,210,208 +DecorationFocus=58,167,221 +DecorationHover=110,214,255 +ForegroundActive=146,76,157 +ForegroundInactive=137,136,135 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=34,31,30 +ForegroundPositive=0,110,40 +ForegroundVisited=100,74,155 + +[General] +ColorScheme=Oxygen +Name=Oxygen +shadeSortColumn=true + +[KDE] +contrast=7 + +[WM] +activeBackground=48,174,232 +activeForeground=255,255,255 +inactiveBackground=224,223,222 +inactiveForeground=75,71,67 diff --git a/kcms/colors/schemes/OxygenCold.colors b/kcms/colors/schemes/OxygenCold.colors new file mode 100644 index 0000000000..53d7777bb8 --- /dev/null +++ b/kcms/colors/schemes/OxygenCold.colors @@ -0,0 +1,95 @@ +[ColorEffects:Disabled] +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0.1 +IntensityEffect=2 + +[ColorEffects:Inactive] +Color=112,111,110 +ColorAmount=0.025 +ColorEffect=2 +ContrastAmount=0.1 +ContrastEffect=2 +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=224,223,222 +BackgroundNormal=232,231,230 +DecorationFocus=43,116,199 +DecorationHover=119,183,255 +ForegroundActive=255,128,224 +ForegroundInactive=136,135,134 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=20,19,18 +ForegroundPositive=0,110,40 +ForegroundVisited=69,40,134 + +[Colors:Selection] +BackgroundAlternate=62,138,204 +BackgroundNormal=65,139,212 +DecorationFocus=43,116,199 +DecorationHover=119,183,255 +ForegroundActive=255,128,224 +ForegroundInactive=165,193,228 +ForegroundLink=0,49,110 +ForegroundNegative=156,14,14 +ForegroundNeutral=255,221,0 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=69,40,134 + +[Colors:Tooltip] +BackgroundAlternate=196,224,255 +BackgroundNormal=192,218,255 +DecorationFocus=43,116,199 +DecorationHover=119,183,255 +ForegroundActive=255,128,224 +ForegroundInactive=96,112,128 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=20,19,18 +ForegroundPositive=0,110,40 +ForegroundVisited=69,40,134 + +[Colors:View] +BackgroundAlternate=248,247,246 +BackgroundNormal=255,255,255 +DecorationFocus=43,116,199 +DecorationHover=119,183,255 +ForegroundActive=255,128,224 +ForegroundInactive=136,135,134 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=20,19,18 +ForegroundPositive=0,110,40 +ForegroundVisited=69,40,134 + +[Colors:Window] +BackgroundAlternate=218,217,216 +BackgroundNormal=224,223,222 +DecorationFocus=43,116,199 +DecorationHover=119,183,255 +ForegroundActive=255,128,224 +ForegroundInactive=136,135,134 +ForegroundLink=0,87,174 +ForegroundNegative=191,3,3 +ForegroundNeutral=176,128,0 +ForegroundNormal=20,19,18 +ForegroundPositive=0,110,40 +ForegroundVisited=69,40,134 + +[General] +Name=Oxygen Cold + +[WM] +activeBackground=96,148,207 +activeForeground=255,255,255 +inactiveBackground=224,223,222 +inactiveForeground=20,19,18 diff --git a/kcms/colors/schemes/Steel.colors b/kcms/colors/schemes/Steel.colors new file mode 100644 index 0000000000..3ebd8b4c32 --- /dev/null +++ b/kcms/colors/schemes/Steel.colors @@ -0,0 +1,95 @@ +[ColorEffects:Disabled] +ColorAmount=-0.9 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0.25 +IntensityEffect=2 + +[ColorEffects:Inactive] +Color=135,133,129 +ColorAmount=0.05 +ColorEffect=2 +ContrastAmount=0.25 +ContrastEffect=2 +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=224,223,216 +BackgroundNormal=232,231,223 +DecorationFocus=69,98,112 +DecorationHover=74,139,163 +ForegroundActive=232,87,82 +ForegroundInactive=148,133,111 +ForegroundLink=41,111,190 +ForegroundNegative=139,83,127 +ForegroundNeutral=191,165,103 +ForegroundNormal=0,0,0 +ForegroundPositive=67,102,46 +ForegroundVisited=100,74,155 + +[Colors:Selection] +BackgroundAlternate=118,154,165 +BackgroundNormal=123,160,173 +DecorationFocus=69,98,112 +DecorationHover=74,139,163 +ForegroundActive=232,87,82 +ForegroundInactive=178,197,204 +ForegroundLink=41,111,190 +ForegroundNegative=139,83,127 +ForegroundNeutral=191,165,103 +ForegroundNormal=255,255,255 +ForegroundPositive=67,102,46 +ForegroundVisited=100,74,155 + +[Colors:Tooltip] +BackgroundAlternate=216,228,231 +BackgroundNormal=219,231,235 +DecorationFocus=69,98,112 +DecorationHover=74,139,163 +ForegroundActive=232,87,82 +ForegroundInactive=148,133,111 +ForegroundLink=41,111,190 +ForegroundNegative=139,83,127 +ForegroundNeutral=191,165,103 +ForegroundNormal=37,34,28 +ForegroundPositive=67,102,46 +ForegroundVisited=100,74,155 + +[Colors:View] +BackgroundAlternate=250,250,248 +BackgroundNormal=255,255,255 +DecorationFocus=69,98,112 +DecorationHover=74,139,163 +ForegroundActive=232,87,82 +ForegroundInactive=148,133,111 +ForegroundLink=41,111,190 +ForegroundNegative=139,83,127 +ForegroundNeutral=191,165,103 +ForegroundNormal=0,0,0 +ForegroundPositive=67,102,46 +ForegroundVisited=100,74,155 + +[Colors:Window] +BackgroundAlternate=212,211,204 +BackgroundNormal=224,223,216 +DecorationFocus=69,98,112 +DecorationHover=74,139,163 +ForegroundActive=232,87,82 +ForegroundInactive=148,133,111 +ForegroundLink=41,111,190 +ForegroundNegative=139,83,127 +ForegroundNeutral=191,165,103 +ForegroundNormal=0,0,0 +ForegroundPositive=67,102,46 +ForegroundVisited=100,74,155 + +[General] +Name=Steel + +[WM] +activeBackground=74,139,163 +activeForeground=255,255,255 +inactiveBackground=208,206,192 +inactiveForeground=100,92,72 diff --git a/kcms/colors/schemes/WontonSoup.colors b/kcms/colors/schemes/WontonSoup.colors new file mode 100644 index 0000000000..34ebaa9913 --- /dev/null +++ b/kcms/colors/schemes/WontonSoup.colors @@ -0,0 +1,94 @@ +[ColorEffects:Disabled] +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0.25 +IntensityEffect=2 + +[ColorEffects:Inactive] +ColorAmount=0 +ColorEffect=0 +ContrastAmount=0.25 +ContrastEffect=2 +IntensityAmount=0.05 +IntensityEffect=2 + +[Colors:Button] +BackgroundAlternate=90,98,109 +BackgroundNormal=82,88,99 +DecorationFocus=125,141,153 +DecorationHover=119,149,179 +ForegroundActive=255,255,255 +ForegroundInactive=135,143,154 +ForegroundLink=156,212,255 +ForegroundNegative=225,150,209 +ForegroundNeutral=218,198,115 +ForegroundNormal=210,222,240 +ForegroundPositive=145,221,100 +ForegroundVisited=64,128,255 + +[Colors:Selection] +BackgroundAlternate=111,126,144 +BackgroundNormal=120,136,156 +DecorationFocus=125,141,153 +DecorationHover=119,149,179 +ForegroundActive=255,255,255 +ForegroundInactive=174,192,218 +ForegroundLink=156,212,255 +ForegroundNegative=225,150,209 +ForegroundNeutral=218,198,115 +ForegroundNormal=209,225,244 +ForegroundPositive=145,221,100 +ForegroundVisited=64,128,255 + +[Colors:Tooltip] +BackgroundAlternate=171,181,195 +BackgroundNormal=182,193,208 +DecorationFocus=125,141,153 +DecorationHover=119,149,179 +ForegroundActive=255,255,255 +ForegroundInactive=112,118,128 +ForegroundLink=87,161,218 +ForegroundNegative=99,66,92 +ForegroundNeutral=86,78,45 +ForegroundNormal=42,44,48 +ForegroundPositive=57,86,38 +ForegroundVisited=46,95,185 + +[Colors:View] +BackgroundAlternate=67,71,80 +BackgroundNormal=60,64,72 +DecorationFocus=125,141,153 +DecorationHover=119,149,179 +ForegroundActive=255,255,255 +ForegroundInactive=135,143,154 +ForegroundLink=156,212,255 +ForegroundNegative=225,150,209 +ForegroundNeutral=218,198,115 +ForegroundNormal=210,222,240 +ForegroundPositive=145,221,100 +ForegroundVisited=64,128,255 + +[Colors:Window] +BackgroundAlternate=78,83,94 +BackgroundNormal=73,78,88 +DecorationFocus=125,141,153 +DecorationHover=119,149,179 +ForegroundActive=255,255,255 +ForegroundInactive=135,143,154 +ForegroundLink=156,212,255 +ForegroundNegative=225,150,209 +ForegroundNeutral=218,198,115 +ForegroundNormal=182,193,208 +ForegroundPositive=145,221,100 +ForegroundVisited=64,128,255 + +[General] +Name=Wonton Soup + +[WM] +activeBackground=138,151,166 +activeForeground=224,237,255 +inactiveBackground=82,89,99 +inactiveForeground=140,152,168 diff --git a/kcms/colors/schemes/Zion.colors b/kcms/colors/schemes/Zion.colors new file mode 100644 index 0000000000..4427567df9 --- /dev/null +++ b/kcms/colors/schemes/Zion.colors @@ -0,0 +1,96 @@ +[ColorEffects:Disabled] +Color=210,205,218 +ColorAmount=-0.9 +ColorEffect=0 +ContrastAmount=0.65 +ContrastEffect=1 +IntensityAmount=0 +IntensityEffect=0 + +[ColorEffects:Inactive] +Color=0,0,0 +ColorAmount=0.5 +ColorEffect=1 +ContrastAmount=0.25 +ContrastEffect=1 +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=252,252,252 +BackgroundNormal=255,255,255 +DecorationFocus=128,128,128 +DecorationHover=0,0,0 +ForegroundActive=0,102,255 +ForegroundInactive=112,112,112 +ForegroundLink=0,0,192 +ForegroundNegative=128,0,0 +ForegroundNeutral=112,96,0 +ForegroundNormal=0,0,0 +ForegroundPositive=0,96,0 +ForegroundVisited=88,0,176 + +[Colors:Selection] +BackgroundAlternate=171,188,248 +BackgroundNormal=176,192,255 +DecorationFocus=128,128,128 +DecorationHover=0,0,0 +ForegroundActive=0,102,255 +ForegroundInactive=64,64,192 +ForegroundLink=0,0,192 +ForegroundNegative=128,0,0 +ForegroundNeutral=112,96,0 +ForegroundNormal=0,0,0 +ForegroundPositive=0,96,0 +ForegroundVisited=88,0,176 + +[Colors:Tooltip] +BackgroundAlternate=250,250,250 +BackgroundNormal=255,255,255 +DecorationFocus=128,128,128 +DecorationHover=0,0,0 +ForegroundActive=0,102,255 +ForegroundInactive=112,112,112 +ForegroundLink=0,0,192 +ForegroundNegative=128,0,0 +ForegroundNeutral=112,96,0 +ForegroundNormal=0,0,0 +ForegroundPositive=0,96,0 +ForegroundVisited=88,0,176 + +[Colors:View] +BackgroundAlternate=252,252,252 +BackgroundNormal=255,255,255 +DecorationFocus=128,128,128 +DecorationHover=0,0,0 +ForegroundActive=0,102,255 +ForegroundInactive=112,112,112 +ForegroundLink=0,0,192 +ForegroundNegative=128,0,0 +ForegroundNeutral=112,96,0 +ForegroundNormal=0,0,0 +ForegroundPositive=0,96,0 +ForegroundVisited=88,0,176 + +[Colors:Window] +BackgroundAlternate=248,248,248 +BackgroundNormal=252,252,252 +DecorationFocus=128,128,128 +DecorationHover=0,0,0 +ForegroundActive=0,102,255 +ForegroundInactive=112,112,112 +ForegroundLink=0,0,192 +ForegroundNegative=128,0,0 +ForegroundNeutral=112,96,0 +ForegroundNormal=0,0,0 +ForegroundPositive=0,96,0 +ForegroundVisited=88,0,176 + +[General] +Name=Zion + +[WM] +activeBackground=176,193,255 +activeForeground=0,0,0 +inactiveBackground=255,255,255 +inactiveForeground=0,0,0 diff --git a/kcms/colors/schemes/ZionReversed.colors b/kcms/colors/schemes/ZionReversed.colors new file mode 100644 index 0000000000..36131d4ac1 --- /dev/null +++ b/kcms/colors/schemes/ZionReversed.colors @@ -0,0 +1,96 @@ +[ColorEffects:Disabled] +Color=56,56,56 +ColorAmount=0.5 +ColorEffect=2 +ContrastAmount=0.5 +ContrastEffect=1 +IntensityAmount=0.05 +IntensityEffect=0 + +[ColorEffects:Inactive] +Color=0,0,0 +ColorAmount=0.5 +ColorEffect=1 +ContrastAmount=0.25 +ContrastEffect=2 +IntensityAmount=0 +IntensityEffect=0 + +[Colors:Button] +BackgroundAlternate=12,12,12 +BackgroundNormal=0,0,0 +DecorationFocus=192,192,192 +DecorationHover=255,255,255 +ForegroundActive=192,255,255 +ForegroundInactive=160,160,160 +ForegroundLink=128,181,255 +ForegroundNegative=255,128,172 +ForegroundNeutral=255,212,128 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=192,128,255 + +[Colors:Selection] +BackgroundAlternate=0,52,116 +BackgroundNormal=0,49,110 +DecorationFocus=192,192,192 +DecorationHover=255,255,255 +ForegroundActive=192,255,255 +ForegroundInactive=96,148,207 +ForegroundLink=128,181,255 +ForegroundNegative=255,128,172 +ForegroundNeutral=255,212,128 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=192,128,255 + +[Colors:Tooltip] +BackgroundAlternate=12,12,12 +BackgroundNormal=0,0,0 +DecorationFocus=192,192,192 +DecorationHover=255,255,255 +ForegroundActive=192,255,255 +ForegroundInactive=160,160,160 +ForegroundLink=128,181,255 +ForegroundNegative=255,128,172 +ForegroundNeutral=255,212,128 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=192,128,255 + +[Colors:View] +BackgroundAlternate=12,12,12 +BackgroundNormal=0,0,0 +DecorationFocus=192,192,192 +DecorationHover=255,255,255 +ForegroundActive=192,255,255 +ForegroundInactive=160,160,160 +ForegroundLink=128,181,255 +ForegroundNegative=255,128,172 +ForegroundNeutral=255,212,128 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=192,128,255 + +[Colors:Window] +BackgroundAlternate=20,20,20 +BackgroundNormal=16,16,16 +DecorationFocus=192,192,192 +DecorationHover=255,255,255 +ForegroundActive=192,255,255 +ForegroundInactive=160,160,160 +ForegroundLink=128,181,255 +ForegroundNegative=255,128,172 +ForegroundNeutral=255,212,128 +ForegroundNormal=255,255,255 +ForegroundPositive=128,255,128 +ForegroundVisited=192,128,255 + +[General] +Name=Zion (Reversed) + +[WM] +activeBackground=0,49,110 +activeForeground=255,255,255 +inactiveBackground=64,64,64 +inactiveForeground=128,128,128 diff --git a/kcms/colors/setpreview.ui b/kcms/colors/setpreview.ui new file mode 100644 index 0000000000..09ae55dee8 --- /dev/null +++ b/kcms/colors/setpreview.ui @@ -0,0 +1,347 @@ + + + setpreview + + + + 0 + 0 + 550 + 96 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + + + + + + Normal Text on Normal Background + + + normal + + + + + + + + + + + + + + true + + + + Link Text on Normal Background + + + link + + + + + + + + + + + + + + true + + + + Visited Text on Normal Background + + + visited + + + + + + + + + + Active Text on Normal Background + + + + + + active + + + + + + + + + + + + + Inactive Text on Normal Background + + + inactive + + + + + + + + + + + + + Negative Text on Normal Background + + + negative + + + + + + + + + + + + + Neutral Text on Normal Background + + + neutral + + + + + + + + + + + + + Positive Text on Normal Background + + + positive + + + + + + + + + + Hover on Normal Background + + + + + + hover + + + + + + + + + + + + + Normal Text on Normal Background + + + normal + + + + + + + + + + + + + + true + + + + Link Text on Link Background +(Note: Link Background is derived from Link Text and cannot be separately configured at this time) + + + link + + + + + + + + + + + + + + true + + + + Visited Text on Visited Background +(Note: Visited Background is derived from Visited Text and cannot be separately configured at this time) + + + visited + + + + + + + + + + + + + Active Text on Active Background +(Note: Active Background is derived from Active Text and cannot be separately configured at this time) + + + active + + + + + + + + + + + + + Inactive Text on Alternate Background + + + alternate + + + + + + + + + + + + + Negative Text on Negative Background +(Note: Negative Background is derived from Negative Text and cannot be separately configured at this time) + + + negative + + + + + + + + + + + + + Neutral Text on Neutral Background +(Note: Neutral Background is derived from Neutral Text and cannot be separately configured at this time) + + + neutral + + + + + + + + + + + + + Positive Text on Positive Background +(Note: Positive Background is derived from Positive Text and cannot be separately configured at this time) + + + positive + + + + + + + + + + + + + Focus on Normal Background + + + focus + + + + + + + + + + + diff --git a/kcms/colors/setpreviewwidget.cpp b/kcms/colors/setpreviewwidget.cpp new file mode 100644 index 0000000000..98413c556d --- /dev/null +++ b/kcms/colors/setpreviewwidget.cpp @@ -0,0 +1,138 @@ +/* Preview widget for KDE Display color scheme setup module + * Copyright (C) 2007 Matthew Woehlke + * eventFilter code Copyright (C) 2007 Urs Wolfer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "setpreviewwidget.h" + +#include + +void setAutoFill(QWidget* widget) +{ + widget->setAutoFillBackground(true); + widget->setBackgroundRole(QPalette::Base); +} + +SetPreviewWidget::SetPreviewWidget(QWidget *parent) : QFrame(parent) +{ + setupUi(this); + + // set correct colors on... lots of things + setAutoFillBackground(true); + setBackgroundRole(QPalette::Base); + setAutoFill(widgetBack0); + setAutoFill(widgetBack1); + setAutoFill(widgetBack2); + setAutoFill(widgetBack3); + setAutoFill(widgetBack4); + setAutoFill(widgetBack5); + setAutoFill(widgetBack6); + setAutoFill(widgetBack7); + setAutoFillBackground(true); +/* + frame->setBackgroundRole(QPalette::Base); + viewWidget->setBackgroundRole(QPalette::Base); + labelView0->setBackgroundRole(QPalette::Base); + labelView3->setBackgroundRole(QPalette::Base); + labelView4->setBackgroundRole(QPalette::Base); + labelView2->setBackgroundRole(QPalette::Base); + labelView1->setBackgroundRole(QPalette::Base); + labelView5->setBackgroundRole(QPalette::Base); + labelView6->setBackgroundRole(QPalette::Base); + labelView7->setBackgroundRole(QPalette::Base); + selectionWidget->setBackgroundRole(QPalette::Highlight); + labelSelection0->setBackgroundRole(QPalette::Highlight); + labelSelection3->setBackgroundRole(QPalette::Highlight); + labelSelection4->setBackgroundRole(QPalette::Highlight); + labelSelection2->setBackgroundRole(QPalette::Highlight); + labelSelection1->setBackgroundRole(QPalette::Highlight); + labelSelection5->setBackgroundRole(QPalette::Highlight); + labelSelection6->setBackgroundRole(QPalette::Highlight); + labelSelection7->setBackgroundRole(QPalette::Highlight); +*/ + + QList widgets = findChildren(); + foreach (QWidget* widget, widgets) + { + widget->installEventFilter(this); + widget->setFocusPolicy(Qt::NoFocus); + } +} + +SetPreviewWidget::~SetPreviewWidget() +{ +} + +bool SetPreviewWidget::eventFilter(QObject *, QEvent *ev) +{ + switch (ev->type()) + { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::Enter: + case QEvent::Leave: + case QEvent::Wheel: + case QEvent::ContextMenu: + return true; // ignore + default: + break; + } + return false; +} + +void SetPreviewWidget::setPalette(const KSharedConfigPtr &config, + KColorScheme::ColorSet set) +{ + QPalette palette = KGlobalSettings::createApplicationPalette(config); + KColorScheme::adjustBackground(palette, KColorScheme::NormalBackground, + QPalette::Base, set, config); + QFrame::setPalette(palette); + +#define SET_ROLE_PALETTE(n, f, b) \ + KColorScheme::adjustForeground(palette, KColorScheme::f, QPalette::Text, set, config); \ + labelFore##n->setPalette(palette); \ + KColorScheme::adjustBackground(palette, KColorScheme::b, QPalette::Base, set, config); \ + labelBack##n->setPalette(palette); \ + widgetBack##n->setPalette(palette); + + SET_ROLE_PALETTE(0, NormalText, NormalBackground); + SET_ROLE_PALETTE(1, InactiveText, AlternateBackground); + SET_ROLE_PALETTE(2, ActiveText, ActiveBackground); + SET_ROLE_PALETTE(3, LinkText, LinkBackground); + SET_ROLE_PALETTE(4, VisitedText, VisitedBackground); + SET_ROLE_PALETTE(5, NegativeText, NegativeBackground); + SET_ROLE_PALETTE(6, NeutralText, NeutralBackground); + SET_ROLE_PALETTE(7, PositiveText, PositiveBackground); + + KColorScheme kcs(QPalette::Active, set, config); + QBrush deco; + +#define SET_DECO_PALETTE(n, d) \ + deco = kcs.decoration(KColorScheme::d); \ + palette.setBrush(QPalette::Text, deco); \ + labelFore##n->setPalette(palette); \ + + SET_DECO_PALETTE(8, HoverColor); + SET_DECO_PALETTE(9, FocusColor); +} + +#include "setpreviewwidget.moc" diff --git a/kcms/colors/setpreviewwidget.h b/kcms/colors/setpreviewwidget.h new file mode 100644 index 0000000000..253414e84c --- /dev/null +++ b/kcms/colors/setpreviewwidget.h @@ -0,0 +1,49 @@ +/* Colorset Preview widget for KDE Display color scheme setup module + * Copyright (C) 2008 Matthew Woehlke + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __SCHEMEPREVIEWSET_H__ +#define __SCHEMEPREVIEWSET_H__ + +#include +#include + +#include +#include + +#include "ui_setpreview.h" + +/** + * The Desktop/Colors tab in kcontrol. + */ +class SetPreviewWidget : public QFrame, Ui::setpreview +{ + Q_OBJECT + +public: + SetPreviewWidget(QWidget *parent); + virtual ~SetPreviewWidget(); + + void setPalette(const KSharedConfigPtr &config, KColorScheme::ColorSet); + +protected: + void setPaletteRecursive(QWidget*, const QPalette&); + bool eventFilter(QObject *, QEvent *); +}; + +#endif diff --git a/kcms/dateandtime/CMakeLists.txt b/kcms/dateandtime/CMakeLists.txt new file mode 100644 index 0000000000..93099c8ee1 --- /dev/null +++ b/kcms/dateandtime/CMakeLists.txt @@ -0,0 +1,34 @@ +########### next target ############### + +set(kcm_clock_PART_SRCS dtime.cpp main.cpp ) + +kde4_add_ui_files(kcm_clock_PART_SRCS dateandtime.ui) +add_library(kcm_clock MODULE ${kcm_clock_PART_SRCS}) + +target_link_libraries(kcm_clock + Qt5::DBus + KF5::ItemViews + KF5::Auth + KF5::KCMUtils + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::Plasma + KF5::KDE4Support +) + +install(TARGETS kcm_clock DESTINATION ${PLUGIN_INSTALL_DIR} ) + +########### next target ############### + +add_executable(kcmdatetimehelper helper.cpp ${helper_mocs}) +target_link_libraries(kcmdatetimehelper KF5::Auth KF5::ConfigCore KF5::KDE4Support) +install(TARGETS kcmdatetimehelper DESTINATION ${LIBEXEC_INSTALL_DIR}) + +kauth_install_helper_files(kcmdatetimehelper org.kde.kcontrol.kcmclock root) + +kauth_install_actions(org.kde.kcontrol.kcmclock kcmclock_actions.actions) + +########### install files ############### + +install( FILES clock.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/kcms/dateandtime/Messages.sh b/kcms/dateandtime/Messages.sh new file mode 100644 index 0000000000..749f180170 --- /dev/null +++ b/kcms/dateandtime/Messages.sh @@ -0,0 +1,3 @@ +#! /usr/bin/env bash +$EXTRACTRC *.ui >> rc.cpp +$XGETTEXT *.cpp -o $podir/kcmkclock.pot diff --git a/kcms/dateandtime/clock.desktop b/kcms/dateandtime/clock.desktop new file mode 100644 index 0000000000..2c23adad7d --- /dev/null +++ b/kcms/dateandtime/clock.desktop @@ -0,0 +1,196 @@ +[Desktop Entry] +Exec=kcmshell5 clock +Icon=preferences-system-time +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/clock/index.html + +X-KDE-Library=kcm_clock +X-KDE-ParentApp=kcontrol + +#should this be in system settings when we can get to it through the panel? +#Answer: Yes. +X-KDE-System-Settings-Parent-Category=system-administration + +Name=Date & Time +Name[af]=Datum & Tyd +Name[ar]=التاريخ و الوقت +Name[ast]=Data y hora +Name[be]=Дата і час +Name[be@latin]=Data j čas +Name[bg]=Дата и час +Name[bn]=তারিখ এবং সময় +Name[bn_IN]=তারিখ ও সময় +Name[br]=Deiziad hag eur +Name[bs]=Datum i vrijeme +Name[ca]=Data i hora +Name[ca@valencia]=Data i hora +Name[cs]=Datum a čas +Name[csb]=Datum ë czas +Name[cy]=Dyddiad ac Amser +Name[da]=Dato og tid +Name[de]=Datum & Zeit +Name[el]=Ημερομηνία & Ώρα +Name[en_GB]=Date & Time +Name[eo]=Dato kaj Tempo +Name[es]=Fecha y hora +Name[et]=Kuupäev ja kellaaeg +Name[eu]=Data eta ordua +Name[fa]=تاریخ و زمان +Name[fi]=Aika ja päiväys +Name[fr]=Date et heure +Name[fy]=Datum en Tiid +Name[ga]=Dáta agus Am +Name[gl]=Data e hora +Name[gu]=તારીખ & સમય +Name[he]=תאריך ושעה +Name[hi]=तारीख़ व समय +Name[hne]=तारीक अउ समय +Name[hr]=Datum i vrijeme +Name[hsb]=Datum & čas +Name[hu]=Dátum és idő +Name[ia]=Data & Tempore +Name[id]=Tanggal & Waktu +Name[is]=Dagsetning og tími +Name[it]=Data e ora +Name[ja]=日付と時刻 +Name[ka]=თარიღი და დრო +Name[kk]=Күн мен уақыт +Name[km]=កាល​បរិច្ឆេទ និង​ពេលវេលា +Name[kn]=ದಿನಾಂಕ ಮತ್ತು ಸಮಯ +Name[ko]=날짜와 시간 +Name[ku]=Roj & Dem +Name[lt]=Data ir laikas +Name[lv]=Datums un laiks +Name[mai]=दिनाँक आ समय +Name[mk]=Датум и време +Name[ml]=തീയതിയും സമയവും +Name[mr]=दिनांक व वेळ +Name[ms]=Tarikh & Masa +Name[nb]=Dato og klokkeslett +Name[nds]=Datum & Tiet +Name[ne]=मिति र समय +Name[nl]=Datum en Tijd +Name[nn]=Dato og klokkeslett +Name[oc]=Data e ora +Name[or]=ତାରିଖ ଏବଂ ସମୟ +Name[pa]=ਮਿਤੀ ਅਤੇ ਟਾਈਮ +Name[pl]=Data i czas +Name[pt]=Data e Hora +Name[pt_BR]=Data e hora +Name[ro]=Data și ora +Name[ru]=Дата и время +Name[se]=Dáhton ja áigi +Name[si]=දිනය සහ වේලාව +Name[sk]=Dátum a čas +Name[sl]=Datum in čas +Name[sr]=Датум и време +Name[sr@ijekavian]=Датум и вријеме +Name[sr@ijekavianlatin]=Datum i vrijeme +Name[sr@latin]=Datum i vreme +Name[sv]=Datum och tid +Name[ta]=தேதி & நேரம் +Name[te]=తేది & సమయం +Name[tg]=Сана ва вақт +Name[th]=วันและเวลา +Name[tr]=Tarih ve Saat +Name[ug]=چېسلا & ۋاقىت +Name[uk]=Дата і час +Name[uz]=Sana va vaqt +Name[uz@cyrillic]=Сана ва вақт +Name[vi]=Ngày & giờ +Name[wa]=Date et eure +Name[xh]=Umhla & Ixesha +Name[x-test]=xxDate & Timexx +Name[zh_CN]=日期和时间 +Name[zh_TW]=日期和時間 + +Comment=Configure date and time settings +Comment[bs]=Podesi datum i vrijeme +Comment[ca]=Configuració de l'arranjament de la data i de l'hora +Comment[ca@valencia]=Configuració de l'arranjament de la data i de l'hora +Comment[cs]=Nastavení voleb data a času +Comment[da]=Indstilling af dato og tid +Comment[de]=Einstellungen für Datum und Zeit ändern +Comment[el]=Διαμόρφωση ρυθμίσεων ώρας και ημερομηνίας +Comment[es]=Configurar las preferencias de fecha y hora +Comment[et]=Kuupäeva ja kellaaja seadistamine +Comment[eu]=Konfiguratu data- eta ordu-ezarpenak +Comment[fi]=Aika-asetukset +Comment[fr]=Configuration des paramètres de date et d'heure +Comment[ga]=Cumraigh socruithe dáta agus ama +Comment[gl]=Configurar as opcións da data e hora +Comment[he]=הגדר זמן ותאריך +Comment[hu]=Dátum- és időbeállítások +Comment[ia]=Configura preferentias de data e tempore +Comment[is]=Stilla dagsetningu og tíma +Comment[it]=Configura le impostazioni della data e ora +Comment[kk]=Күн мен уақыт параметрлерін баптау +Comment[km]=កំណត់​រចនាសម្ព័ន្ធ​ការ​កំណត់កាលបរិច្ឆេទ និង​ពេលវេលា +Comment[ko]=날짜 및 시간 설정 변경 +Comment[lt]=Konfigūruoti datos ir laiko nustatymus +Comment[mr]=दिनांक व वेळ संयोजीत करा +Comment[nb]=Innstillinger for dato og tid +Comment[nds]=Instellen vun Datum un Tiet fastleggen +Comment[nl]=Instellingen van datum en tijd instellen +Comment[pa]=ਮਿਤੀ ਅਤੇ ਸਮਾਂ ਸੈਟਿੰਗ ਸੰਰਚਨਾ +Comment[pl]=Konfiguruj ustawienia daty i czasu +Comment[pt]=Configuração das opções da data e hora +Comment[pt_BR]=Configuração das opções de data e hora +Comment[ro]=Configurează opțiunile de dată și oră +Comment[ru]=Настройка даты и времени +Comment[sk]=Nastaviť nastavenia dátumu a času +Comment[sl]=Nastavi datum in čas +Comment[sr]=Подешавање датума и времена +Comment[sr@ijekavian]=Подешавање датума и времена +Comment[sr@ijekavianlatin]=Podešavanje datuma i vremena +Comment[sr@latin]=Podešavanje datuma i vremena +Comment[sv]=Anpassa inställningar av datum och tid +Comment[tr]=Tarih ve saat ayarlarını yapılandır +Comment[uk]=Налаштування параметрів дати і часу +Comment[vi]=Cấu hình thiết lập ngày giờ +Comment[x-test]=xxConfigure date and time settingsxx +Comment[zh_CN]=配置日期和时间设置 +Comment[zh_TW]=設定日期與時間 + +X-KDE-Keywords=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time +X-KDE-Keywords[bs]=sat,datum,vrijeme,vremenska zona,ntp,sinkronizirati,kalendar,lokalno vrijeme,regionalno vrijeme +X-KDE-Keywords[ca]=rellotge,data,hora,zona horària,ntp,sincronització,calendari,hora local,hora de la regió +X-KDE-Keywords[ca@valencia]=rellotge,data,hora,zona horària,ntp,sincronització,calendari,hora local,hora de la regió +X-KDE-Keywords[da]=ur,dato,tid,tidszone,ntp,synkroniser,kalender,lokal tid,regional tid +X-KDE-Keywords[de]=Uhr,Datum,Zeit,Zeitzone,ntp,synchronisation,abgleich,Kalender, +X-KDE-Keywords[el]=ρολόι,ημερομηνία,ώρα,ζώνη ώρας,ntp,συγχρονισμός,ημερολόγιο,τοπική ώρα,ώρα περιοχής +X-KDE-Keywords[es]=reloj,fecha,hora,zona horaria,ntp,sincronizar,calendario,hora local,hora regional +X-KDE-Keywords[et]=kell,kuupäev,kellaaeg,ajavöönd,ntp,sünkroonimine,sünkroniseerimine,kalender,kohalik aeg,vööndiaeg +X-KDE-Keywords[eu]=erloju,data,ordu,ordu-zona,ntp,sinkronizatu,egutegi,ordu lokal,eskualdeko ordu +X-KDE-Keywords[fi]=kello,päivä,päiväys,päivämäärä,aika,aikavyöhyke,ntp,synkronointi,kalenteri,paikallinen aika,alueellinen aika +X-KDE-Keywords[fr]=horloge, date, heure, zone horaire, ntp, synchronisation, calendrier, heure locale, heure régionale +X-KDE-Keywords[gl]=reloxo, data, hora, fuso, fuso horario, ntp, sincronizar, calendario, almanaque, hora local +X-KDE-Keywords[hu]=óra,dátum,idő,időzóna,ntp,szinkronizáció,naptár,helyi idő,régió idő +X-KDE-Keywords[ia]=horologio,data,tempore,fuso horari,ntp,synchronisa,calendario,tempore local,tempore de region +X-KDE-Keywords[it]=orologio,data,ora,fuso orario,ntp,sincronizza,calendario,ora locale,ora regionale +X-KDE-Keywords[kk]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time +X-KDE-Keywords[km]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time +X-KDE-Keywords[ko]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,시간,날짜,시간대,동기화 +X-KDE-Keywords[mr]=घड्याळ, दिनांक, वेळ, समय क्षेत्र, एन टी पी , सिन्क्रोनाइज़, दिनदर्शिका, स्थानिक वेळ, क्षेत्रीय वेळ +X-KDE-Keywords[nb]=klokke,dato,tid,tidssone,ntp,synkronisere,kalender,lokal tid,regiontid +X-KDE-Keywords[nds]=Klock,Datum,Tiet,Tietrebeet,NTP,synkroniseren,Kalenner,lokaal Tiet +X-KDE-Keywords[nl]=klok,datum,tijd,tijdzone,ntp,synchroniseren,agenda,lokale tijd,tijd in regio +X-KDE-Keywords[pl]=zegar,data,czas,strefa czasowa,ntp,synchronizuj,kalendarz,czas lokalny,czas regionalny +X-KDE-Keywords[pt]=relógio,data,hora,fuso-horário,ntp,sincronizar,calendário,hora local,hora regional +X-KDE-Keywords[pt_BR]=relógio,data,hora,fuso horário,ntp,sincronizar,calendário,hora local,hora regional +X-KDE-Keywords[ru]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,время,дата,часы,часовой пояс,синхронизировать,календарь,местное время,локальное время,региональное время +X-KDE-Keywords[sk]=hodiny,dátum,čas,časové pásmo,ntp,synchronizácia,kalendár,miestny čas,regionálny čas +X-KDE-Keywords[sl]=ura,datum,čas,časovni pas,ntp,uskladitev,koledar,krajevni čas,področni čas +X-KDE-Keywords[sr]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,сат,часовник,датум,време,временска зона,НТП,синхронизовати,календар,локално време +X-KDE-Keywords[sr@ijekavian]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,сат,часовник,датум,време,временска зона,НТП,синхронизовати,календар,локално време +X-KDE-Keywords[sr@ijekavianlatin]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,sat,časovnik,datum,vreme,vremenska zona,NTP,sinhronizovati,kalendar,lokalno vreme +X-KDE-Keywords[sr@latin]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,sat,časovnik,datum,vreme,vremenska zona,NTP,sinhronizovati,kalendar,lokalno vreme +X-KDE-Keywords[sv]=klocka,datum,tid,tidszon,ntp,synkronisera,kalender,lokal tid,områdestid +X-KDE-Keywords[tr]=saat,tarih,zaman,zaman dilimi,ntp,eşzamanlama,takvim,yerel saat,bölge saati +X-KDE-Keywords[uk]=годинник,дата,час,часовий пояс,синхронізація,календар,місцевий час,clock,date,time,time zone,ntp,synchronize,calendar,local time,region time +X-KDE-Keywords[x-test]=xxclock,date,time,time zone,ntp,synchronize,calendar,local time,region timexx +X-KDE-Keywords[zh_CN]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time,时钟,日期,时间,时区,同步,日历,本地时间,区域时间 +X-KDE-Keywords[zh_TW]=clock,date,time,time zone,ntp,synchronize,calendar,local time,region time + +Categories=Qt;KDE;X-KDE-settings-system; diff --git a/kcms/dateandtime/dateandtime.ui b/kcms/dateandtime/dateandtime.ui new file mode 100644 index 0000000000..c073b5e405 --- /dev/null +++ b/kcms/dateandtime/dateandtime.ui @@ -0,0 +1,198 @@ + + + Davide Bettio <davide.bettio@kdemail.net> + DateAndTime + + + + 0 + 0 + 613 + 463 + + + + + + + 0 + + + + Date and Time + + + + + + + + Set date and time &automatically: + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 13 + 21 + + + + + + + + Time server: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + timeServerList + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Here you can change the system date's day of the month, month and year. + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Time Zone + + + + + + To change the local time zone, select your area from the list below. + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 5 + + + + + + + + Current local time zone: + + + + + + + true + + + Search + + + + + + + + + + + + + + + + K4TimeZoneWidget + QTreeWidget +
    k4timezonewidget.h
    +
    + + KTreeWidgetSearchLine + KLineEdit +
    ktreewidgetsearchline.h
    +
    + + KLineEdit + QLineEdit +
    klineedit.h
    +
    + + KSeparator + QFrame +
    kseparator.h
    +
    + + KDatePicker + QFrame +
    kdatepicker.h
    +
    +
    + + +
    diff --git a/kcms/dateandtime/dtime.cpp b/kcms/dateandtime/dtime.cpp new file mode 100644 index 0000000000..e8511d1851 --- /dev/null +++ b/kcms/dateandtime/dtime.cpp @@ -0,0 +1,476 @@ +/* + * dtime.cpp + * + * Copyright (C) 1998 Luca Montecchiani + * + * Plasma analog-clock drawing code: + * + * Copyright 2007 by Aaron Seigo + * Copyright 2007 by Riccardo Iaconelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "dtime.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 "dtime.moc" + +#include "helper.h" + +Dtime::Dtime(QWidget * parent) + : QWidget(parent) +{ + setupUi(this); + + connect(setDateTimeAuto, SIGNAL(toggled(bool)), this, SLOT(serverTimeCheck())); + connect(setDateTimeAuto, SIGNAL(toggled(bool)), SLOT(configChanged())); + + timeServerList->setEditable(false); + connect(timeServerList, SIGNAL(activated(int)), SLOT(configChanged())); + connect(timeServerList, SIGNAL(editTextChanged(QString)), SLOT(configChanged())); + connect(setDateTimeAuto, SIGNAL(toggled(bool)), timeServerList, SLOT(setEnabled(bool))); + timeServerList->setEnabled(false); + timeServerList->setEditable(true); + findNTPutility(); + if (ntpUtility.isEmpty()) { + setDateTimeAuto->setEnabled(false); + setDateTimeAuto->setToolTip(i18n("No NTP utility has been found. " + "Install 'ntpdate' or 'rdate' command to enable automatic " + "updating of date and time.")); + } + + QVBoxLayout *v2 = new QVBoxLayout( timeBox ); + v2->setMargin( 0 ); + + kclock = new Kclock( timeBox ); + kclock->setObjectName("Kclock"); + kclock->setMinimumSize(150,150); + v2->addWidget( kclock ); + + v2->addSpacing( KDialog::spacingHint() ); + + QHBoxLayout *v3 = new QHBoxLayout( ); + v2->addLayout( v3 ); + + v3->addStretch(); + + timeEdit = new QTimeEdit( timeBox ); + timeEdit->setWrapping(true); + timeEdit->setDisplayFormat(KGlobal::locale()->use12Clock() ? "hh:mm:ss ap" : "HH:mm:ss"); + v3->addWidget(timeEdit); + + v3->addStretch(); + + QString wtstr = i18n("Here you can change the system time. Click into the" + " hours, minutes or seconds field to change the relevant value, either" + " using the up and down buttons to the right or by entering a new value."); + timeEdit->setWhatsThis( wtstr ); + + connect( timeEdit, SIGNAL(timeChanged(QTime)), SLOT(set_time()) ); + connect( cal, SIGNAL(dateChanged(QDate)), SLOT(changeDate(QDate))); + + connect( &internalTimer, SIGNAL(timeout()), SLOT(timeout()) ); + + kclock->setEnabled(false); + + //Timezone + connect( tzonelist, SIGNAL(itemSelectionChanged()), SLOT(configChanged()) ); + tzonesearch->setTreeWidget(tzonelist); +} + +void Dtime::currentZone() +{ + KTimeZone localZone = KSystemTimeZones::local(); + + if (localZone.abbreviations().isEmpty()) { + m_local->setText(i18nc("%1 is name of time zone", "Current local time zone: %1", + K4TimeZoneWidget::displayName(localZone))); + } else { + m_local->setText(i18nc("%1 is name of time zone, %2 is its abbreviation", + "Current local time zone: %1 (%2)", + K4TimeZoneWidget::displayName(localZone), + QString::fromUtf8(localZone.abbreviations().first()))); + } +} + +void Dtime::serverTimeCheck() { + bool enabled = !setDateTimeAuto->isChecked(); + cal->setEnabled(enabled); + timeEdit->setEnabled(enabled); + //kclock->setEnabled(enabled); +} + +void Dtime::findNTPutility(){ + QByteArray envpath = qgetenv("PATH"); + if (!envpath.isEmpty() && envpath[0] == ':') { + envpath = envpath.mid(1); + } + + QString path = "/sbin:/usr/sbin:"; + if (!envpath.isEmpty()) { + path += QString::fromLocal8Bit(envpath); + } else { + path += QLatin1String("/bin:/usr/bin"); + } + + foreach(const QString &possible_ntputility, QStringList() << "ntpdate" << "rdate" ) { + if( !((ntpUtility = KStandardDirs::findExe(possible_ntputility, path)).isEmpty()) ) { + kDebug() << "ntpUtility = " << ntpUtility; + return; + } + } + + kDebug() << "ntpUtility not found!"; +} + +void Dtime::set_time() +{ + if( ontimeout ) + return; + + internalTimer.stop(); + + time = timeEdit->time(); + kclock->setTime( time ); + + emit timeChanged( true ); +} + +void Dtime::changeDate(const QDate &d) +{ + date = d; + emit timeChanged( true ); +} + +void Dtime::configChanged(){ + emit timeChanged( true ); +} + +void Dtime::load() +{ + // The config is actually written to the system config, but the user does not have any local config, + // since there is nothing writing it. + KConfig _config( "kcmclockrc", KConfig::NoGlobals ); + KConfigGroup config(&_config, "NTP"); + timeServerList->clear(); + timeServerList->addItems(config.readEntry("servers", + i18n("Public Time Server (pool.ntp.org),\ +asia.pool.ntp.org,\ +europe.pool.ntp.org,\ +north-america.pool.ntp.org,\ +oceania.pool.ntp.org")).split(',', QString::SkipEmptyParts)); + setDateTimeAuto->setChecked(config.readEntry("enabled", false)); + + // Reset to the current date and time + time = QTime::currentTime(); + date = QDate::currentDate(); + cal->setDate(date); + + // start internal timer + internalTimer.start( 1000 ); + + timeout(); + + //Timezone + currentZone(); + + // read the currently set time zone + tzonelist->setSelected(KSystemTimeZones::local().name(), true); +} + +void Dtime::save( QVariantMap& helperargs ) +{ + // Save the order, but don't duplicate! + QStringList list; + if( timeServerList->count() != 0) + list.append(timeServerList->currentText()); + for ( int i=0; icount();i++ ) { + QString text = timeServerList->itemText(i); + if( !list.contains(text) ) + list.append(text); + // Limit so errors can go away and not stored forever + if( list.count() == 10) + break; + } + + helperargs["ntp"] = true; + helperargs["ntpServers"] = list; + helperargs["ntpEnabled"] = setDateTimeAuto->isChecked(); + helperargs["ntpUtility"] = ntpUtility; + + if(setDateTimeAuto->isChecked() && !ntpUtility.isEmpty()){ + // NTP Time setting - done in helper + timeServer = timeServerList->currentText(); + kDebug() << "Setting date from time server " << timeServer; + } + else { + // User time setting + QDateTime dt(date, QTime(timeEdit->time())); + + kDebug() << "Set date " << dt; + + helperargs["date"] = true; + helperargs["newdate"] = QString::number(dt.toTime_t()); + helperargs["olddate"] = QString::number(::time(0)); + } + + // restart time + internalTimer.start( 1000 ); + + QStringList selectedZones(tzonelist->selection()); + + if (selectedZones.count() > 0) { + QString selectedzone(selectedZones[0]); + helperargs["tz"] = true; + helperargs["tzone"] = selectedzone; + } else { + helperargs["tzreset"] = true; // // make the helper reset the timezone + } + + currentZone(); +} + +void Dtime::processHelperErrors( int code ) +{ + if( code & ClockHelper::NTPError ) { + KMessageBox::error( this, i18n("Unable to contact time server: %1.", timeServer) ); + setDateTimeAuto->setChecked( false ); + } + if( code & ClockHelper::DateError ) { + KMessageBox::error( this, i18n("Can not set date.")); + } + if( code & ClockHelper::TimezoneError) + KMessageBox::error( this, i18n("Error setting new time zone."), + i18n("Time zone Error")); +} + +void Dtime::timeout() +{ + // get current time + time = QTime::currentTime(); + + ontimeout = true; + timeEdit->setTime(time); + ontimeout = false; + + kclock->setTime( time ); +} + +QString Dtime::quickHelp() const +{ + return i18n("

    Date & Time

    This system settings module can be used to set the system date and" + " time. As these settings do not only affect you as a user, but rather the whole system, you" + " can only change these settings when you start the System Settings as root. If you do not have" + " the root password, but feel the system time should be corrected, please contact your system" + " administrator."); +} + +Kclock::Kclock(QWidget *parent) + : QWidget(parent) +{ + m_theme = new Plasma::Svg(this); + m_theme->setImagePath("widgets/clock"); + m_theme->setContainsMultipleImages(true); +} + +Kclock::~Kclock() +{ + delete m_theme; +} + +void Kclock::showEvent( QShowEvent *event ) +{ + setClockSize( size() ); + QWidget::showEvent( event ); +} + +void Kclock::resizeEvent( QResizeEvent * ) +{ + setClockSize( size() ); +} + +void Kclock::setClockSize(const QSize &size) +{ + int dim = qMin(size.width(), size.height()); + QSize newSize = QSize(dim, dim); + + if (newSize != m_faceCache.size()) { + m_faceCache = QPixmap(newSize); + m_handsCache = QPixmap(newSize); + m_glassCache = QPixmap(newSize); + + m_theme->resize(newSize); + m_repaintCache = RepaintAll; + } +} + +void Kclock::setTime(const QTime &time) +{ + if (time.minute() != this->time.minute() || time.hour() != this->time.hour()) { + if (m_repaintCache == RepaintNone) { + m_repaintCache = RepaintHands; + } + } + this->time = time; + update(); +} + +void Kclock::drawHand(QPainter *p, const QRect &rect, const qreal verticalTranslation, const qreal rotation, const QString &handName) +{ + // this code assumes the following conventions in the svg file: + // - the _vertical_ position of the hands should be set with respect to the center of the face + // - the _horizontal_ position of the hands does not matter + // - the _shadow_ elements should have the same vertical position as their _hand_ element counterpart + + QRectF elementRect; + QString name = handName + "HandShadow"; + if (m_theme->hasElement(name)) { + p->save(); + + elementRect = m_theme->elementRect(name); + if( rect.height() < 64 ) + elementRect.setWidth( elementRect.width() * 2.5 ); + static const QPoint offset = QPoint(2, 3); + + p->translate(rect.x() + (rect.width() / 2) + offset.x(), rect.y() + (rect.height() / 2) + offset.y()); + p->rotate(rotation); + p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation); + m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name); + + p->restore(); + } + + p->save(); + + name = handName + "Hand"; + elementRect = m_theme->elementRect(name); + if (rect.height() < 64) { + elementRect.setWidth(elementRect.width() * 2.5); + } + + p->translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2); + p->rotate(rotation); + p->translate(-elementRect.width()/2, elementRect.y()-verticalTranslation); + m_theme->paint(p, QRectF(QPointF(0, 0), elementRect.size()), name); + + p->restore(); +} + +void Kclock::paintInterface(QPainter *p, const QRect &rect) +{ + const bool m_showSecondHand = true; + + // compute hand angles + const qreal minutes = 6.0 * time.minute() - 180; + const qreal hours = 30.0 * time.hour() - 180 + + ((time.minute() / 59.0) * 30.0); + qreal seconds = 0; + if (m_showSecondHand) { + static const double anglePerSec = 6; + seconds = anglePerSec * time.second() - 180; + } + + // paint face and glass cache + QRect faceRect = m_faceCache.rect(); + if (m_repaintCache == RepaintAll) { + m_faceCache.fill(Qt::transparent); + m_glassCache.fill(Qt::transparent); + + QPainter facePainter(&m_faceCache); + QPainter glassPainter(&m_glassCache); + facePainter.setRenderHint(QPainter::SmoothPixmapTransform); + glassPainter.setRenderHint(QPainter::SmoothPixmapTransform); + + m_theme->paint(&facePainter, m_faceCache.rect(), "ClockFace"); + + glassPainter.save(); + QRectF elementRect = QRectF(QPointF(0, 0), m_theme->elementSize("HandCenterScrew")); + glassPainter.translate(faceRect.width() / 2 - elementRect.width() / 2, faceRect.height() / 2 - elementRect.height() / 2); + m_theme->paint(&glassPainter, elementRect, "HandCenterScrew"); + glassPainter.restore(); + + m_theme->paint(&glassPainter, faceRect, "Glass"); + + // get vertical translation, see drawHand() for more details + m_verticalTranslation = m_theme->elementRect("ClockFace").center().y(); + } + + // paint hour and minute hands cache + if (m_repaintCache == RepaintHands || m_repaintCache == RepaintAll) { + m_handsCache.fill(Qt::transparent); + + QPainter handsPainter(&m_handsCache); + handsPainter.drawPixmap(faceRect, m_faceCache, faceRect); + handsPainter.setRenderHint(QPainter::SmoothPixmapTransform); + + drawHand(&handsPainter, faceRect, m_verticalTranslation, hours, "Hour"); + drawHand(&handsPainter, faceRect, m_verticalTranslation, minutes, "Minute"); + } + + // reset repaint cache flag + m_repaintCache = RepaintNone; + + // paint caches and second hand + QRect targetRect = faceRect; + if (targetRect.width() < rect.width()) { + targetRect.moveLeft((rect.width() - targetRect.width()) / 2); + } + + p->drawPixmap(targetRect, m_handsCache, faceRect); + if (m_showSecondHand) { + p->setRenderHint(QPainter::SmoothPixmapTransform); + drawHand(p, targetRect, m_verticalTranslation, seconds, "Second"); + } + p->drawPixmap(targetRect, m_glassCache, faceRect); +} + +void Kclock::paintEvent( QPaintEvent * ) +{ + QPainter paint(this); + + paint.setRenderHint(QPainter::Antialiasing); + paintInterface(&paint, rect()); +} + diff --git a/kcms/dateandtime/dtime.h b/kcms/dateandtime/dtime.h new file mode 100644 index 0000000000..1a90698c6c --- /dev/null +++ b/kcms/dateandtime/dtime.h @@ -0,0 +1,121 @@ +/* + * dtime.h + * + * Copyright (C) 1998 Luca Montecchiani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 dtime_included +#define dtime_included + +#include "ui_dateandtime.h" + +#include +#include +#include +#include +#include +//Added by qt3to4: +#include + +#include +#include + +class Kclock; +class QTimeEdit; + +namespace Plasma { + class Svg; +} + +class Dtime : public QWidget, public Ui::DateAndTime +{ + Q_OBJECT + public: + Dtime( QWidget *parent=0 ); + + void save( QVariantMap &helperargs ); + void processHelperErrors( int code ); + void load(); + + QString quickHelp() const; + +Q_SIGNALS: + void timeChanged(bool); + + private Q_SLOTS: + void configChanged(); + void serverTimeCheck(); + void timeout(); + void set_time(); + void changeDate(const QDate&); + +private: + void currentZone(); + void findNTPutility(); + QString ntpUtility; + + QTimeEdit *timeEdit; + + Kclock *kclock; + + QTime time; + QDate date; + QTimer internalTimer; + + QString timeServer; + int BufI; + bool refresh; + bool ontimeout; +}; + +class Kclock : public QWidget +{ + Q_OBJECT + +public: + Kclock( QWidget *parent=0 ); + ~Kclock(); + + void setTime(const QTime&); + +protected: + virtual void paintEvent( QPaintEvent *event ); + virtual void showEvent( QShowEvent *event ); + virtual void resizeEvent( QResizeEvent *event ); + +private: + void setClockSize(const QSize &size); + void drawHand(QPainter *p, const QRect &rect, const qreal verticalTranslation, const qreal rotation, const QString &handName); + void paintInterface(QPainter *p, const QRect &rect); + +private: + QTime time; + Plasma::Svg *m_theme; + enum RepaintCache { + RepaintNone, + RepaintAll, + RepaintHands + }; + RepaintCache m_repaintCache; + QPixmap m_faceCache; + QPixmap m_handsCache; + QPixmap m_glassCache; + qreal m_verticalTranslation; +}; + +#endif // dtime_included diff --git a/kcms/dateandtime/helper.cpp b/kcms/dateandtime/helper.cpp new file mode 100644 index 0000000000..11207751ae --- /dev/null +++ b/kcms/dateandtime/helper.cpp @@ -0,0 +1,254 @@ +/* + * tzone.cpp + * + * Copyright (C) 1998 Luca Montecchiani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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. + * + */ + +/* + + A helper that's run using KAuth and does the system modifications. + +*/ + +#include "helper.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(USE_SOLARIS) +#include +#include +#include +#include +#endif + +// We cannot rely on the $PATH environment variable, because D-Bus activation +// clears it. So we have to use a reasonable default. +static const QString exePath = QLatin1String("/usr/sbin:/usr/bin:/sbin:/bin"); + +int ClockHelper::ntp( const QStringList& ntpServers, bool ntpEnabled, + const QString& ntpUtility ) +{ + int ret = 0; + + // write to the system config file + QFile config_file(KDE_CONFDIR "/kcmclockrc"); + if(!config_file.exists()) { + config_file.open(QIODevice::WriteOnly); + config_file.close(); + config_file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::ReadOther); + } + KConfig _config(config_file.fileName(), KConfig::SimpleConfig); + KConfigGroup config(&_config, "NTP"); + config.writeEntry("servers", ntpServers ); + config.writeEntry("enabled", ntpEnabled ); + + if ( ntpEnabled && !ntpUtility.isEmpty() ) { + // NTP Time setting + QString timeServer = ntpServers.first(); + if( timeServer.indexOf( QRegExp(".*\\(.*\\)$") ) != -1 ) { + timeServer.replace( QRegExp(".*\\("), "" ); + timeServer.replace( QRegExp("\\).*"), "" ); + // Would this be better?: s/^.*\(([^)]*)\).*$/\1/ + } + + KProcess proc; + proc << ntpUtility << timeServer; + if ( proc.execute() != 0 ) { + ret |= NTPError; + } else { + toHwclock(); + } + } else if( ntpEnabled ) { + ret |= NTPError; + } + + return ret; +} + +int ClockHelper::date( const QString& newdate, const QString& olddate ) +{ + struct timeval tv; + + tv.tv_sec = newdate.toULong() - olddate.toULong() + time(0); + tv.tv_usec = 0; + if (settimeofday(&tv, 0)) { + return DateError; + } + + toHwclock(); + return 0; +} + +// on non-Solaris systems which do not use /etc/timezone? +int ClockHelper::tz( const QString& selectedzone ) +{ + int ret = 0; +#if defined(USE_SOLARIS) // MARCO + + KTemporaryFile tf; + tf.setPrefix("kde-tzone"); + tf.open(); + QTextStream ts(&tf); + + QFile fTimezoneFile(INITFILE); + bool updatedFile = false; + + if (fTimezoneFile.open(QIODevice::ReadOnly)) + { + bool found = false; + + QTextStream is(&fTimezoneFile); + + for (QString line = is.readLine(); !line.isNull(); + line = is.readLine()) + { + if (line.find("TZ=") == 0) + { + ts << "TZ=" << selectedzone << endl; + found = true; + } + else + { + ts << line << endl; + } + } + + if (!found) + { + ts << "TZ=" << selectedzone << endl; + } + + updatedFile = true; + fTimezoneFile.close(); + } + + if (updatedFile) + { + ts.device()->reset(); + fTimezoneFile.remove(); + + if (fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) + { + QTextStream os(&fTimezoneFile); + + for (QString line = ts->readLine(); !line.isNull(); + line = ts->readLine()) + { + os << line << endl; + } + + fchmod(fTimezoneFile.handle(), + S_IXUSR | S_IRUSR | S_IRGRP | S_IXGRP | + S_IROTH | S_IXOTH); + fTimezoneFile.close(); + } + } + + + QString val = selectedzone; +#else + QString tz = "/usr/share/zoneinfo/" + selectedzone; + + QString zic = KStandardDirs::findExe("zic", exePath); + if (!zic.isEmpty()) { + KProcess::execute(zic, QStringList() << "-l" << selectedzone); + } else if (!QFile::remove("/etc/localtime")) { + ret |= TimezoneError; + } else if (!QFile::copy(tz, "/etc/localtime")) { + ret |= TimezoneError; + } + + QFile fTimezoneFile("/etc/timezone"); + + if (fTimezoneFile.exists() && fTimezoneFile.open(QIODevice::WriteOnly | QIODevice::Truncate) ) { + QTextStream t(&fTimezoneFile); + t << selectedzone; + fTimezoneFile.close(); + } + + QString val = ':' + tz; +#endif // !USE_SOLARIS + + setenv("TZ", val.toAscii(), 1); + tzset(); + + return ret; +} + +int ClockHelper::tzreset() +{ +#if !defined(USE_SOLARIS) // Do not update the System! + unlink( "/etc/timezone" ); + unlink( "/etc/localtime" ); + + setenv("TZ", "", 1); + tzset(); +#endif // !USE SOLARIS + return 0; +} + +void ClockHelper::toHwclock() +{ + QString hwclock = KStandardDirs::findExe("hwclock", exePath); + if (!hwclock.isEmpty()) { + KProcess::execute(hwclock, QStringList() << "--systohc"); + } +} + +ActionReply ClockHelper::save(const QVariantMap &args) +{ + bool _ntp = args.value("ntp").toBool(); + bool _date = args.value("date").toBool(); + bool _tz = args.value("tz").toBool(); + bool _tzreset = args.value("tzreset").toBool(); + + KComponentData data( "kcmdatetimehelper" ); + + int ret = 0; // error code +// The order here is important + if( _ntp ) + ret |= ntp( args.value("ntpServers").toStringList(), args.value("ntpEnabled").toBool(), args.value("ntpUtility").toString() ); + if( _date ) + ret |= date( args.value("newdate").toString(), args.value("olddate").toString() ); + if( _tz ) + ret |= tz( args.value("tzone").toString() ); + if( _tzreset ) + ret |= tzreset(); + + if (ret == 0) { + return ActionReply::SuccessReply(); + } else { + ActionReply reply(ActionReply::HelperErrorReply()); + reply.setErrorCode(static_cast(ret)); + return reply; + } +} + +KAUTH_HELPER_MAIN("org.kde.kcontrol.kcmclock", ClockHelper) diff --git a/kcms/dateandtime/helper.h b/kcms/dateandtime/helper.h new file mode 100644 index 0000000000..2b75805d72 --- /dev/null +++ b/kcms/dateandtime/helper.h @@ -0,0 +1,54 @@ +/* + * main.h + * + * Copyright (C) 1998 Luca Montecchiani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 CLOCK_HELPER_H +#define CLOCK_HELPER_H + +#include + +using namespace KAuth; + +class ClockHelper : public QObject +{ + Q_OBJECT + + public: + enum + { + CallError = 1 << 0, + TimezoneError = 1 << 1, + NTPError = 1 << 2, + DateError = 1 << 3 + }; + + public Q_SLOTS: + ActionReply save(const QVariantMap &map); + + private: + int ntp(const QStringList& ntpServers, bool ntpEnabled, + const QString& ntpUtility); + int date(const QString& newdate, const QString& olddate); + int tz(const QString& selectedzone); + int tzreset(); + + void toHwclock(); +}; + +#endif // CLOCK_HELPER_H diff --git a/kcms/dateandtime/kcmclock_actions.actions b/kcms/dateandtime/kcmclock_actions.actions new file mode 100644 index 0000000000..14b4433bb8 --- /dev/null +++ b/kcms/dateandtime/kcmclock_actions.actions @@ -0,0 +1,209 @@ +[Domain] +Name=Date and Time Control Module +Name[ar]=وحدة التحكم بالتاريخ والوقت +Name[ast]=Módulu de control de data y hora +Name[bg]=Управление на дата и час +Name[bn]=তারিখ এবং সময় নিয়ন্ত্রণ মডিউল +Name[bs]=Kontrolni modul datuma i vremena +Name[ca]=Mòdul de control de data i hora +Name[ca@valencia]=Mòdul de control de data i hora +Name[cs]=Ovládací modul data a času +Name[csb]=Mòduł kòntrolë datuma ë czasu +Name[da]=Kontrolmodul til dato og tid +Name[de]=Kontrollmodul für Datum und Zeit +Name[el]=Μονάδα ελέγχου ημερομηνίας και ώρας +Name[en_GB]=Date and Time Control Module +Name[eo]=Kontrol-Modulo de Dato kaj Tempo +Name[es]=Módulo de control de fecha y hora +Name[et]=Kuupäeva ja kellaaja juhtimismoodul +Name[eu]=Data eta ordua kontrolatzeko modulua +Name[fi]=Aika-asetukset +Name[fr]=Module de contrôle de la date et de l'heure +Name[fy]=Datum en tiid kontrôle module +Name[ga]=Modúl Rialaithe Dáta agus Am +Name[gl]=Módulo de control da data e hora +Name[gu]=તારીખ અને સમય નિયંત્રણ મોડ્યુલ +Name[he]=מודול הגדרות תאריך ושעה +Name[hi]=तारीख़ और समय तंत्र मोड्यूल +Name[hr]=Upravljački modul za datum i vrijeme +Name[hu]=Dátum és idő beállítómodul +Name[ia]=Modulo de controlo de data e tempore +Name[id]=Modul Kontrol Tanggal dan Waktu +Name[is]=Stjórneining fyrir dagsetningu og tíma +Name[it]=Modulo di controllo di data e ora +Name[ja]=日付と時刻の設定モジュール +Name[kk]=Күні мен уақытын басқару модулі +Name[km]=ម៉ូឌុល​ត្រួតពិនិត្យ​ពេលវេលា និងកាលបរិច្ឆេទ +Name[kn]=ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ನಿಯಂತ್ರಣ ಘಟಕ +Name[ko]=날짜와 시간 제어 모듈 +Name[lt]=Datos ir laiko valdymo modulis +Name[lv]=Datuma un laika kontroles modulis +Name[mk]=Контролен модул за датум и време +Name[ml]=തീയതിയും സമയവും നിയന്ത്രിയ്ക്കുന്ന ഭാഗം +Name[mr]=दिनांक व वेळ नियंत्रण विभाग +Name[nb]=Styremodul for dato og tid +Name[nds]=Datum- un Tiet-Kuntrullmoduul +Name[nl]=Controlemodule van datum en tijd +Name[nn]=Kontrollmodul for dato og klokkeslett +Name[pa]=ਮਿਤੀ ਅਤੇ ਟਾਈਮ ਕੰਟਰੋਲ ਮੋਡੀਊਲ +Name[pl]=Moduł sterowania datą i czasem +Name[pt]=Módulo de Controlo da Data e Hora +Name[pt_BR]=Módulo de controle da data e hora +Name[ro]=Modul de control dată și oră +Name[ru]=Модуль настройки даты и времени +Name[si]=දිනය සහ වේලා පාලක මොඩියුලය +Name[sk]=Modul pre nastavenie dátumu a času +Name[sl]=Nadzorni modul za datum in čas +Name[sr]=Контролни модул датума и времена +Name[sr@ijekavian]=Контролни модул датума и времена +Name[sr@ijekavianlatin]=Kontrolni modul datuma i vremena +Name[sr@latin]=Kontrolni modul datuma i vremena +Name[sv]=Inställningsmodul för datum och tid +Name[tg]=Сана ва вақт +Name[th]=มอดูลควบคุมสำหรับวันและเวลา +Name[tr]=Tarih ve Saat Denetim Modülü +Name[ug]=چېسلا ۋە ۋاقىت تىزگىن بۆلىكى +Name[uk]=Модуль керування датою і часом +Name[vi]=Mô-đun điều khiển ngày giờ +Name[wa]=Module di controle del date eyet d' l' eure +Name[x-test]=xxDate and Time Control Modulexx +Name[zh_CN]=日期和时间控制模块 +Name[zh_TW]=日期與時間控制模組 +Icon=preferences-system-time + +[org.kde.kcontrol.kcmclock.save] +Name=Save the date/time settings +Name[ar]=احفظ إعدادات التاريخ والوقت +Name[ast]=Guardar les preferencies de data/hora +Name[bg]=Запазване настройките за дата и час +Name[bn]=তারিখ এবং সময় সেটিংস সংরক্ষণ করো +Name[bs]=Sačuvaj postavke datuma i vremena +Name[ca]=Desa la configuració de data i hora +Name[ca@valencia]=Guarda la configuració de data i hora +Name[cs]=Uložit nastavení data a času +Name[csb]=Zapiszë nastôw datuma ë czasu +Name[da]=Gem dato- og tidsindstillinger +Name[de]=Einstellungen für Datum und Zeit speichern +Name[el]=Αποθήκευση ρυθμίσεων ημερομηνίας και ώρας +Name[en_GB]=Save the date/time settings +Name[eo]=Konservu Agordon de dato kaj tempo +Name[es]=Guardar las preferencias de fecha/hora +Name[et]=Kuupäeva ja kellaaja seadistuste salvestamine +Name[eu]=Gorde data- eta ordu-ezarpenak +Name[fi]=Tallenna päiväyksen ja ajan asetukset +Name[fr]=Enregistrer les paramètres de date et d'heure +Name[fy]=Datum en tiid ynstellings bewarje +Name[ga]=Sábháil na socruithe dáta/ama +Name[gl]=Garda a configuración da data e hora +Name[gu]=તારીખ/સમય ગોઠવણીઓ સંગ્રહો +Name[he]=שמירת הגדרות התאריך והשעה +Name[hi]=तारीख़ तथा समय विन्यास सहेजें +Name[hr]=Spremi datumske/vremenske postavke +Name[hu]=A dátum- és időbeállítások mentése +Name[ia]=Salveguarda le preferentias de data & tempore +Name[id]=Simpan pengaturan tanggal/waktu +Name[is]=Vista stillingar dagssetningar og tíma +Name[it]=Salva le impostazioni di data e ora +Name[ja]=日付と時刻の設定を保存 +Name[kk]=Күн/уақыт параметрлерін сақтау +Name[km]=រក្សាទុកការកំណត់​ពេលវេលា/កាលបរិច្ឆេទ +Name[kn]=ದಿನಾಂಕ/ಸಮಯ ಸಂಯೋಜನೆಗಳನ್ನು ಉಳಿಸಿ +Name[ko]=날짜와 시간 설정 저장 +Name[lt]=Duomenų ir laiko nustatymai +Name[lv]=Saglabāt datuma/laika iestatījumus +Name[mk]=Зачувување на поставувања за датум и време +Name[ml]=തീയതിയുടെ/സമയത്തിന്റെ സജ്ജീകരണങ്ങള്‍ സൂക്ഷിയ്ക്കുക +Name[mr]=दिनांक व वेळ संयोजना साठवा +Name[nb]=Lagre dato og klokkeslett-innstillinger +Name[nds]=Instellen vun Datum un Tiet sekern +Name[nl]=Datum- en tijdinstellingen opslaan +Name[nn]=Lagra innstillingane for dato og klokkeslett +Name[pa]=ਮਿਤੀ/ਸਮਾਂ ਸੈਟਿੰਗ ਸੰਭਾਲੋ +Name[pl]=Zapisz ustawienia daty/czasu +Name[pt]=Mudar a configuração da data/hora +Name[pt_BR]=Salvar as configurações de data e hora +Name[ro]=Salvează configurările datei și orei +Name[ru]=Сохранить параметры даты и времени +Name[si]=දිනය/වේලාව සිටුවම් සුරකින්න +Name[sk]=Uložiť nastavenia dátumu a času +Name[sl]=Shranjevanje nastavitev datuma in časa +Name[sr]=Сачувај поставке датума и времена +Name[sr@ijekavian]=Сачувај поставке датума и времена +Name[sr@ijekavianlatin]=Sačuvaj postavke datuma i vremena +Name[sr@latin]=Sačuvaj postavke datuma i vremena +Name[sv]=Spara inställningar av datum och tid +Name[tg]=Танзимоти сана ва вақт +Name[th]=จัดเก็บการตั้งค่าวันและเวลา +Name[tr]=Tarih ve saat ayarlarını kaydet +Name[ug]=چېسلا/ۋاقىت تەڭشىكىنى ساقلايدۇ +Name[uk]=Зберегти параметри дати/часу +Name[wa]=Schaper ls apontiaedjes del date et d' l' eure +Name[x-test]=xxSave the date/time settingsxx +Name[zh_CN]=保存日期和时间设置 +Name[zh_TW]=儲存日期和時間設定值 +Description=System policies prevent you from saving the date/time settings. +Description[ar]=إن سياسات النظام لا تسمح لك بحفظ إعدادات الوقت والتاريخ +Description[ast]=Les polítiques del sistema impiden guardar les preferencies de data/hora. +Description[bg]=Системните правила не позволяват запазване на настройките за дата и час. +Description[bn]=সিস্টেম পলিসি আপনাকে তারিখ এবং সময় সেটিংস সংরক্ষণ করতে দিচ্ছে না। +Description[bs]=Sistemske smjernice sprečavaju upisivanje postavki datuma i vremena. +Description[ca]=Les polítiques del sistema impedeixen que deseu la configuració de data i hora. +Description[ca@valencia]=Les polítiques del sistema impedeixen que guardeu la configuració de data i hora. +Description[cs]=Nastavení systému vám znemožňuje uložit datum/čas. +Description[csb]=Przez systemòwi nastôw nié mòżé zapisac nastôwù datuma ë czasu. +Description[da]=Systempolitikker forhindrer dig i at gemme dato- og tidsindstillinger. +Description[de]=Die Einstellungen für Datum und Zeit können aufgrund einer Systemrichtlinie nicht gespeichert werden. +Description[el]=Οι πολιτικές του συστήματος αποτρέπουν την αποθήκευση των ρυθμίσεων ώρας/ημερομηνίας. +Description[en_GB]=System policies prevent you from saving the date/time settings. +Description[es]=Las políticas del sistema le impiden guardar las preferencias de fecha/hora. +Description[et]=Süsteemi reeglid takistavad kuupäeva ja kellaaja seadistuste salvestamist. +Description[eu]=Sistemako gidalerroek data- eta ordu-ezarpenak gordetzea eragozten dizute +Description[fi]=Järjestelmämenettelytavat estävät sinua tallentamasta päivämäärä/aika-asetuksia. +Description[fr]=La stratégie système vous empêche d'enregistrer les paramètres de date et d'heure. +Description[fy]=Systeem belied foarkomt dat jo datum en tiid ynstellings bewarje kinne. +Description[ga]=De bharr polasaí an chórais, níl cead agat socruithe an dáta/ama a shábháil. +Description[gl]=As políticas do sistema non permiten que garde a configuración da data e hora. +Description[he]=מדיניות המערכת מונעת ממך שמירת הגדרות התאריך והשעה. +Description[hr]=Pravila sustava vam brane spremanje datumskih/vremenskih postavki. +Description[hu]=A rendszer házirendjei nem engedik Önnek a dátum- és időbeállítások mentését. +Description[ia]=Le politicas de systema preveni te ex salveguardar le preferentias de tempore/data. +Description[id]=Kebijakan sistem menghalangi anda untuk menyimpan pengaturan tanggal/waktu. +Description[is]=Öryggisstillingar kerfisins koma í veg fyrir að þú getir vistað tíma/dagsetningu. +Description[it]=Le regole di condotta del sistema impediscono di salvare le impostazioni di data e ora. +Description[ja]=システムポリシーにより、日時設定を保存することができません。 +Description[kk]=Күн/уақыт параметрлерін сақтауды болдырмайтын жүйелік ережелері. +Description[km]=គោលនយោបាយ​ប្រព័ន្ធ​ ការពារ​អ្នក​​មិន​ឲ្យ​រក្សាទុក​ការកំណត់​កាលបរិច្ឆេទ/ពេលវេលា ។ +Description[kn]=ವ್ಯವಸ್ಥೆಯ ಕಾರ್ಯನೀತಿ ನಿಮ್ಮನ್ನು ಸಮಯ/ದಿನಾಂಕ ಸಂಯೋಜನೆಗಳನ್ನು ಉಳಿಸಿಕೊಳ್ಳುವುದರಿಂದ ತಡೆಯುತ್ತಿವೆ +Description[ko]=시스템 정책 때문에 날짜와 시간 설정을 저장할 수 없습니다. +Description[lt]=Sistemos taisyklės neleidžia jums įrašyti datos/laiko. +Description[lv]=Sistēmas politikas neļauj jums saglabāt datuma/laika iestatījumus. +Description[mk]=Политиката на системот Ве спречува да ги зачувате поставувањата за датум и време. +Description[ml]=സിസ്റ്റത്തിലെ നയങ്ങള്‍ തിയ്യതി/സമയം ക്രമീകരിയ്ക്കുന്നതില്‍ നിന്നും നിങ്ങളെ തടയുന്നു. +Description[mr]=प्रणाली धोरण दिनांक व वेळ संयोजना संचयीत करण्यास प्रतिबंध करत आहे. +Description[nb]=Systembestemmelser gjør at du ikke kan lagre dato/tid-innstillingene +Description[nds]=De Systeemregeln verlöövt nich, dat Du de Instellen för Datum un Tiet sekerst. +Description[nl]=Systeembeleid voorkwam dat u de datum- en tijdinstellingen kon opslaan. +Description[nn]=Systemreglane hindrar deg i å lagra innstillingane for dato og klokkeslett. +Description[pa]=ਸਿਸਟਮ ਪਾਲਸੀ ਤੁਹਾਨੂੰ ਮਿਤੀ/ਸਮਾਂ ਸੈਟਿੰਗ ਬਦਲਣ ਤੋਂ ਤੁਹਾਨੂੰ ਰੋਕਦੀ ਹੈ। +Description[pl]=Polityka systemu nie pozwala ci na zapisanie ustawień daty/czasu. +Description[pt]=As políticas do sistema proíbem a modificação da configuração de data/hora. +Description[pt_BR]=As políticas do sistema não permitem a modificação das configurações de data e hora. +Description[ro]=Politicile sistemului vă interzic salvarea configurărilor de dată și oră. +Description[ru]=Правила безопасности запрещают вам управлять системной датой и временем. +Description[si]=පද්ධති ප්‍රතිපත්තො ඔබව දිනය/වේලාව සැකසුම් සුරැකිම වලකාලයි. +Description[sk]=Systémové politiky vám zabránili uložiť nastavenie dátumu a času. +Description[sl]=Sistemski pravilniki vam onemogočajo, da bi shranili nastavitve datuma in časa. +Description[sr]=Системске смернице спречавају уписивање поставки датума и времена. +Description[sr@ijekavian]=Системске смјернице спречавају уписивање поставки датума и времена. +Description[sr@ijekavianlatin]=Sistemske smjernice sprečavaju upisivanje postavki datuma i vremena. +Description[sr@latin]=Sistemske smernice sprečavaju upisivanje postavki datuma i vremena. +Description[sv]=Systemets policy förhindrar att du sparar inställningar av datum och tid. +Description[th]=นโยบายของระบบเพื่อป้องกันจากการจัดเก็บการตั้งค่าต่าง ๆ ของวันและเวลา +Description[tr]=Sistem politikaları tarih saat ayarlarını kaydetmenizi engelliyor. +Description[ug]=سىستېما بىخەتەرلىك تەدبىرىڭىز چېسلا/ۋاقىت تەڭشەكلەرنى ساقلاشقا يول قويمايدۇ. +Description[uk]=Відповідно до загальносистемних правил, ви не можете зберігати параметри дати/часу. +Description[wa]=Les politikes do sistinme vos espaitchèt d' schaper les apontiaedjes del date/eure. +Description[x-test]=xxSystem policies prevent you from saving the date/time settings.xx +Description[zh_CN]=系统安全策略不允许您保存日期/时间设置。 +Description[zh_TW]=系統政策不允許您儲存日期與時間的設定 +Policy=auth_admin diff --git a/kcms/dateandtime/main.cpp b/kcms/dateandtime/main.cpp new file mode 100644 index 0000000000..bf2d96ada8 --- /dev/null +++ b/kcms/dateandtime/main.cpp @@ -0,0 +1,117 @@ +/* + * main.cpp + * + * Copyright (C) 1998 Luca Montecchiani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "main.h" + +#include + +//Added by qt3to4: +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dtime.h" +#include "helper.h" + +#include +#include + +K_PLUGIN_FACTORY(KlockModuleFactory, registerPlugin();) +K_EXPORT_PLUGIN(KlockModuleFactory("kcmkclock")) + + +KclockModule::KclockModule(QWidget *parent, const QVariantList &) + : KCModule(parent/*, name*/) +{ + KAboutData *about = + new KAboutData(I18N_NOOP("kcmclock"), QString(), i18n("KDE Clock Control Module"), + QString(), QString(), KAboutData::License_GPL, + i18n("(c) 1996 - 2001 Luca Montecchiani")); + + about->addAuthor(i18n("Luca Montecchiani"), i18n("Original author"), QStringLiteral("m.luca@usa.net")); + about->addAuthor(i18n("Paul Campbell"), i18n("Current Maintainer"), QStringLiteral("paul@taniwha.com")); + about->addAuthor(i18n("Benjamin Meyer"), i18n("Added NTP support"), QStringLiteral("ben+kcmclock@meyerhome.net")); + setAboutData( about ); + setQuickHelp( i18n("

    Date & Time

    This control module can be used to set the system date and" + " time. As these settings do not only affect you as a user, but rather the whole system, you" + " can only change these settings when you start the System Settings as root. If you do not have" + " the root password, but feel the system time should be corrected, please contact your system" + " administrator.")); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(KDialog::spacingHint()); + + dtime = new Dtime(this); + layout->addWidget(dtime); + connect(dtime, SIGNAL(timeChanged(bool)), this, SIGNAL(changed(bool))); + + setButtons(Help|Apply); + + setNeedsAuthorization(true); + + process = NULL; +} + +void KclockModule::save() +{ + setDisabled(true); + + QVariantMap helperargs; + dtime->save( helperargs ); + + Action action = authAction(); + action.setArguments(helperargs); + + ExecuteJob *job = action.execute(); + + if (!job->exec()) { + KMessageBox::error(this, i18n("Unable to authenticate/execute the action: %1, %2", job->error(), job->errorString())); + } + else { + QDBusMessage msg = QDBusMessage::createSignal("/org/kde/kcmshell_clock", "org.kde.kcmshell_clock", "clockUpdated"); + QDBusConnection::sessionBus().send(msg); + } + + // NOTE: super nasty hack #1 + // Try to work around time mismatch between KSystemTimeZones' update of local + // timezone and reloading of data, so that the new timezone is taken into account. + // The Ultimate solution to this would be if KSTZ emitted a signal when a new + // local timezone was found. + QTimer::singleShot(5000, this, SLOT(load())); + + // setDisabled(false) happens in load(), since QTimer::singleShot is non-blocking +} + +void KclockModule::load() +{ + dtime->load(); + setDisabled(false); +} + +#include "main.moc" diff --git a/kcms/dateandtime/main.h b/kcms/dateandtime/main.h new file mode 100644 index 0000000000..c1e5234091 --- /dev/null +++ b/kcms/dateandtime/main.h @@ -0,0 +1,47 @@ +/* + * main.h + * + * Copyright (C) 1998 Luca Montecchiani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 main_included +#define main_included + +#include + +class Dtime; +class QTabWidget; +class KProcess; + + +class KclockModule : public KCModule +{ + Q_OBJECT + +public: + KclockModule(QWidget *parent, const QVariantList &); + + void save(); + void load(); + +private: + QTabWidget *tab; + Dtime *dtime; + KProcess *process; +}; + +#endif // main_included diff --git a/kcms/desktoppaths/CMakeLists.txt b/kcms/desktoppaths/CMakeLists.txt new file mode 100644 index 0000000000..4076f68959 --- /dev/null +++ b/kcms/desktoppaths/CMakeLists.txt @@ -0,0 +1,17 @@ +set(kcm_desktoppaths_PART_SRCS + globalpaths.cpp +) + +add_library(kcm_desktoppaths MODULE ${kcm_desktoppaths_PART_SRCS}) + +target_link_libraries(kcm_desktoppaths + KF5::KCMUtils + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::KDE4Support +) + +install(TARGETS kcm_desktoppaths DESTINATION ${PLUGIN_INSTALL_DIR}) +install(FILES desktoppath.desktop DESTINATION ${SERVICES_INSTALL_DIR}) + diff --git a/kcms/desktoppaths/Messages.sh b/kcms/desktoppaths/Messages.sh new file mode 100644 index 0000000000..fe3c1740c6 --- /dev/null +++ b/kcms/desktoppaths/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kcm_desktoppaths.pot diff --git a/kcms/desktoppaths/desktoppath.desktop b/kcms/desktoppaths/desktoppath.desktop new file mode 100644 index 0000000000..c3ef14c3fc --- /dev/null +++ b/kcms/desktoppaths/desktoppath.desktop @@ -0,0 +1,237 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/paths/index.html +Icon=system-file-manager +Exec=kcmshell5 desktoppath + +X-KDE-Library=kcm_desktoppaths +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=account-details +X-KDE-Weight=60 + +Name=Paths +Name[af]=Soekgidse +Name[ar]=المسارات +Name[as]=পথ +Name[ast]=Caminos +Name[be]=Шляхі +Name[be@latin]=Ściežki +Name[bg]=Пътища +Name[bn]=পাথ (Paths) +Name[bn_IN]=পাথ +Name[br]=Hentoù +Name[bs]=Putanje +Name[ca]=Camins +Name[ca@valencia]=Camins +Name[cs]=Cesty +Name[csb]=Stegnë +Name[cy]=Llwybrau +Name[da]=Stier +Name[de]=Pfade +Name[el]=Κατάλογοι +Name[en_GB]=Paths +Name[eo]=Vojoj +Name[es]=Rutas +Name[et]=Otsinguteed +Name[eu]=Bide-izenak +Name[fa]=مسیرها +Name[fi]=Polut +Name[fr]=Emplacements +Name[fy]=Paden +Name[ga]=Conairí +Name[gl]=Rutas +Name[gu]=માર્ગો +Name[he]=נתיבים +Name[hi]=पथ +Name[hne]=पथ +Name[hr]=Putanje +Name[hsb]=Puće +Name[hu]=Elérési utak +Name[ia]=Percursos +Name[id]=Alamat +Name[is]=Slóðir +Name[it]=Percorsi +Name[ja]=パス +Name[ka]=ბილიკი +Name[kk]=Жолдар +Name[km]=ផ្លូវ +Name[kn]=ಪಥಗಳು (ಪಾತ್) +Name[ko]=경로 +Name[ku]=Rêç +Name[lt]=Keliai +Name[lv]=Ceļi +Name[mai]=पथ +Name[mk]=Патеки +Name[ml]=വഴികള്‍ +Name[mr]=मार्ग +Name[ms]=Laluan +Name[nb]=Stier +Name[nds]=Padden +Name[ne]=मार्ग +Name[nl]=Paden +Name[nn]=Stiar +Name[oc]=Camins +Name[or]=ପଥଗୁଡ଼ିକ +Name[pa]=ਮਾਰਗ +Name[pl]=Ścieżki +Name[pt]=Localizações +Name[pt_BR]=Caminhos +Name[ro]=Căi +Name[ru]=Пути +Name[se]=Bálgát +Name[si]=මාර්‍ග +Name[sk]=Cesty +Name[sl]=Poti +Name[sr]=Путање +Name[sr@ijekavian]=Путање +Name[sr@ijekavianlatin]=Putanje +Name[sr@latin]=Putanje +Name[sv]=Sökvägar +Name[ta]=பாதைகள் +Name[te]=దారులు +Name[tg]=Роҳчаҳо +Name[th]=พาธ +Name[tr]=Yollar +Name[ug]=يول +Name[uk]=Шляхи +Name[uz]=Yoʻllar +Name[uz@cyrillic]=Йўллар +Name[vi]=Đường dẫn +Name[wa]=Tchimins +Name[xh]=Umendo +Name[x-test]=xxPathsxx +Name[zh_CN]=路径 +Name[zh_TW]=路徑 + +Comment=Change the location important files are stored +Comment[af]=Verander die ligging belangrik lêers word gestoor +Comment[ar]=غيّر المكان المُستخدم لتخزين الملفات المهمة +Comment[as]=গুৰুত্বপূৰ্ণ নথিপত্ৰ সংৰক্ষণ কৰাৰ স্থান সলনি কৰক +Comment[ast]=Camudar l'allugamientu de ficheros importantes +Comment[be]=Змена тэчак для захавання важных файлаў +Comment[be@latin]=Źmiani miescy, dzie zachoŭvajucca važnyja fajły +Comment[bg]=Настройване местоположението на важните файлове +Comment[bn]=বিভিন্ন গুরুত্বপূর্ণ ফাইল কোন অবস্থানে থাকবে তা পরিবর্তন করুন +Comment[bn_IN]=গুরুত্বপূর্ণ ফাইল সংরক্ষণের স্থান পরিবর্তন করুন +Comment[bs]=Promijenite lokaciju gdje su smješteni važni datoteke +Comment[ca]=Canvia la localització d'on seran desats els fitxers importants +Comment[ca@valencia]=Canvia la localització d'on seran guardats els fitxers importants +Comment[cs]=Změna umístění důležitých souborů +Comment[csb]=Môl trzëmaniô wôżnëch lopków +Comment[cy]=Newid lle mae ffeiliau pwysig yn cael eu cadw +Comment[da]=Ændr stedet hvor vigtige filer gemmes +Comment[de]=Ordner für wichtige Dateien ändern +Comment[el]=Αλλάξτε την τοποθεσία στην οποία αποθηκεύονται σημαντικά αρχεία +Comment[en_GB]=Change the location important files are stored +Comment[eo]=Ŝanĝi la lokon, kie oni konservas gravajn dosierojn +Comment[es]=Cambiar la ubicación de archivos importantes +Comment[et]=Oluliste failide asukoha muutmine +Comment[eu]=Aldatu fitxategi garrantzitsuak gordetzen diren kokalekua +Comment[fa]=تغییر محل ذخیره پرونده‌های مهم +Comment[fi]=Tärkeiden tiedostojen tallennuspaikkojen asetukset +Comment[fr]=Changer l'emplacement où les fichiers importants sont stockés +Comment[fy]=Hjir kinne jo de lokaasje fan it bewarjen fan belangrike triemmen wizigje +Comment[ga]=Athraigh an suíomh ina stóráiltear comhaid thábhachtacha +Comment[gl]=Cambia o lugar onde se gardan os ficheiros importantes +Comment[gu]=મહત્વની ફાઇલો સંગ્રહ થાય તે સ્થાન બદલો +Comment[he]=שינוי המיקומים בהם מאוחסנים קבצים חשובים +Comment[hi]=महत्वपूर्ण फ़ाइलों के रखने का स्थान बदलें +Comment[hne]=जरूरी फाइल मन के रखे के जगह बदलव +Comment[hr]=Promijenite lokaciju za smještaj važnih datoteka +Comment[hsb]=Městna změnić, hdźež so wažne dataje namakaja +Comment[hu]=Néhány fontosabb elérési utat lehet itt beállítani +Comment[ia]=Modifica le location ubi files importante es immagazinate +Comment[id]=Ubah lokasi berkas penting disimpan +Comment[is]=Breyta staðsetningu mikilvægra skráa +Comment[it]=Cambia il posto dove vengono salvati i file importanti +Comment[ja]=重要なファイルなどの保存場所を変更 +Comment[ka]=მნიშვნელოვანი ფაილბის გეზის ცვლილება შენახულია +Comment[kk]=Маңызды файлдар орналасатын орындарын өзгерту +Comment[km]=ផ្លាស់ប្ដូរ​​ទីតាំង​ដែល​ត្រូវ​ទុក​ឯកសារ​សំខាន់ៗ +Comment[kn]=ಮಖ್ಯ ಕಡತಗಳನ್ನು ಸಂಗ್ರಹಿಸಲಾಗುವ ಸ್ಥಳವನ್ನು ಬದಲಾಯಿಸು +Comment[ko]=중요한 파일이 저장되는 곳 설정 +Comment[ku]=Ciyê ku pelên girîng lê tomar dibin biguherîne +Comment[lt]=Pakeiskite svarbių failų saugojimo vietą +Comment[lv]=Mainīt nozīmīgu failu atrašanās vietas +Comment[mai]=महत्वपूर्ण फाइलसभ केर रखबाक स्थान बदलू +Comment[mk]=Сменете ја локацијата каде што се чуваат важни датотеки +Comment[ml]=പ്രധാനപ്പെട്ട ഫയലുകള്‍ സൂക്ഷിച്ച സ്ഥാനം മാറ്റുക +Comment[mr]=महत्वपूर्ण फाईल संयोजनाचे स्थान बदला +Comment[ms]=Ubah lokasi fail penting disimpan +Comment[nb]=Endre plasseringa av viktige filer +Comment[nds]=Den Oort för wichtige Dateien ännern +Comment[ne]=महत्वपूर्ण फाइल भण्डारण गरिएको स्थान परिवर्तन गर्नुहोस् +Comment[nl]=Hier kunt u de locatie voor het opslaan van belangrijke bestanden wijzigen +Comment[nn]=Endra plasseringa av viktige filer +Comment[or]=ଦରକାରି ଫାଇଲଗୁଡ଼ିକୁ ସଂରକ୍ଷିତ କରାଯାଇଥିବା ସ୍ଥାନକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ +Comment[pa]=ਜ਼ਰੂਰੀ ਫਾਇਲਾਂ ਸੰਭਾਲਣ ਲਈ ਟਿਕਾਣਾ ਤਬਦੀਲ +Comment[pl]=Zmiana miejsca przechowywania ważnych plików +Comment[pt]=Alterar as localizações onde os ficheiros importantes estão guardados +Comment[pt_BR]=Altera o local de armazenamento dos arquivos importantes +Comment[ro]=Modifică locul de stocare a fișierelor importante +Comment[ru]=Пути к важным файлам +Comment[se]=Rievdat báikkiid gosa dehálaš fiillat bidjut +Comment[si]=වැදගත් ගොනු ගබඩා කර ඇති ස්ථානය වෙනස් කරන්න +Comment[sk]=Zmena umiestnenia dôležitých súborov +Comment[sl]=Spremenite mesta shranjevanja pomembnih datotek +Comment[sr]=Промените локацију где су смештени важни фајлови +Comment[sr@ijekavian]=Промијените локацију гдје су смјештени важни фајлови +Comment[sr@ijekavianlatin]=Promijenite lokaciju gdje su smješteni važni fajlovi +Comment[sr@latin]=Promenite lokaciju gde su smešteni važni fajlovi +Comment[sv]=Ändra plats för lagring av viktiga filer +Comment[ta]=முக்கிய கோப்புகள் சேகரிக்கப்பட்டுள்ள இடத்தை மாற்று +Comment[te]=ముఖ్యమైన దస్త్రములు నిల్వవుంచు స్థానమును మార్చుము +Comment[tg]=Ҷойгиршавии файлҳои лозимӣ +Comment[th]=เปลี่ยนตำแหน่งที่เก็บแฟ้มที่สำคัญต่าง ๆ +Comment[tr]=Önemli dosyaların kaydedildiği yerleri düzenle +Comment[ug]=مۇھىم ھۆججەت ساقلايدىغان ئورۇننى ئۆزگەرت +Comment[uk]=Зміна адреси зберігання важливих файлів +Comment[uz]=Muhim fayllarning joylashgan joyini oʻzgartirish +Comment[uz@cyrillic]=Муҳим файлларнинг жойлашган жойини ўзгартириш +Comment[vi]=Thay đổi đường dẫn tới các tập tin quan trọng +Comment[wa]=Candjî l' eplaeçmint ki les fitchîs impôrtants sont wårdés +Comment[xh]=Tshintsha indawo apho zibekwa kona iifayile ezibalulekileyo +Comment[x-test]=xxChange the location important files are storedxx +Comment[zh_CN]=更改重要文件存储的位置 +Comment[zh_TW]=改變儲存重要檔案的位置 +X-KDE-Keywords=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures +X-KDE-Keywords[bs]=konqueror, delfin, datoteke, menadžer datoteka, put, putevi, desktop, upute, autostart, preuuzimanja, muzika, dokumenti, filmovi, slike +X-KDE-Keywords[ca]=konqueror,dolphin,fitxers,gestor de fitxers,camí,camins,escriptori,directoris,inici automàtic,baixades,música,documents,pel·lícules,imatges +X-KDE-Keywords[ca@valencia]=konqueror,dolphin,fitxers,gestor de fitxers,camí,camins,escriptori,directoris,inici automàtic,baixades,música,documents,pel·lícules,imatges +X-KDE-Keywords[da]=konqueror,dolphin,filhåndtering,stifinder,stier,skrivebord,mapper,autostart,downoad,hentninger,musik,dokumenter,film,billeder,filer,sti +X-KDE-Keywords[de]=Konqueror,Dolphin,Dateien,Dateimanager,Dateiverwaltung,Pfade,Arbeitsfläche,Verzeichnisse,Ordner,Autostart,Download,Herunterladen,Musik,Dokumente,Filme,Bilder +X-KDE-Keywords[el]=konqueror,dolphin,αρχεία,διαχειριστής αρχείων,διαδρομή, διαδρομές,επιφάνεια εργασίας,κατάλογοι,αυτόματη εκκίνηση,λήψεις,μουσική,έγγραφα,κινηματογραφία,εικόνες +X-KDE-Keywords[es]=konqueror,dolphin,archivos,gestor de archivos,ruta,rutas,escritorio,directorios,autoinicio,descargas,música,documentos,películas,imágenes +X-KDE-Keywords[et]=konqueror,dolphin,failid,failihaldur,asukohad,töölaud,kataloogid,autostart,allalaadimised,muusika,dokumendid,filmid,pildid +X-KDE-Keywords[eu]=konqueror,dolphin,fitxategi,fitxategi-kudeatzaile,bide-izen, bide-izenak,mahaigain,direktorio,hasi automatikoki,deskargak,musika,dokumentuak,filmak,irudiak +X-KDE-Keywords[fi]=konqueror,dolphin,tiedostot,tiedostonhallinta,polku,polut,työpöytä,hakemistot,kansiot,automaattikäynnistys,lataukset,musiikki,asiakirjat,elokuvat,kuvat +X-KDE-Keywords[fr]=konqueror, dolphin, fichiers, gestionnaire de fichiers, emplacement, emplacements, bureau, dossiers, démarrage automatique, téléchargements, musique, documents, films, images +X-KDE-Keywords[ga]=konqueror,dolphin,comhaid,bainisteoir comhad,conairí,cosáin,deasc,comhadlanna,tosú uathoibríoch,íosluchtuithe,ceol,cáipéisí,scannáin,pictiúir,grianghraif +X-KDE-Keywords[gl]=konqueror, dolphin, ficheiros, xestor de ficheiros, ruta, rutas, escritorio, cartafoles, inicio automático, descargas, música, documentos, películas, imaxes +X-KDE-Keywords[hu]=konqueror,dolphin,fájlok,fájlkezelő,elérési út, elérési utak,asztal,mappák, automatikus indítás,letöltések,zene,dokumentumok,filmek,képek +X-KDE-Keywords[ia]=konqueror,dolphin,files,gerente de file,percurso,percursos,scriptorio,directorios,autoinitio,discargamentos, musica,documentos,pelliculas,photos +X-KDE-Keywords[it]=konqueror,dolphin,file,gestore dei file,percorso,percorsi,desktop,cartelle,avvio automatico,scaricamenti,musica,documenti,film,immagini +X-KDE-Keywords[kk]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures +X-KDE-Keywords[km]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures +X-KDE-Keywords[ko]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,파일,파일 관리자,탐색기,디렉터리,다운로드,음악,문서,비디오,그림 +X-KDE-Keywords[mr]=कॉन्करर , डॉल्फीन, फाईल्स, फाईल मेनेजर, पाथस , डेस्कटॉप , डीरेक्टरिज , ऑटोस्टार्ट, डाउनलोडस,म्युझिक, डॉक्युमेंट, मूव्हीज, पिक्चर्स +X-KDE-Keywords[nb]=konqueror,dolphin,filer,filbehandler,sti,stier,skrivebord,mapper,autostart,nedlastinger,musikk,dokumenter,filmer,bilder +X-KDE-Keywords[nds]=Konqueror,Dolphin,Dateien,Dateipleger,Padden,Schriefdisch,Ornern,Vertekens,Autostart,Daalladen,Musik,Dokmenten,Filmen,Biller +X-KDE-Keywords[nl]=konqueror,dolphin,bestanden,bestandsbeheerder,pad,paden,bureaublad,mappen,autostart,downloads,muziek,documenten,films,afbeeldingen +X-KDE-Keywords[pl]=konqueror,dolphin,pliki,menadżer plików,ścieżka,ścieżki,pulpit,katalogi,auto-uruchamianie, pobierania,muzyka,dokumenty,filmy,zdjęcia,autostart +X-KDE-Keywords[pt]=konqueror,gestor de ficheiros,localizações,ecrã,pastas,arranque,transferências,música,documentos,filmes,imagens +X-KDE-Keywords[pt_BR]=konqueror,dolphin,arquivos,gerenciador de arquivos,localização,localizações,caminho,caminhos,área de trabalho,pastas,inicialização,downloads,música,documentos,filmes,imagens +X-KDE-Keywords[ru]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,файлы,диспетчер файлов,путь,местоположение,рабочий стол,директории,каталоги,папки,автозапуск,загрузки,музыка,документы,фильмы,видео,картинки +X-KDE-Keywords[sk]=konqueror,dolphin,súbory,správca súborov,cesta,cesty,plocha,adresáre,automatické spustenie,sťahovania,hudba,dokumenty,filmy,obrázky +X-KDE-Keywords[sl]=konqueror,dolphin,datoteke,upravljalnik datotek,datotečni upravljalnik,poti,namizje,mape,samodejni zagon,prejeto,prejemi,glasba,dokumenti,filmi,slike +X-KDE-Keywords[sr]=konqueror,dolphin,files,filemanager,path,paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,К‑освајач,Делфин,фајлови,менаџер фајлова,путање,путања,површ,фасцикле,самопокретање,преузимање,музика,документи,филмови,слике +X-KDE-Keywords[sr@ijekavian]=konqueror,dolphin,files,filemanager,path,paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,К‑освајач,Делфин,фајлови,менаџер фајлова,путање,путања,површ,фасцикле,самопокретање,преузимање,музика,документи,филмови,слике +X-KDE-Keywords[sr@ijekavianlatin]=konqueror,dolphin,files,filemanager,path,paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,K‑osvajač,Dolphin,fajlovi,menadžer fajlova,putanje,putanja,površ,fascikle,samopokretanje,preuzimanje,muzika,dokumenti,filmovi,slike +X-KDE-Keywords[sr@latin]=konqueror,dolphin,files,filemanager,path,paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,K‑osvajač,Dolphin,fajlovi,menadžer fajlova,putanje,putanja,površ,fascikle,samopokretanje,preuzimanje,muzika,dokumenti,filmovi,slike +X-KDE-Keywords[sv]=konqueror,dolphin,filer,filhanterare,sökväg,sökvägar,skrivbord,kataloger,automatisk start,nerladdningar,musik,dokument,filmer,bilder +X-KDE-Keywords[tr]=konqueror,dolphin,dosyalar,dosya yöneticisi,yol, yollar,masaüstü,dizinler,otomatik başlat,indirmeler,müzik,belgeler,filmler,resimler +X-KDE-Keywords[uk]=konqueror,dolphin,files,filemanager,paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,файл,дельфін,керування,менеджер,шляхи,стільниця,каталог,каталоги,автоматично,автоматичний,запуск,звантаження,завантаження,музика,документи,фільми,відео,зображення,знімки,фотографії +X-KDE-Keywords[x-test]=xxkonqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,picturesxx +X-KDE-Keywords[zh_CN]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures,文件,文件管理器,路径,桌面,目录,自动启动,下载,音乐,文档,电影,图片 +X-KDE-Keywords[zh_TW]=konqueror,dolphin,files,filemanager,path, paths,desktop,directories,autostart,downloads,music,documents,movies,pictures diff --git a/kcms/desktoppaths/globalpaths.cpp b/kcms/desktoppaths/globalpaths.cpp new file mode 100644 index 0000000000..5cfd3594e5 --- /dev/null +++ b/kcms/desktoppaths/globalpaths.cpp @@ -0,0 +1,455 @@ +/** + * Copyright (c) Martin R. Jones 1996 + * Copyright (c) Bernd Wuebben 1998 + * Copyright (c) Christian Tibirna 1998 + * Copyright 1998-2007 David Faure + * Copyright (c) 2010 Matthias Fuchs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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. + */ + +// +// +// "Desktop Options" Tab for KDesktop configuration +// +// (c) Martin R. Jones 1996 +// (c) Bernd Wuebben 1998 +// +// Layouts +// (c) Christian Tibirna 1998 +// Port to KControl, split from Misc Tab, Port to KControl2 +// (c) David Faure 1998 +// Desktop menus, paths +// (c) David Faure 2000 + + +// Own +#include "globalpaths.h" + +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +K_PLUGIN_FACTORY(KcmDesktopPathsFactory, registerPlugin();) + +//----------------------------------------------------------------------------- + +static QUrl desktopLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); +} + +static QUrl autostartLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/autostart")); +} + +static QUrl documentsLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); +} + +static QUrl downloadLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); +} + +static QUrl moviesLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); +} + +static QUrl picturesLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); +} + +static QUrl musicLocation() +{ + return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); +} + +DesktopPathConfig::DesktopPathConfig(QWidget *parent, const QVariantList &) + : KCModule( parent ) +{ + QFormLayout *lay = new QFormLayout(this); + lay->setVerticalSpacing(0); + lay->setMargin(0); + + setQuickHelp( i18n("

    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.")); + + urDesktop = addRow(lay, i18n("Desktop path:"), + i18n("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.")); + + urAutostart = addRow(lay, i18n("Autostart path:"), + i18n("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.")); + + urDocument = addRow(lay, i18n("Documents path:"), + i18n("This folder will be used by default to " + "load or save documents from or to.")); + + urDownload = addRow(lay, i18n("Downloads path:"), + i18n("This folder will be used by default to " + "save your downloaded items.")); + + urMovie = addRow(lay, i18n("Movies path:"), + i18n("This folder will be used by default to " + "load or save movies from or to.")); + + urPicture = addRow(lay, i18n("Pictures path:"), + i18n("This folder will be used by default to " + "load or save pictures from or to.")); + + urMusic = addRow(lay, i18n("Music path:"), + i18n("This folder will be used by default to " + "load or save music from or to.")); +} + +KUrlRequester* DesktopPathConfig::addRow(QFormLayout *lay, const QString& label, const QString& whatsThis) +{ + KUrlRequester* ur = new KUrlRequester(this); + ur->setMode(KFile::Directory | KFile::LocalOnly); + lay->addRow(label, ur); + connect(ur, SIGNAL(textChanged(QString)), this, SLOT(changed())); + lay->labelForField(ur)->setWhatsThis(whatsThis); + ur->setWhatsThis(whatsThis); + return ur; +} + +void DesktopPathConfig::load() +{ + // Desktop Paths + urDesktop->setUrl(desktopLocation()); + urAutostart->setUrl(autostartLocation()); + urDocument->setUrl(documentsLocation()); + urDownload->setUrl(downloadLocation()); + urMovie->setUrl(moviesLocation()); + urPicture->setUrl(picturesLocation()); + urMusic->setUrl(musicLocation()); + emit changed(false); +} + +void DesktopPathConfig::defaults() +{ + // Desktop Paths - keep defaults in sync with kglobalsettings.cpp + urDesktop->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Desktop"))); + urAutostart->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/.config/autostart"))); + urDocument->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Documents"))); + urDownload->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Downloads"))); + urMovie->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Movies"))); + urPicture->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Pictures"))); + urMusic->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Music"))); +} + +// the following method is copied from kdelibs/kdecore/config/kconfiggroup.cpp +static bool cleanHomeDirPath( QString &path, const QString &homeDir ) +{ +#ifdef Q_WS_WIN //safer + if (!QDir::convertSeparators(path).startsWith(QDir::convertSeparators(homeDir))) + return false; +#else + if (!path.startsWith(homeDir)) + return false; +#endif + + int len = homeDir.length(); + // replace by "$HOME" if possible + if (len && (path.length() == len || path[len] == '/')) { + path.replace(0, len, QString::fromLatin1("$HOME")); + return true; + } else + return false; +} + +// TODO this functionality is duplicated in libkonq - keep it only there and export + +static QString translatePath( QString path ) // krazy:exclude=passbyvalue +{ + // keep only one single '/' at the beginning - needed for cleanHomeDirPath() + while (path[0] == '/' && path[1] == '/') + path.remove(0,1); + + // we probably should escape any $ ` and \ characters that may occur in the path, but the Qt code that reads back + // the file doesn't unescape them so not much point in doing so + + // All of the 3 following functions to return the user's home directory + // can return different paths. We have to test all them. + const QString homeDir0 = QFile::decodeName(qgetenv("HOME")); + const QString homeDir1 = QDir::homePath(); + const QString homeDir2 = QDir(homeDir1).canonicalPath(); + if (cleanHomeDirPath(path, homeDir0) || + cleanHomeDirPath(path, homeDir1) || + cleanHomeDirPath(path, homeDir2) ) { + // kDebug() << "Path was replaced\n"; + } + + return path; +} + +void DesktopPathConfig::save() +{ + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup configGroup( config, "Paths" ); + + bool pathChanged = false; + bool autostartMoved = false; + + QUrl desktopURL(desktopLocation()); + + QUrl autostartURL(autostartLocation()); + QUrl newAutostartURL = urAutostart->url(); + + if ( !urDesktop->url().matches( desktopURL, QUrl::StripTrailingSlash ) ) + { + // Test which other paths were inside this one (as it is by default) + // and for each, test where it should go. + // * Inside destination -> let them be moved with the desktop (but adjust name if necessary) + // * Not inside destination -> move first + // !!! + kDebug() << "desktopURL=" << desktopURL; + QString urlDesktop = urDesktop->url().toLocalFile(); + if ( !urlDesktop.endsWith('/')) + urlDesktop+='/'; + + if ( desktopURL.isParentOf( autostartURL ) ) + { + kDebug() << "Autostart is on the desktop"; + + // Either the Autostart field wasn't changed (-> need to update it) + if ( newAutostartURL.matches(autostartURL, QUrl::StripTrailingSlash) ) + { + // Hack. It could be in a subdir inside desktop. Hmmm... Argl. + urAutostart->setUrl(QUrl::fromLocalFile(urlDesktop + QStringLiteral("Autostart/"))); + kDebug() << "Autostart is moved with the desktop"; + autostartMoved = true; + } + // or it has been changed (->need to move it from here) + else + { + QUrl futureAutostartURL = QUrl::fromLocalFile(urlDesktop + QStringLiteral("Autostart/")); + if ( newAutostartURL.matches( futureAutostartURL, QUrl::StripTrailingSlash ) ) + autostartMoved = true; + else + autostartMoved = moveDir( autostartLocation(), urAutostart->url(), i18n("Autostart") ); + } + } + + if ( moveDir( desktopLocation(), QUrl::fromLocalFile( urlDesktop ), i18n("Desktop") ) ) + { + //save in XDG path + const QString userDirsFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/user-dirs.dirs")); + KConfig xdgUserConf( userDirsFile, KConfig::SimpleConfig ); + KConfigGroup g( &xdgUserConf, "" ); + g.writeEntry( "XDG_DESKTOP_DIR", QString("\"" + translatePath( urlDesktop ) + "\"") ); + pathChanged = true; + } + } + + if ( !newAutostartURL.matches( autostartURL, QUrl::StripTrailingSlash ) ) + { + if (!autostartMoved) + autostartMoved = moveDir( autostartLocation(), urAutostart->url(), i18n("Autostart") ); + if (autostartMoved) + { + configGroup.writePathEntry( "Autostart", urAutostart->url().toLocalFile(), KConfigBase::Normal | KConfigBase::Global ); + pathChanged = true; + } + } + + config->sync(); + + if (xdgSavePath(urDocument, documentsLocation(), "XDG_DOCUMENTS_DIR", i18n("Documents"))) + pathChanged = true; + + if (xdgSavePath(urDownload, downloadLocation(), "XDG_DOWNLOAD_DIR", i18n("Downloads"))) + pathChanged = true; + + if (xdgSavePath(urMovie, moviesLocation(), "XDG_VIDEOS_DIR", i18n("Movies"))) + pathChanged = true; + + if (xdgSavePath(urPicture, picturesLocation(), "XDG_PICTURES_DIR", i18n("Pictures"))) + pathChanged = true; + + if (xdgSavePath(urMusic, musicLocation(), "XDG_MUSIC_DIR", i18n("Music"))) + pathChanged = true; + + if (pathChanged) { + kDebug() << "sending message SettingsChanged"; + KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_PATHS); + } +} + +bool DesktopPathConfig::xdgSavePath(KUrlRequester* ur, const QUrl& currentUrl, const char* xdgKey, const QString& type) +{ + QUrl newUrl = ur->url(); + //url might be empty, use QDir::homePath (the default for xdg) then + if (!newUrl.isValid()) { + newUrl = QUrl(QUrl::fromLocalFile(QDir::homePath())); + } + if (!newUrl.matches(currentUrl, QUrl::StripTrailingSlash)) { + const QString path = newUrl.toLocalFile(); + if (!QDir(path).exists()) { + // Check permissions + if (QDir().mkpath(path)) { + QDir().rmdir(path); // rmdir again, so that we get a fast rename + } else { + KMessageBox::sorry(this, KIO::buildErrorString(KIO::ERR_COULD_NOT_MKDIR, path)); + ur->setUrl(currentUrl); // revert + return false; + } + } + if (moveDir(currentUrl, newUrl, type)) { + //save in XDG user-dirs.dirs config file, this is where KGlobalSettings/QDesktopServices reads from. + const QString userDirsFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/user-dirs.dirs")); + KConfig xdgUserConf(userDirsFile, KConfig::SimpleConfig); + KConfigGroup g(&xdgUserConf, ""); + g.writeEntry(xdgKey, QString("\"" + translatePath(path) + "\"")); + return true; + } + } + return false; +} + +bool DesktopPathConfig::moveDir( const QUrl & src, const QUrl & dest, const QString & type ) +{ + if (!src.isLocalFile() || !dest.isLocalFile()) + return true; + if (!QFile::exists(src.toLocalFile())) + return true; + // Do not move $HOME! #193057 + const QString translatedPath = translatePath(src.toLocalFile()); + if (translatedPath == "$HOME" || translatedPath == "$HOME/") { + return true; + } + + m_ok = true; + + QString question; + KGuiItem yesItem; + KGuiItem noItem; + if (QFile::exists(dest.toLocalFile())) { + // TODO: check if the src dir is empty? Nothing to move, then... + question = i18n("The path for '%1' has been changed.\nDo you want the files to be moved from '%2' to '%3'?", + type, src.toLocalFile(), + dest.toLocalFile()); + yesItem = KGuiItem(i18nc("Move files from old to new place", "Move")); + noItem = KGuiItem(i18nc("Use the new directory but do not move files", "Do not Move")); + } else { + question = i18n("The path for '%1' has been changed.\nDo you want to move the directory '%2' to '%3'?", + type, src.toLocalFile(), + dest.toLocalFile()); + yesItem = KGuiItem(i18nc("Move the directory", "Move")); + noItem = KGuiItem(i18nc("Use the new directory but do not move anything", "Do not Move")); + } + + // Ask for confirmation before moving the files + if (KMessageBox::questionYesNo(this, question, i18n("Confirmation Required"), + yesItem, noItem) + == KMessageBox::Yes ) + { + if (QFile::exists(dest.toLocalFile())) { + // Destination already exists -- should always be the case, for most types, + // but maybe not for the complex autostart case (to be checked...) + m_copyToDest = dest; + m_copyFromSrc = src; + KIO::ListJob* job = KIO::listDir( src ); + job->setAutoDelete(false); // see below + KJobWidgets::setWindow(job, this); + job->ui()->setAutoErrorHandlingEnabled(true); + connect(job, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)), + this, SLOT(slotEntries(KIO::Job*,KIO::UDSEntryList))); + // slotEntries will move every file/subdir individually into the dest + job->exec(); + if (m_ok) { + QDir().rmdir(src.toLocalFile()); // hopefully it's empty by now + } + delete job; + } + else + { + kDebug() << "Direct move from" << src << "to" << dest; + KIO::Job * job = KIO::move( src, dest ); + KJobWidgets::setWindow(job, this); + connect(job, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*))); + job->exec(); + } + } + kDebug() << "DesktopPathConfig::slotResult returning " << m_ok; + return m_ok; +} + +void DesktopPathConfig::slotEntries(KIO::Job*, const KIO::UDSEntryList& list) +{ + QListIterator it(list); + while (it.hasNext()) { + KFileItem file(it.next(), m_copyFromSrc, true, true); + kDebug() << file.url(); + if (file.url() == m_copyFromSrc || file.url().fileName() == "..") { + continue; + } + + KIO::Job * moveJob = KIO::move(file.url(), m_copyToDest); + KJobWidgets::setWindow(moveJob, this); + connect(moveJob, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*))); + moveJob->exec(); // sub-event loop here. : the main job is not autodeleted because it would be deleted here + } +} + +void DesktopPathConfig::slotResult( KJob * job ) +{ + if (job->error()) { + if ( job->error() != KIO::ERR_DOES_NOT_EXIST ) + m_ok = false; + + // If the source doesn't exist, no wonder we couldn't move the dir. + // In that case, trust the user and set the new setting in any case. + + static_cast(job)->ui()->showErrorMessage(); + } +} + +#include "globalpaths.moc" diff --git a/kcms/desktoppaths/globalpaths.h b/kcms/desktoppaths/globalpaths.h new file mode 100644 index 0000000000..ef3234afb1 --- /dev/null +++ b/kcms/desktoppaths/globalpaths.h @@ -0,0 +1,84 @@ +/** + * Copyright (c) Martin R. Jones 1996 + * Copyright 1998-2007 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// Summarized history: +// +// "Desktop Icons Options" Tab for KDesktop configuration +// Martin Jones +// +// Port to KControl, split from "Misc" Tab, Port to KControl2 +// (c) David Faure 1998 +// Desktop menus, paths +// (c) David Faure 2000 + +#ifndef __GLOBALPATHS_H +#define __GLOBALPATHS_H + +#include +#include +#include +#include + +class QFormLayout; +class KJob; +class KUrlRequester; +class QStringList; + +namespace KIO { class Job; } + +//----------------------------------------------------------------------------- +// The "Path" Tab contains : +// The paths for Desktop, Autostart and Documents + +class DesktopPathConfig : public KCModule +{ + Q_OBJECT +public: + DesktopPathConfig( QWidget *parent, const QVariantList &args ); + virtual void load(); + virtual void save(); + virtual void defaults(); + +private Q_SLOTS: + void slotEntries( KIO::Job * job, const KIO::UDSEntryList& list); + +private: + KUrlRequester* addRow(QFormLayout *lay, const QString& label, const QString& whatsThis); + bool xdgSavePath(KUrlRequester* ur, const QUrl& currentUrl, const char* xdgKey, const QString& type); + + // Desktop Paths + KUrlRequester *urDesktop; + KUrlRequester *urAutostart; + KUrlRequester *urDocument; + KUrlRequester *urDownload; + KUrlRequester *urMovie; + KUrlRequester *urPicture; + KUrlRequester *urMusic; + + bool moveDir( const QUrl & src, const QUrl & dest, const QString & type ); + bool m_ok; + QUrl m_copyToDest; // used when the destination directory already exists + QUrl m_copyFromSrc; + +private Q_SLOTS: + void slotResult( KJob * job ); +}; + +#endif + diff --git a/kcms/desktoptheme/CMakeLists.txt b/kcms/desktoptheme/CMakeLists.txt new file mode 100644 index 0000000000..b5d2bc57d3 --- /dev/null +++ b/kcms/desktoptheme/CMakeLists.txt @@ -0,0 +1,27 @@ +# Project Needs a name ofcourse +project(desktoptheme) + +set(kcmdesktoptheme_SRCS kcmdesktoptheme.cpp desktopthemedetails.cpp thememodel.cpp) +qt5_wrap_ui(kcmdesktoptheme_SRCS DesktopTheme.ui DesktopThemeDetails.ui) + +add_library(kcm_desktoptheme MODULE ${kcmdesktoptheme_SRCS}) +target_link_libraries(kcm_desktoptheme ${X11_LIBRARIES} + KF5::Archive + KF5::KCMUtils + KF5::I18n + KF5::Parts + KF5::Plasma + KF5::KIOCore + KF5::KIOWidgets + KF5::NewStuff + KF5::KDE4Support +) + +kservice_desktop_to_json(kcm_desktoptheme desktoptheme.desktop) + +install(TARGETS kcm_desktoptheme DESTINATION ${PLUGIN_INSTALL_DIR} ) +install( FILES plasma-themes.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) + +########### install files ############### +install( FILES desktoptheme.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + diff --git a/kcms/desktoptheme/DesktopTheme.ui b/kcms/desktoptheme/DesktopTheme.ui new file mode 100644 index 0000000000..ccc040c212 --- /dev/null +++ b/kcms/desktoptheme/DesktopTheme.ui @@ -0,0 +1,104 @@ + + + DesktopTheme + + + + 0 + 0 + 669 + 460 + + + + + + + 0 + + + + Theme + + + + + + Insta&ll from File + + + + + + + + + + + + + true + + + Get New Themes... + + + + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + 462 + 20 + + + + + + + + + Details + + + + + + + + + + + + + + KPushButton + QPushButton +
    kpushbutton.h
    +
    + + DesktopThemeDetails + QWidget +
    desktopthemedetails.h
    + 1 +
    +
    + + +
    diff --git a/kcms/desktoptheme/DesktopThemeDetails.ui b/kcms/desktoptheme/DesktopThemeDetails.ui new file mode 100644 index 0000000000..9df3536eab --- /dev/null +++ b/kcms/desktoptheme/DesktopThemeDetails.ui @@ -0,0 +1,395 @@ + + + DesktopThemeItems + + + + 0 + 0 + 661 + 487 + + + + + 0 + 0 + + + + + 200 + 700 + + + + Desktop Theme Details + + + + + + + + + + 0 + 0 + + + + Choose an item and customize it by assigning it a theme + + + You can set any theme to any item. The available themes for the item are in the dropdown box on the right. + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + false + + + false + + + + + + + + 0 + 0 + + + + + + + Enable more options + + + This will expand the dialog and give you options to export your custom theme as well as to remove a theme. + + + More + + + + + + + + + true + + + Remove the selected theme + + + Clicking this button will remove the selected theme. You will be asked for confirmation. + + + Remove Theme + + + + + + + true + + + Save your theme in a zip archive + + + You can save your theme in a zip archive in order to share it with the community. + + + Export Theme to File... + + + + + + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + + + New theme name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_newThemeName + + + + + + + Custom theme name + + + Give a name to your custom theme. + + + + + + + Author: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_newThemeAuthor + + + + + + + Custom theme author + + + Enter the author name of your custom theme. + + + + + + + Version: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_newThemeVersion + + + + + + + Custom theme version number + + + Enter the version number of your custom theme. + + + + + + + + + + + Description: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_newThemeDescription + + + + + + + + 0 + 0 + + + + Custom theme description + + + Enter a description which will explain your custom theme. + + + + + + + + + + + + Qt::Vertical + + + + + + + Select theme from above to customize + + + + + + + + 0 + 0 + + + + + + + + + Theme Author + + + Qt::AlignLeading + + + + + + + + 75 + true + + + + Theme Name + + + Qt::AlignCenter + + + + + + + Theme Version + + + Qt::AlignRight + + + + + + + + + The theme description goes here... + + + Qt::AlignCenter + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 130 + + + + + + + + + 187 + 187 + 187 + + + + + + + + + 187 + 187 + 187 + + + + + + + + + 255 + 255 + 255 + + + + + + + + Available themes + + + Choose a start theme in this list then customize some items below. All less important items not listed below will use this start theme. + + + Qt::ScrollBarAlwaysOff + + + false + + + QListView::IconMode + + + + + + + + KLineEdit + QLineEdit +
    klineedit.h
    +
    +
    + + +
    diff --git a/kcms/desktoptheme/Messages.sh b/kcms/desktoptheme/Messages.sh new file mode 100755 index 0000000000..14b32ad903 --- /dev/null +++ b/kcms/desktoptheme/Messages.sh @@ -0,0 +1,4 @@ +#! /bin/sh +$EXTRACTRC *.ui >> rc.cpp +$XGETTEXT *.cpp -o $podir/kcm_desktopthemedetails.pot +rm -f rc.cpp diff --git a/kcms/desktoptheme/desktoptheme.desktop b/kcms/desktoptheme/desktoptheme.desktop new file mode 100644 index 0000000000..602f04cfd5 --- /dev/null +++ b/kcms/desktoptheme/desktoptheme.desktop @@ -0,0 +1,189 @@ +[Desktop Entry] +Exec=kcmshell5 desktoptheme +Icon=preferences-desktop +Type=Service + +X-KDE-ServiceTypes=KCModule +X-KDE-Library=kcm_desktoptheme +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=desktop-appearance +X-DocPath=kcontrol/desktopthemedetails/index.html + +Name=Desktop Theme +Name[ar]=سمة سطح المكتب +Name[ast]=Tema d'escritoriu +Name[bg]=Тема за работния плот +Name[bn]=ডেস্কটপ থীম +Name[bs]=Tema površi +Name[ca]=Tema d'escriptori +Name[ca@valencia]=Tema d'escriptori +Name[cs]=Motiv plochy +Name[da]=Skrivebordstema +Name[de]=Arbeitsflächen-Design +Name[el]=Θέμα επιφάνειας εργασίας +Name[en_GB]=Desktop Theme +Name[es]=Tema de escritorio +Name[et]=Töölauateema +Name[eu]=Mahaigaineko gaia +Name[fi]=Työpöytäteema +Name[fr]=Thème de bureau +Name[ga]=Téama Deisce +Name[gl]=Tema do escritorio +Name[gu]=ડેસ્કટોપ થીમ +Name[he]=ערכת־הנושא לשולחן־העבודה +Name[hi]=डेस्कटॉप प्रसंग +Name[hr]=Tema radne površine +Name[hu]=Asztali téma +Name[ia]=Thema de scriptorio +Name[id]=Tema Desktop +Name[is]=Skjáborðsþema +Name[it]=Tema del desktop +Name[ja]=デスクトップテーマ +Name[kk]=Үстел нақышы +Name[km]=ស្បែក​ផ្ទៃតុ +Name[kn]=ಗಣಕತೆರೆ ಪರಿಸರವಿನ್ಯಾಸ +Name[ko]=데스크톱 테마 +Name[lt]=Darbastalio tema +Name[lv]=Darbvirsmas tēma +Name[mr]=डेस्कटॉप शैली +Name[nb]=Skrivebordstema +Name[nds]=Schriefdischmuster +Name[nl]=Bureaubladthema +Name[nn]=Skrivebordstema +Name[pa]=ਡੈਸਕਟਾਪ ਥੀਮ +Name[pl]=Wystrój pulpitu +Name[pt]=Tema do Ambiente de Trabalho +Name[pt_BR]=Tema da área de trabalho +Name[ro]=Tematica de birou +Name[ru]=Тема рабочего стола +Name[si]=වැඩතල තේමාව +Name[sk]=Téma plochy +Name[sl]=Namizna tema +Name[sr]=Тема површи +Name[sr@ijekavian]=Тема површи +Name[sr@ijekavianlatin]=Tema površi +Name[sr@latin]=Tema površi +Name[sv]=Skrivbordstema +Name[tg]=Мавзӯъи мизи корӣ +Name[th]=ชุดตกแต่งพื้นที่ทำงาน +Name[tr]=Masaüstü Teması +Name[ug]=ئۈستەلئۈستى ئۆرنىكى +Name[uk]=Тема стільниці +Name[vi]=Sắc thái màn hình +Name[wa]=Tinme do scribanne +Name[x-test]=xxDesktop Themexx +Name[zh_CN]=桌面主题 +Name[zh_TW]=桌面主題 +Comment=Customize the desktop theme +Comment[ar]=خصص عناصر السمة سطح المكتب بشكل منفرد +Comment[ast]=Personalizar el tema d'escritoriu +Comment[bg]=Настройки на теми за работния плот +Comment[bn]=ডেস্কটপ থীম পছন্দমত বদলান +Comment[bs]=Prilagodite temu površi +Comment[ca]=Personalitza el tema d'escriptori +Comment[ca@valencia]=Personalitza el tema d'escriptori +Comment[cs]=Upravit vzhled plochy +Comment[da]=Tilpas skrivebordstemaet +Comment[de]=Arbeitsflächen-Design anpassen +Comment[el]=Προσαρμογή θέματος της επιφάνειας εργασίας +Comment[en_GB]=Customise the desktop theme +Comment[es]=Personalizar el tema de escritorio +Comment[et]=Töölauateema kohandamine +Comment[eu]=Pertsonalizatu mahaigaineko gaia +Comment[fi]=Työpöytäteeman asetukset +Comment[fr]=Personnaliser le thème de bureau +Comment[ga]=Saincheap an téama deisce +Comment[gl]=Personaliza o tema do escritorio +Comment[he]=התאמה אישית של ערכת־הנושא לשולחן־העבודה +Comment[hi]=डेस्कटॉप प्रसंग मनपसंद बनाएँ +Comment[hr]=Prilagodba teme radne površine +Comment[hu]=Az asztali téma testreszabása +Comment[ia]=Personalisar le thema de scriptorio +Comment[id]=Sesuaikan tema desktop +Comment[is]=Sérsníða skjáborðsþema +Comment[it]=Personalizza il tema del desktop +Comment[ja]=デスクトップテーマのカスタマイズ +Comment[kk]=Үстел нақышын өзінше баптап алу +Comment[km]=ប្ដូរ​ស្បែក​ផ្ទៃតុ​តាមបំណង +Comment[kn]=ಗಣಕತೆರೆ ಪರಿಸರವಿನ್ಯಾಸವನ್ನು ಇಚ್ಛೆಗೆ ತಕ್ಕಂತೆ ಹೊಂದಿಸಿ +Comment[ko]=테마 사용자 정의 +Comment[lt]=Derinti darbastalio temą +Comment[lv]=Pielāgot darbivrsmas tēmu +Comment[mr]=डेस्कटॉप शैलीत ऐच्छिक बदल करा +Comment[nb]=Still inn temaet for skrivebordet +Comment[nds]=Dat Schriefdischmuster topassen +Comment[nl]=Pas het bureaubladthema aan +Comment[nn]=Tilpass skrivebordstemaet +Comment[pa]=ਡੈਸਕਟਾਪ ਥੀਮ ਕਸਟਮਾਈਜ਼ ਕਰੋ +Comment[pl]=Dostosowywanie wystroju pulpitu +Comment[pt]=Personalizar o tema do ambiente de trabalho +Comment[pt_BR]=Personaliza o tema da área de trabalho +Comment[ro]=Particularizează tematica de birou +Comment[ru]=Настройка темы рабочего стола +Comment[si]=වැඩතල තේමාව රිසිකරණය කරන්න +Comment[sk]=Prispôsobenie témy plochy +Comment[sl]=Prilagodite namizno temo +Comment[sr]=Прилагодите тему површи +Comment[sr@ijekavian]=Прилагодите тему површи +Comment[sr@ijekavianlatin]=Prilagodite temu površi +Comment[sr@latin]=Prilagodite temu površi +Comment[sv]=Anpassa skrivbordstemat +Comment[tg]=Танзимоти мавзӯъи мизи корӣ +Comment[th]=ปรับแต่งชุดตกแต่งพื้นที่ทำงานด้วยตนเอง +Comment[tr]=Masaüstü temasını özelleştir +Comment[ug]=ئۈستەلئۈستى ئۆرنىكىنى ئۆزلەشتۈرىدۇ +Comment[uk]=Налаштування теми стільниці +Comment[vi]=Tuỳ chỉnh sắc thái màn hình +Comment[wa]=Mete a vosse môde li tinme do scribanne +Comment[x-test]=xxCustomize the desktop themexx +Comment[zh_CN]=定制桌面主题 +Comment[zh_TW]=自訂桌面主題 +X-KDE-Keywords=Desktop Theme +X-KDE-Keywords[ar]=سمة سطح المكتب +X-KDE-Keywords[bs]=Tema površi +X-KDE-Keywords[ca]=Tema d'escriptori +X-KDE-Keywords[ca@valencia]=Tema d'escriptori +X-KDE-Keywords[cs]=Motiv plochy +X-KDE-Keywords[da]=Skrivebordstema +X-KDE-Keywords[de]=Arbeitsflächen-Design +X-KDE-Keywords[el]=Θέμα επιφάνειας εργασίας +X-KDE-Keywords[es]=Tema de escritorio +X-KDE-Keywords[et]=Töölauateema +X-KDE-Keywords[eu]=Mahaigaineko gaia +X-KDE-Keywords[fi]=Työpöytäteema +X-KDE-Keywords[fr]=Thème du bureau +X-KDE-Keywords[ga]=Téama Deisce +X-KDE-Keywords[gl]=Tema do escritorio +X-KDE-Keywords[he]=ערכת־הנושא +X-KDE-Keywords[hu]=Asztali téma +X-KDE-Keywords[ia]=Thema de scriptorio +X-KDE-Keywords[is]=Skjáborðsþema +X-KDE-Keywords[it]=Tema del desktop +X-KDE-Keywords[kk]=Desktop Theme,Үстел нақышы +X-KDE-Keywords[km]=រូបរាង​ផ្ទៃតុ +X-KDE-Keywords[ko]=데스크톱 테마 +X-KDE-Keywords[lt]=Darbastalio tema +X-KDE-Keywords[mr]=डेस्कटॉप शैली +X-KDE-Keywords[nb]=Skrivebordstema +X-KDE-Keywords[nds]=Schriefdischmuster +X-KDE-Keywords[nl]=Bureaubladthema +X-KDE-Keywords[pa]=ਡੈਸਕਟਾਪ ਥੀਮ +X-KDE-Keywords[pl]=Wystrój pulpitu +X-KDE-Keywords[pt]=Tema do Ambiente de Trabalho +X-KDE-Keywords[pt_BR]=Tema da área de trabalho +X-KDE-Keywords[ro]=Tematica de birou +X-KDE-Keywords[ru]=Тема рабочего стола +X-KDE-Keywords[sk]=Téma plochy +X-KDE-Keywords[sl]=Namizna tema +X-KDE-Keywords[sr]=Desktop Theme,тема површи +X-KDE-Keywords[sr@ijekavian]=Desktop Theme,тема површи +X-KDE-Keywords[sr@ijekavianlatin]=Desktop Theme,tema površi +X-KDE-Keywords[sr@latin]=Desktop Theme,tema površi +X-KDE-Keywords[sv]=Skrivbordstema +X-KDE-Keywords[tr]=Masaüstü Teması +X-KDE-Keywords[ug]=ئۈستەلئۈستى ئۆرنىكى +X-KDE-Keywords[uk]=тема,стільниця +X-KDE-Keywords[vi]=Sắc thái màn hình +X-KDE-Keywords[x-test]=xxDesktop Themexx +X-KDE-Keywords[zh_CN]=Desktop Theme,桌面主题 +X-KDE-Keywords[zh_TW]=Desktop Theme diff --git a/kcms/desktoptheme/desktopthemedetails.cpp b/kcms/desktoptheme/desktopthemedetails.cpp new file mode 100644 index 0000000000..ab6973e255 --- /dev/null +++ b/kcms/desktoptheme/desktopthemedetails.cpp @@ -0,0 +1,590 @@ +/* + Copyright (c) 2008 Andrew Lake + Copyright (c) 2010 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. +*/ + +#include "desktopthemedetails.h" + +#include "thememodel.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct ThemeItemNameType { + const char* m_type; + const char* m_displayItemName; + const char* m_themeItemPath; + const char* m_iconName; +}; + +const ThemeItemNameType themeCollectionName[] = { + { "Color Scheme", I18N_NOOP2("plasma name", "Color Scheme"),"colors", "preferences-desktop-color"}, + { "Panel Background", I18N_NOOP2("plasma name", "Panel Background"),"widgets/panel-background", "plasma"}, + { "Kickoff", I18N_NOOP2("plasma name", "Kickoff"), "dialogs/kickoff", "kde"}, + { "Task Items", I18N_NOOP2("plasma name", "Task Items"), "widgets/tasks", "preferences-system-windows"}, + { "Widget Background", I18N_NOOP2("plasma name", "Widget Background"), "widgets/background", "plasma"}, + { "Translucent Background", I18N_NOOP2("plasma name", "Translucent Background"), "widgets/translucentbackground", "plasma"}, + { "Dialog Background", I18N_NOOP2("plasma name", "Dialog Background"), "dialogs/background", "plasma"}, + { "Analog Clock", I18N_NOOP2("plasma name", "Analog Clock"), "widgets/clock", "chronometer"}, + { "Notes", I18N_NOOP2("plasma name", "Notes"), "widgets/notes", "view-pim-notes"}, + { "Tooltip", I18N_NOOP2("plasma name", "Tooltip"), "widgets/tooltip", "plasma"}, + { "Pager", I18N_NOOP2("plasma name", "Pager"), "widgets/pager", "plasma"}, + { "Run Command Dialog", I18N_NOOP2("plasma name", "Run Command Dialog"), "dialogs/krunner", "system-run"}, + { "Shutdown Dialog", I18N_NOOP2("plasma name", "Shutdown Dialog"), "dialogs/shutdowndialog", "system-shutdown"}, + { "Icons", I18N_NOOP2("plasma name", "Icons"), "icons/", "preferences-desktop-icons"}, + { 0, 0,0,0 } // end of data +}; + + +DesktopThemeDetails::DesktopThemeDetails(QWidget* parent) + : QWidget(parent), + m_themeModel(0) + +{ + setWindowIcon(QIcon::fromTheme("preferences-desktop")); + setupUi(this); + + QFont font = QFont(); + //font.setBold(true); + font.setPointSize(1.2*font.pointSize()); + m_themeInfoName->setFont(font); + + m_enableAdvanced->setChecked(false); + toggleAdvancedVisible(); + + + m_themeModel = new ThemeModel(this); + m_theme->setModel(m_themeModel); + m_theme->setItemDelegate(new ThemeDelegate(m_theme)); + + reloadConfig(); + + connect(m_theme->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(themeSelectionChanged(QItemSelection,QItemSelection))); + + connect(m_enableAdvanced, SIGNAL(toggled(bool)), this, SLOT(toggleAdvancedVisible())); + connect(m_removeThemeButton, SIGNAL(clicked()), this, SLOT(removeTheme())); + connect(m_exportThemeButton, SIGNAL(clicked()), this, SLOT(exportTheme())); + + connect(m_newThemeName, SIGNAL(editingFinished()), this, SLOT(newThemeInfoChanged())); + + m_baseTheme = "default"; + m_themeCustomized = false; + resetThemeDetails(); + adjustSize(); +} + +DesktopThemeDetails::~DesktopThemeDetails() +{ + cleanup(); +} + +void DesktopThemeDetails::cleanup() +{ +} + +void DesktopThemeDetails::reloadConfig() +{ + // Theme + KConfigGroup cfg = KConfigGroup(KSharedConfig::openConfig("plasmarc"), "Theme"); + const QString theme = cfg.readEntry("name", "default"); + m_theme->setCurrentIndex(m_themeModel->indexOf(theme)); + +} + +void DesktopThemeDetails::save() +{ + QString themeRoot; + KStandardDirs dirs; + if (m_newThemeName->text().isEmpty()) { + themeRoot = ".customized"; + //Toggle customized theme directory name to ensure theme reload + if (QDir(dirs.locateLocal("data", "desktoptheme/" + themeRoot + '/', false)).exists()) { + themeRoot = themeRoot + '1'; + } + } else { + themeRoot = m_newThemeName->text().replace(' ',"_").remove(QRegExp("[^A-Za-z0-9_]")); + } + + //Save theme items + QFile customSettingsFile; + bool customSettingsFileOpen = false; + + if (m_themeCustomized || !m_newThemeName->text().isEmpty()) { + + clearCustomized(themeRoot); + + //Copy all files from the base theme + QString baseSource = dirs.locate("data", "desktoptheme/" + m_baseTheme + "/metadata.desktop"); + baseSource = baseSource.left(baseSource.lastIndexOf('/', -1)); + KIO::CopyJob *copyBaseTheme = KIO::copyAs(QUrl::fromLocalFile(baseSource), QUrl::fromLocalFile(dirs.locateLocal("data", "desktoptheme/" + themeRoot, true)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(copyBaseTheme, this); + + //Prepare settings file for customized theme + if (isCustomized(themeRoot)) { + customSettingsFile.setFileName(dirs.locateLocal("data", "desktoptheme/" + themeRoot + "/settings")); + customSettingsFileOpen = customSettingsFile.open(QFile::WriteOnly); + if (customSettingsFileOpen) { + QTextStream out(&customSettingsFile); + out << "baseTheme=" + m_baseTheme + "\r\n";; + } + } + QString settingsSource; + + //Copy each item theme file to new theme folder + QHashIterator i(m_itemThemeReplacements); + while (i.hasNext()) { + i.next(); + //Get root directory where item should reside (relative to theme root) + QString itemRoot = ""; + if (m_itemPaths[i.key()].lastIndexOf('/', -1) != -1) { + itemRoot= m_itemPaths[i.key()].left(m_itemPaths[i.key()].lastIndexOf('/', -1)); + } + //Setup source and destination + QString source; + QString dest; + if (i.value() != -1) { + //Source is a theme + source = "desktoptheme/" + m_themeRoots[i.value()] + '/' + m_itemPaths[i.key()] + '*'; + dest = "desktoptheme/" + themeRoot + '/' + itemRoot + '/'; + settingsSource = m_themeRoots[i.value()]; + } else { + //Source is a file + source = m_itemFileReplacements[i.key()]; + dest = "desktoptheme/" + themeRoot + '/' + itemRoot + '/'; + settingsSource = m_itemFileReplacements[i.key()]; + } + + + //Delete item files at destination before copying (possibly there from base theme copy) + const QStringList deleteFiles = dirs.findAllResources("data", "desktoptheme/" + themeRoot + '/' + m_itemPaths[i.key()] + '*', + KStandardDirs::NoDuplicates); + for (int j = 0; j < deleteFiles.size(); ++j) { + KIO::DeleteJob *dj = KIO::del(QUrl::fromLocalFile(deleteFiles.at(j)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(dj, this); + } + + //Copy item(s) + dest = dirs.locateLocal("data", dest, true); + QStringList copyFiles; + if (i.value() != -1) { + copyFiles = dirs.findAllResources("data", source, KStandardDirs::NoDuplicates); //copy from theme + } else { + copyFiles << source; //copy from file + } + for (int j = 0; j < copyFiles.size(); ++j) { + KIO::CopyJob *cj = KIO::copy(QUrl::fromLocalFile(copyFiles.at(j)), QUrl::fromLocalFile(dest), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(cj, this); + } + + //Record settings file + if (customSettingsFileOpen) { + QTextStream out(&customSettingsFile); + out << m_items.key(i.key()) + "=" + settingsSource +"\r\n"; + } + } + if (customSettingsFileOpen) customSettingsFile.close(); + + // Create new theme FDO desktop file + QFile::remove(dirs.locateLocal("data", "desktoptheme/" + themeRoot + "/metadata.desktop", false)); + KDesktopFile df(dirs.locateLocal("data", "desktoptheme/" + themeRoot + "/metadata.desktop")); + KConfigGroup cg = df.desktopGroup(); + if (isCustomized(themeRoot)) { + cg.writeEntry("Name",i18n("(Customized)")); + cg.writeEntry("Comment", i18n("User customized theme")); + cg.writeEntry("X-KDE-PluginInfo-Name", themeRoot); + } else { + cg.writeEntry("Name", m_newThemeName->text()); + cg.writeEntry("Comment", m_newThemeDescription->text()); + cg.writeEntry("X-KDE-PluginInfo-Author", m_newThemeAuthor->text()); + cg.writeEntry("X-KDE-PluginInfo-Version", m_newThemeVersion->text()); + } + cg.sync(); + + m_themeCustomized = false; + } + + m_themeModel->reload(); + if (m_themeModel->indexOf(themeRoot).isValid()) { + m_theme->setCurrentIndex(m_themeModel->indexOf(themeRoot)); + QString themeName = m_theme->currentIndex().data(Qt::DisplayRole).toString(); + setDesktopTheme(themeRoot); + } + resetThemeDetails(); +} + +void DesktopThemeDetails::removeTheme() +{ + bool removeTheme = true; + KConfigGroup cfg = KConfigGroup(KSharedConfig::openConfig("plasmarc"), "Theme"); + QString activeTheme = cfg.readEntry("name", "default"); + const QString theme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + const QString themeName = m_theme->currentIndex().data(Qt::DisplayRole).toString(); + + + if (m_themeCustomized) { + if(KMessageBox::questionYesNo(this, i18n("Theme items have been changed. Do you still wish remove the \"%1\" theme?", themeName), i18n("Remove Desktop Theme")) == KMessageBox::No) { + removeTheme = false; + } + } else { + if (theme == "default") { + KMessageBox::information(this, i18n("Removal of the default desktop theme is not allowed."), i18n("Remove Desktop Theme")); + removeTheme = false; + } else { + if(KMessageBox::questionYesNo(this, i18n("Are you sure you wish remove the \"%1\" theme?", themeName), i18n("Remove Desktop Theme")) == KMessageBox::No) { + removeTheme = false; + } + } + + } + KStandardDirs dirs; + if (removeTheme) { + if (theme == activeTheme) { + setDesktopTheme("default"); + activeTheme = "default"; + } + if (QDir(dirs.locateLocal("data", "desktoptheme/" + theme, false)).exists()) { + KIO::DeleteJob *deleteTheme = KIO::del(QUrl::fromLocalFile(dirs.locateLocal("data", "desktoptheme/" + theme, false)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(deleteTheme, this); + } + } + m_themeModel->reload(); + reloadConfig(); + m_theme->setCurrentIndex(m_themeModel->indexOf(activeTheme)); +} + +void DesktopThemeDetails::exportTheme() +{ + const QString theme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + + if (m_themeCustomized || + (isCustomized(theme) && m_newThemeName->text() == "")) { + KMessageBox::information(this, i18n("Please apply theme item changes (with a new theme name) before attempting to export theme."), i18n("Export Desktop Theme")); + } else { + QString themeStoragePath = theme; + + KStandardDirs dirs; + const QString themePath = dirs.findResource("data", "desktoptheme/" + themeStoragePath + "/metadata.desktop"); + if (!themePath.isEmpty()){ + QString expFileName = QFileDialog::getSaveFileName(this, i18n("Export theme to file"), QString(), i18n("Archive (*.zip)")); + if (!expFileName.endsWith(".zip")) + expFileName = expFileName + ".zip"; + if (!expFileName.isEmpty()) { + KUrl path(themePath); + KZip expFile(expFileName); + expFile.open(QIODevice::WriteOnly); + expFile.addLocalDirectory(path.directory (), themeStoragePath); + expFile.close(); + } + } + } + +} + +void DesktopThemeDetails::loadThemeItems() +{ + // Set up items, item paths and icons + m_items.clear(); // clear theme items + m_itemPaths.clear(); // clear theme item paths + m_itemIcons.clear(); + for (int i = 0; themeCollectionName[i].m_type; ++i) { + m_items[themeCollectionName[i].m_type] = i; + m_itemPaths[i] = themeCollectionName[i].m_themeItemPath; + m_itemIcons[i] = themeCollectionName[i].m_iconName; + } + + // Get installed themes + m_themes.clear(); // clear installed theme list + m_themeRoots.clear(); // clear installed theme root paths + KStandardDirs dirs; + QStringList themes = dirs.findAllResources("data", "desktoptheme/*/metadata.desktop", + KStandardDirs::NoDuplicates); + themes.sort(); + int j=0; + for (int i = 0; i < themes.size(); ++i) { + QString theme = themes.at(i); + int themeSepIndex = theme.lastIndexOf('/', -1); + QString themeRoot = theme.left(themeSepIndex); + int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); + QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); + KDesktopFile df(theme); + QString name = df.readName(); + if (name.isEmpty()) { + name = packageName; + } + + if (!isCustomized(packageName) && (m_themeRoots.key(packageName, -1) == -1)) { + m_themes[name] = j; + m_themeRoots[j] = packageName; + ++j; + } + } + + // Set up default item replacements + m_itemThemeReplacements.clear(); + m_itemFileReplacements.clear(); + QString currentTheme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + + if (!isCustomized(currentTheme)) { + // Set default replacements to current theme + QHashIterator i(m_items); + while (i.hasNext()) { + i.next(); + m_itemThemeReplacements[i.value()] = m_themeRoots.key(currentTheme); + } + m_baseTheme = currentTheme; + } else { + // Set default replacements to customized theme settings + QFile customSettingsFile(dirs.locateLocal("data", "desktoptheme/" + currentTheme +"/settings")); + if (customSettingsFile.open(QFile::ReadOnly)) { + QTextStream in(&customSettingsFile); + QString line; + QStringList settingsPair; + while (!in.atEnd()) { + line = in.readLine(); + settingsPair = line.split('='); + if (settingsPair.at(0) == "baseTheme") { + m_baseTheme = settingsPair.at(1); + } else { + if (m_themeRoots.key(settingsPair.at(1), -1) != -1) { // theme for current item exists + m_itemThemeReplacements[m_items[settingsPair.at(0)]] = m_themeRoots.key(settingsPair.at(1)); + } else if (QFile::exists(settingsPair.at(1))) { + m_itemThemeReplacements[m_items[settingsPair.at(0)]] = -1; + m_itemFileReplacements[m_items[settingsPair.at(0)]] = settingsPair.at(1); + } + } + } + customSettingsFile.close(); + } + } + + // Build displayed list of theme items + m_themeItemList->setRowCount(m_items.size()); + m_themeItemList->setColumnCount(2); + m_themeItemList->setHorizontalHeaderLabels(QStringList()<< i18n("Theme Item")< i(m_items); + while (i.hasNext()) { + i.next(); + displayedItem = displayedItemText(i.value()); + m_themeItemList->setItem(i.value(), 0, new QTableWidgetItem(displayedItem)); + m_themeItemList->item(i.value(),0)->setIcon(QIcon::fromTheme(m_itemIcons[i.value()])); + m_themeItemList->setCellWidget(i.value(), 1, new QComboBox()); + updateReplaceItemList(i.value()); + m_themeItemList->resizeColumnToContents(1); + } + m_themeItemList->setSelectionBehavior(QAbstractItemView::SelectRows); + m_themeItemList->verticalHeader()->hide(); + m_themeItemList->horizontalHeader()->setStretchLastSection(true); + m_themeItemList->horizontalHeader()->setMinimumSectionSize(120); + m_themeItemList->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);; + m_themeItemList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);; + m_themeItemList->setCurrentCell(0, 1); +} + +void DesktopThemeDetails::updateReplaceItemList(const int& item) +{ + QString currentTheme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + + + // Repopulate combobox droplist + QComboBox *itemComboBox = static_cast(m_themeItemList->cellWidget(item,1)); + disconnect(itemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(replacementItemChanged())); + itemComboBox->clear(); + for (int i = 0; i < m_themes.size(); ++i) { + QString displayedDropListItem = i18n("%1 %2", m_themes.key(i), displayedItemText(item)); + itemComboBox->addItem(displayedDropListItem); + } + itemComboBox->addItem(i18n("File...")); + + // Set combobox value to current replacement + if (m_itemThemeReplacements[item] != -1) { + itemComboBox->setCurrentIndex(m_itemThemeReplacements[item]); + } else { + itemComboBox->addItem(m_itemFileReplacements[item]); + itemComboBox->setCurrentIndex(itemComboBox->findText(m_itemFileReplacements[item])); + } + connect(itemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(replacementItemChanged())); +} + +void DesktopThemeDetails::replacementItemChanged() +{ + //Check items to see if theme has been customized + m_themeCustomized = true; + QHashIterator i(m_items); + while (i.hasNext()) { + i.next(); + QComboBox *itemComboBox = static_cast(m_themeItemList->cellWidget(i.value(), 1)); + int replacement = itemComboBox->currentIndex(); + if (replacement <= (m_themes.size() - 1)) { + // Item replacement source is a theme + m_itemThemeReplacements[i.value()] = itemComboBox->currentIndex(); + } else if (replacement > (m_themes.size() - 1)) { + // Item replacement source is a file + if (itemComboBox->currentText() == i18n("File...")) { + //Get the filename for the replacement item + QString translated_key = i18nc("plasma name", qPrintable( i.key() ) ); + QString fileReplacement = QFileDialog::getOpenFileName(this, i18n("Select File to Use for %1",translated_key)); + if (!fileReplacement.isEmpty()) { + m_itemFileReplacements[i.value()] = fileReplacement; + int index = itemComboBox->findText(fileReplacement); + if (index == -1) itemComboBox->addItem(fileReplacement); + disconnect(itemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(replacementItemChanged())); + itemComboBox->setCurrentIndex(itemComboBox->findText(fileReplacement)); + connect(itemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(replacementItemChanged())); + m_itemThemeReplacements[i.value()] = -1; //source is not a theme + m_itemFileReplacements[i.value()] = itemComboBox->currentText(); + } else { + // Reset combobox to previous value if no file is selected + if (m_itemThemeReplacements[i.value()] != -1) { + itemComboBox->setCurrentIndex(m_itemThemeReplacements[i.value()]); + } else { + itemComboBox->setCurrentIndex(itemComboBox->findText(m_itemFileReplacements[i.value()])); + } + m_themeCustomized = false; + } + } else { + m_itemThemeReplacements[i.value()] = -1; //source is not a theme + m_itemFileReplacements[i.value()] = itemComboBox->currentText(); + } + } + } + + if (m_themeCustomized) emit changed(); +} + +void DesktopThemeDetails::newThemeInfoChanged() +{ + emit changed(); +} + +void DesktopThemeDetails::resetThemeDetails() +{ + QString theme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + + m_themeInfoName->setText(m_theme->currentIndex().data(Qt::DisplayRole).toString()); + m_themeInfoDescription->setText(m_theme->currentIndex().data(ThemeModel::PackageDescriptionRole).toString()); + QString author = m_theme->currentIndex().data(ThemeModel::PackageAuthorRole).toString(); + + if (!author.isEmpty()) { + m_themeInfoAuthor->setText(i18n(" Author: %1",author)); + } else { + m_themeInfoAuthor->setText(""); + } + QString version = m_theme->currentIndex().data(ThemeModel::PackageVersionRole).toString(); + if (!version.isEmpty()) { + m_themeInfoVersion->setText(i18n("Version: %1",version)); + } else { + m_themeInfoVersion->setText(""); + } + + loadThemeItems(); + + m_newThemeName->clear(); + m_newThemeAuthor->clear(); + m_newThemeVersion->clear(); + m_newThemeDescription->clear(); + m_themeCustomized = false; + } + +void DesktopThemeDetails::toggleAdvancedVisible() +{ + m_newThemeNameLabel->setVisible(m_enableAdvanced->isChecked()); + m_newThemeName->setVisible(m_enableAdvanced->isChecked()); + m_newThemeAuthor->setVisible(m_enableAdvanced->isChecked()); + m_newThemeAuthorLabel->setVisible(m_enableAdvanced->isChecked()); + m_newThemeVersion->setVisible(m_enableAdvanced->isChecked()); + m_newThemeVersionLabel->setVisible(m_enableAdvanced->isChecked()); + m_newThemeDescriptionLabel->setVisible(m_enableAdvanced->isChecked()); + m_newThemeDescription->setVisible(m_enableAdvanced->isChecked()); + m_exportThemeButton->setVisible(m_enableAdvanced->isChecked()); + m_removeThemeButton->setVisible(m_enableAdvanced->isChecked()); + m_advancedLine->setVisible(m_enableAdvanced->isChecked()); +} + +bool DesktopThemeDetails::isCustomized(const QString& theme) { + if (theme == ".customized" || theme == ".customized1") { + return true; + } else { + return false; + } +} + +void DesktopThemeDetails::clearCustomized(const QString& themeRoot) { + KStandardDirs dirs; + + if ((isCustomized(themeRoot))) { + // Remove both possible unnamed customized directories + if (QDir(dirs.locateLocal("data", "desktoptheme/.customized", false)).exists()) { + KIO::DeleteJob *clearCustom = KIO::del(QUrl::fromLocalFile(dirs.locateLocal("data", "desktoptheme/.customized", false)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(clearCustom, this); + } + if (QDir(dirs.locateLocal("data", "desktoptheme/.customized1", false)).exists()) { + KIO::DeleteJob *clearCustom1 = KIO::del(QUrl::fromLocalFile(dirs.locateLocal("data", "desktoptheme/.customized1", false)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(clearCustom1, this); + } + } else { + if (QDir(dirs.locateLocal("data", "desktoptheme/" + themeRoot, false)).exists()) { + KIO::DeleteJob *clearCustom = KIO::del(QUrl::fromLocalFile(dirs.locateLocal("data", "desktoptheme/" + themeRoot, false)), KIO::HideProgressInfo); + KIO::NetAccess::synchronousRun(clearCustom, this); + } + } +} + +QString DesktopThemeDetails::displayedItemText(int item) { + QString displayedText = m_items.key(item); + for (int i = 0; themeCollectionName[i].m_type; ++i) { + if (themeCollectionName[i].m_type == m_items.key(item)) { + displayedText = i18nc("plasma name", themeCollectionName[i].m_displayItemName); + } + } + return displayedText; +} + +void DesktopThemeDetails::themeSelectionChanged(const QItemSelection newSelection, const QItemSelection oldSelection) +{ + QString theme = m_theme->currentIndex().data(ThemeModel::PackageNameRole).toString(); + if (theme == "default") { + m_removeThemeButton->setEnabled(false); + } else { + m_removeThemeButton->setEnabled(true); + } + resetThemeDetails(); + Q_UNUSED(newSelection); + Q_UNUSED(oldSelection); +} + +void DesktopThemeDetails::setDesktopTheme(QString themeRoot) +{ + KConfig config(QStandardPaths::locate(QStandardPaths::ConfigLocation, "plasmarc")); + KConfigGroup cg = KConfigGroup(&config, "Theme"); + if (themeRoot == "default") { + cg.deleteEntry("name"); + } else { + cg.writeEntry("name", themeRoot); + } + cg.sync(); +} diff --git a/kcms/desktoptheme/desktopthemedetails.h b/kcms/desktoptheme/desktopthemedetails.h new file mode 100644 index 0000000000..5eab98ebad --- /dev/null +++ b/kcms/desktoptheme/desktopthemedetails.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2007 Paolo Capriotti + Copyright (c) 2008 by Petri Damsten + + This program is free software; you can redistribute it and/or modify + it under the terms of the 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 DESKTOPTHEMEDETAILS_H +#define DESKTOPTHEMEDETAILS_H + +#include "ui_DesktopThemeDetails.h" + +#include + +class ThemeModel; + +class DesktopThemeDetails : public QWidget, public Ui::DesktopThemeItems +{ + Q_OBJECT +public: + DesktopThemeDetails(QWidget* parent); + ~DesktopThemeDetails(); + + void reloadConfig(); + +public Q_SLOTS: + void replacementItemChanged(); + void resetThemeDetails(); + void toggleAdvancedVisible(); + void save(); + void removeTheme(); + void exportTheme(); + void newThemeInfoChanged(); + +Q_SIGNALS: + void changed(); + +private: + void updateReplaceItemList(const int& item); + void loadThemeItems(); + QString displayedItemText(int item); + bool isCustomized(const QString& theme); + void clearCustomized(const QString& themeRoot); + void setDesktopTheme(QString themeRoot); + +private Q_SLOTS: + void cleanup(); + void themeSelectionChanged(const QItemSelection newSelection, const QItemSelection oldSelection); + +private: + ThemeModel* m_themeModel; + + QHash m_items; // theme items + QHash m_itemPaths; // theme item paths + QHash m_itemIcons; //theme item icons + QHash m_themes; // installed themes + QHash m_themeRoots; // installed themes root paths + QHash m_itemThemeReplacements; // source theme for item replacements + QHashm_itemFileReplacements; //non-theme source files for item replacements + + bool m_themeCustomized; + QString m_baseTheme; +}; + +#endif // DESKTOPTHEMEDETAILS_H diff --git a/kcms/desktoptheme/kcmdesktoptheme.cpp b/kcms/desktoptheme/kcmdesktoptheme.cpp new file mode 100644 index 0000000000..1d82ef16a3 --- /dev/null +++ b/kcms/desktoptheme/kcmdesktoptheme.cpp @@ -0,0 +1,260 @@ +/* + * KCMDesktopTheme + * Copyright (C) 2002 Karol Szwed + * Copyright (C) 2002 Daniel Molkentin + * Copyright (C) 2007 Urs Wolfer + * Copyright (C) 2009 by Davide Bettio + + * Portions Copyright (C) 2007 Paolo Capriotti + * Portions Copyright (C) 2007 Ivan Cukic + * Portions Copyright (C) 2008 by Petri Damsten + * Portions Copyright (C) 2000 TrollTech AS. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 "kcmdesktoptheme.h" + +#include "thememodel.h" + +#include + +#include +#include +#include +#include +#include + +#include + +/**** DLL Interface for kcontrol ****/ + +#include +#include + +K_PLUGIN_FACTORY_WITH_JSON(KCMDesktopThemeFactory, "desktoptheme.json", registerPlugin();) + + +KCMDesktopTheme::KCMDesktopTheme( QWidget* parent, const QVariantList& ) + : KCModule( parent ) + , m_dialog(0) + , m_installProcess(0) + , m_defaultTheme(new Plasma::Theme(this)) +{ + setQuickHelp( i18n("

    Desktop Theme

    " + "This module allows you to modify the visual appearance " + "of the desktop.")); + + setupUi(this); + + m_bDesktopThemeDirty = false; + m_bDetailsDirty = false; + + KAutostart plasmaNetbookAutoStart("plasma-netbook"); + m_isNetbook = plasmaNetbookAutoStart.autostarts(); + + KGlobal::dirs()->addResourceType("themes", "data", "kstyle/themes"); + + KAboutData *about = + new KAboutData( I18N_NOOP("KCMDesktopTheme"), 0, + i18n("KDE Desktop Theme Module"), + 0, QString(), KAboutData::License_GPL, + i18n("(c) 2002 Karol Szwed, Daniel Molkentin")); + + about->addAuthor(i18n("Karol Szwed"), QString(), QStringLiteral("gallium@kde.org")); + about->addAuthor(i18n("Daniel Molkentin"), QString(), QStringLiteral("molkentin@kde.org")); + about->addAuthor(i18n("Ralf Nolden"), QString(), QStringLiteral("nolden@kde.org")); + setAboutData( about ); + + m_newThemeButton->setIcon(QIcon::fromTheme("get-hot-new-stuff")); + + m_themeModel = new ThemeModel(this); + m_theme->setModel(m_themeModel); + m_theme->setItemDelegate(new ThemeDelegate(m_theme)); + m_theme->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + + connect(m_detailsWidget, SIGNAL(changed()), this, SLOT(detailChanged())); + + connect(m_theme->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(setDesktopThemeDirty())); + connect(m_newThemeButton, SIGNAL(clicked()), this, SLOT(getNewThemes())); + connect(m_fileInstallButton, &QPushButton::clicked, this, &KCMDesktopTheme::showFileDialog); +} + + +KCMDesktopTheme::~KCMDesktopTheme() +{ +} + +void KCMDesktopTheme::load() +{ + KConfig config( "kdeglobals", KConfig::FullConfig ); + + loadDesktopTheme(); + + m_bDesktopThemeDirty = false; + m_bDetailsDirty = false; + + emit changed( false ); +} + + +void KCMDesktopTheme::save() +{ + qDebug() << "Save!"; + // Don't do anything if we don't need to. + if ( !( m_bDesktopThemeDirty) && !(m_bDetailsDirty) ) + return; + + //Desktop theme + if ( m_bDesktopThemeDirty ) + { + QString theme = m_themeModel->data(m_theme->currentIndex(), ThemeModel::PackageNameRole).toString(); + qDebug() << "theme changed to " << theme; + if (m_isNetbook) { + KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme-plasma-netbook"); + cg.writeEntry("name", theme); + } else { + qDebug() << "m-defaultTheme" << theme; + m_defaultTheme->setThemeName(theme); + } + } + + if (m_bDetailsDirty) + { + m_detailsWidget->save(); + } + + // Clean up + m_bDesktopThemeDirty = false; + m_bDetailsDirty = false; + emit changed( false ); + qDebug() << "saved."; +} + +void KCMDesktopTheme::defaults() +{ + // TODO: reset back to default theme? +} + +void KCMDesktopTheme::setDesktopThemeDirty() +{ + m_bDesktopThemeDirty = true; + emit changed(true); +} + +void KCMDesktopTheme::getNewThemes() +{ + KNS3::DownloadDialog dialog("plasma-themes.knsrc", this); + dialog.exec(); + KNS3::Entry::List entries = dialog.changedEntries(); + + if (entries.size() > 0) { + loadDesktopTheme(); + } +} + +void KCMDesktopTheme::loadDesktopTheme() +{ + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + m_themeModel->reload(); + QString themeName; + KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme"); + themeName = cg.readEntry("name", m_defaultTheme->themeName()); + + m_theme->setCurrentIndex(m_themeModel->indexOf(themeName)); + QApplication::restoreOverrideCursor(); +} + +void KCMDesktopTheme::detailChanged() +{ + m_bDetailsDirty = true; + emit changed(true); +} + +void KCMDesktopTheme::showFileDialog() +{ + if (!m_dialog) { + QUrl baseUrl; + m_dialog = new QFileDialog(m_fileInstallButton, i18n("Open Theme"), + QDir::homePath(), + i18n("Theme Files (*.zip *.tar.gz *.tar.bz2)")); + m_dialog->setFileMode(QFileDialog::ExistingFile); + connect(m_dialog, &QDialog::accepted, this, &KCMDesktopTheme::fileBrowserCompleted); + } + + m_dialog->exec(); + m_dialog->raise(); + m_dialog->activateWindow(); +} + +void KCMDesktopTheme::fileBrowserCompleted() +{ + if (m_dialog && m_dialog->selectedFiles().count() > 0) { + foreach (const QString &file, m_dialog->selectedFiles()) { + qDebug() << "INSTALL Theme file: " << file; + m_newThemeButton->setEnabled(false); + installTheme(file); + } + } +} + +void KCMDesktopTheme::installTheme(const QString &file) +{ + qDebug() << "Installing ... " << file; + + QString program = "plasmapkg2"; + QStringList arguments; + arguments << "-t" << "theme" << "-i" << file; + + if (!m_installProcess) { + qDebug() << program << arguments.join(" "); + QProcess *myProcess = new QProcess(this); + //connect(myProcess, &QProcess::finished, this, &KCMDesktopTheme::installFinished); + connect(myProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(installFinished(int, QProcess::ExitStatus))); + connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(installError(QProcess::ProcessError))); + + myProcess->start(program, arguments); + } else { + qWarning() << "theme install process already running, refusing to install simultaneously"; + } +} + +void KCMDesktopTheme::installFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + //int exitCode = m_installProcess->exitCode(); + if (exitCode == 0) { + qDebug() << "Theme installed successfully :)"; + m_themeModel->reload(); + m_statusLabel->setText(i18n("Theme installed successfully.")); + } else { + qDebug() << "Theme installation failed."; + m_statusLabel->setText(i18n("Theme installation failed. (%1)", exitCode)); + } + m_newThemeButton->setEnabled(true); +} + +void KCMDesktopTheme::installError(QProcess::ProcessError e) +{ + qDebug() << "Theme installation failed. :("; + m_statusLabel->setText(i18n("Theme installation failed.")); + m_newThemeButton->setEnabled(true); + +} + + +#include "kcmdesktoptheme.moc" + +// vim: set noet ts=4: diff --git a/kcms/desktoptheme/kcmdesktoptheme.h b/kcms/desktoptheme/kcmdesktoptheme.h new file mode 100644 index 0000000000..ad32b4a585 --- /dev/null +++ b/kcms/desktoptheme/kcmdesktoptheme.h @@ -0,0 +1,90 @@ +/* + * KCMDesktopTheme + * Copyright (C) 2002 Karol Szwed + * Copyright (C) 2002 Daniel Molkentin + * Copyright (C) 2007 Urs Wolfer + * + * Portions Copyright (C) TrollTech AS. + * + * Based on kcmstyle which is based on kcmdisplay + * Copyright (C) 1997-2002 kcmdisplay Authors. + * (see Help -> About Style Settings) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 KCMDESKTOPTHEME_H +#define KCMDESKTOPTHEME_H + +#include + + +#include "ui_DesktopTheme.h" + +#include + +class QFileDialog; +class ThemeModel; + +namespace Plasma +{ + class Theme; +} + +class KCMDesktopTheme : public KCModule, public Ui::DesktopTheme +{ + Q_OBJECT + +public: + KCMDesktopTheme( QWidget* parent, const QVariantList& ); + ~KCMDesktopTheme(); + + virtual void load(); + virtual void save(); + virtual void defaults(); + +protected Q_SLOTS: + void loadDesktopTheme(); + + void setDesktopThemeDirty(); + + void getNewThemes(); + + void detailChanged(); + void installFinished(int exitCode, QProcess::ExitStatus exitStatus); + void installError(QProcess::ProcessError e); + +private: + static QString toolbarButtonText(int index); + static int toolbarButtonIndex(const QString &text); + + bool m_bDesktopThemeDirty; + bool m_bDetailsDirty; + + void showFileDialog(); + QFileDialog *m_dialog; + void installTheme(const QString &file); + void fileBrowserCompleted(); + + ThemeModel* m_themeModel; + Plasma::Theme *m_defaultTheme; + QProcess *m_installProcess; + + bool m_isNetbook; +}; + +#endif // KCMDESKTOPTHEME_H + +// vim: set noet ts=4: diff --git a/kcms/desktoptheme/plasma-themes.knsrc b/kcms/desktoptheme/plasma-themes.knsrc new file mode 100644 index 0000000000..6f85777a5c --- /dev/null +++ b/kcms/desktoptheme/plasma-themes.knsrc @@ -0,0 +1,6 @@ +[KNewStuff3] +ProvidersUrl=http://download.kde.org/ocs/providers.xml +Categories=Plasma Theme +StandardResource=tmp +InstallationCommand=plasmapkg2 -t theme -i %f +UninstallCommand=plasmapkg2 -t theme -r %f diff --git a/kcms/desktoptheme/thememodel.cpp b/kcms/desktoptheme/thememodel.cpp new file mode 100644 index 0000000000..e712489bbb --- /dev/null +++ b/kcms/desktoptheme/thememodel.cpp @@ -0,0 +1,224 @@ +/* + * ThemeModel + * Copyright (C) 2002 Karol Szwed + * Copyright (C) 2002 Daniel Molkentin + * Copyright (C) 2007 Urs Wolfer + * Copyright (C) 2009 by Davide Bettio + + * Portions Copyright (C) 2007 Paolo Capriotti + * Portions Copyright (C) 2007 Ivan Cukic + * Portions Copyright (C) 2008 by Petri Damsten + * Portions Copyright (C) 2000 TrollTech AS. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 "thememodel.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +ThemeModel::ThemeModel( QObject *parent ) +: QAbstractListModel( parent ) +{ + reload(); +} + +ThemeModel::~ThemeModel() +{ + clearThemeList(); +} + +void ThemeModel::clearThemeList() +{ + foreach (const ThemeInfo& themeInfo, m_themes) { + delete themeInfo.svg; + } + m_themes.clear(); +} + +void ThemeModel::reload() +{ + reset(); + clearThemeList(); + + // get all desktop themes + QStringList themes; + const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "desktoptheme", QStandardPaths::LocateDirectory); + foreach (const QString &ppath, packs) { + const QDir cd(ppath); + const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden); + foreach (const QString pack, entries) { + const QString _metadata = ppath+QLatin1Char('/')+pack+QStringLiteral("/metadata.desktop"); + if ((pack != "." && pack != "..") && + (QFile::exists(_metadata))) { + themes << _metadata; + } + } + } + + foreach (const QString &theme, themes) { + int themeSepIndex = theme.lastIndexOf('/', -1); + QString themeRoot = theme.left(themeSepIndex); + int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); + QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); + + KDesktopFile df(theme); + + if (df.noDisplay()) { + continue; + } + + QString name = df.readName(); + if (name.isEmpty()) { + name = packageName; + } + const QString comment = df.readComment(); + const QString author = df.desktopGroup().readEntry("X-KDE-PluginInfo-Author",QString()); + const QString version = df.desktopGroup().readEntry("X-KDE-PluginInfo-Version",QString()); + + + Plasma::FrameSvg *svg = new Plasma::FrameSvg(this); + const QString svgFile = themeRoot + QStringLiteral("/widgets/background.svg"); + if (QFile::exists(svgFile)) { + svg->setImagePath(svgFile); + } else { + svg->setImagePath(svgFile + "z"); + } + svg->setEnabledBorders(Plasma::FrameSvg::AllBorders); + ThemeInfo info; + info.package = packageName; + info.description = comment; + info.author = author; + info.version = version; + info.svg = svg; + info.themeRoot = themeRoot; + m_themes[name] = info; + } + + beginInsertRows(QModelIndex(), 0, m_themes.size()); + endInsertRows(); +} + +int ThemeModel::rowCount(const QModelIndex &) const +{ + return m_themes.size(); +} + +QVariant ThemeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (index.row() >= m_themes.size()) { + return QVariant(); + } + + QMap::const_iterator it = m_themes.constBegin(); + for (int i = 0; i < index.row(); ++i) { + ++it; + } + + switch (role) { + case Qt::DisplayRole: + return it.key(); + case PackageNameRole: + return (*it).package; + case SvgRole: + return qVariantFromValue((void*)(*it).svg); + case PackageDescriptionRole: + return (*it).description; + case PackageAuthorRole: + return (*it).author; + case PackageVersionRole: + return (*it).version; + default: + return QVariant(); + } +} + +QModelIndex ThemeModel::indexOf(const QString &name) const +{ + QMapIterator it(m_themes); + int i = -1; + while (it.hasNext()) { + ++i; + if (it.next().value().package == name) { + return index(i, 0); + } + } + + return QModelIndex(); +} + +ThemeDelegate::ThemeDelegate(QObject* parent) +: QAbstractItemDelegate(parent) +{ +} + +void ThemeDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QString title = index.model()->data(index, Qt::DisplayRole).toString(); + QString package = index.model()->data(index, ThemeModel::PackageNameRole).toString(); + + QStyleOptionViewItemV4 opt(option); + QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); + style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); + + // draw image + Plasma::FrameSvg *svg = static_cast( + index.model()->data(index, ThemeModel::SvgRole).value()); + svg->resizeFrame(QSize(option.rect.width() - (2 * MARGIN), 100 - (2 * MARGIN))); + QRect imgRect = QRect(option.rect.topLeft(), + QSize(option.rect.width() - (2 * MARGIN), 100 - (2 * MARGIN))) + .translated(MARGIN, MARGIN); + svg->paintFrame(painter, QPoint(option.rect.left() + MARGIN, option.rect.top() + MARGIN)); + + // draw text + painter->save(); + QFont font = painter->font(); + //font.setWeight(QFont::Bold); + const QString colorFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "desktoptheme/" + package + "/colors"); + if (!colorFile.isEmpty()) { + KSharedConfigPtr colors = KSharedConfig::openConfig(colorFile); + KColorScheme colorScheme(QPalette::Active, KColorScheme::Window, colors); + painter->setPen(colorScheme.foreground(KColorScheme::NormalText).color()); + } + painter->setFont(font); + painter->drawText(option.rect, Qt::AlignCenter | Qt::TextWordWrap, title); + painter->restore(); +} + +QSize ThemeDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const +{ + return QSize(152, 100); +} + + diff --git a/kcms/desktoptheme/thememodel.h b/kcms/desktoptheme/thememodel.h new file mode 100644 index 0000000000..bf0d9ebcc7 --- /dev/null +++ b/kcms/desktoptheme/thememodel.h @@ -0,0 +1,87 @@ +/* + * ThemeModel + * Copyright (C) 2002 Karol Szwed + * Copyright (C) 2002 Daniel Molkentin + * Copyright (C) 2007 Urs Wolfer + * Copyright (C) 2009 by Davide Bettio + + * Portions Copyright (C) 2007 Paolo Capriotti + * Portions Copyright (C) 2007 Ivan Cukic + * Portions Copyright (C) 2008 by Petri Damsten + * Portions Copyright (C) 2000 TrollTech AS. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 THEMEMODEL_H +#define THEMEMODEL_H + +#include + +namespace Plasma +{ + class FrameSvg; +} + +//Theme selector code by Andre Duffeck (modified to add package description) +class ThemeInfo +{ +public: + QString package; + Plasma::FrameSvg *svg; + QString description; + QString author; + QString version; + QString themeRoot; +}; + +class ThemeModel : public QAbstractListModel +{ +public: + enum { PackageNameRole = Qt::UserRole, + SvgRole = Qt::UserRole + 1, + PackageDescriptionRole = Qt::UserRole + 2, + PackageAuthorRole = Qt::UserRole + 3, + PackageVersionRole = Qt::UserRole + 4 + }; + + ThemeModel(QObject *parent = 0); + virtual ~ThemeModel(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QModelIndex indexOf(const QString &path) const; + void reload(); + void clearThemeList(); +private: + QMap m_themes; +}; + +class ThemeDelegate : public QAbstractItemDelegate +{ +public: + ThemeDelegate(QObject * parent = 0); + + virtual void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const; +private: + static const int MARGIN = 10; +}; + + +#endif diff --git a/kcms/fonts/CMakeLists.txt b/kcms/fonts/CMakeLists.txt new file mode 100644 index 0000000000..f1a800a68f --- /dev/null +++ b/kcms/fonts/CMakeLists.txt @@ -0,0 +1,37 @@ +if(FONTCONFIG_FOUND) + include_directories(${FONTCONFIG_INCLUDE_DIR}) +endif() +include_directories(${FREETYPE_INCLUDE_DIRS}) + +########### next target ############### + +set(kcm_fonts_PART_SRCS ../krdb/krdb.cpp fonts.cpp) + +if(X11_FOUND) + set(kcm_fonts_PART_SRCS ${kcm_fonts_PART_SRCS} ${libkxftconfig_SRCS}) +endif() + +set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) +qt5_add_dbus_interface(kcm_fonts_PART_SRCS ${klauncher_xml} klauncher_iface) + +add_library(kcm_fonts MODULE ${kcm_fonts_PART_SRCS}) + + +target_link_libraries(kcm_fonts Qt5::DBus Qt5::Xml KF5::KCMUtils KF5::I18n KF5::KDE4Support ${FREETYPE_LIBRARIES}) + +if(X11_FOUND) + set_target_properties(kcm_fonts PROPERTIES COMPILE_FLAGS -DHAVE_X11=1) + target_link_libraries(kcm_fonts Qt5::X11Extras) + if(FONTCONFIG_FOUND) + target_link_libraries(kcm_fonts ${FONTCONFIG_LIBRARIES}) + endif() + + target_link_libraries(kcm_fonts ${X11_LIBRARIES}) +endif() + +install(TARGETS kcm_fonts DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES fonts.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/kcms/fonts/Messages.sh b/kcms/fonts/Messages.sh new file mode 100644 index 0000000000..c49832c6a0 --- /dev/null +++ b/kcms/fonts/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kcmfonts.pot diff --git a/kcms/fonts/fonts.cpp b/kcms/fonts/fonts.cpp new file mode 100644 index 0000000000..974776146f --- /dev/null +++ b/kcms/fonts/fonts.cpp @@ -0,0 +1,850 @@ +// KDE Display fonts setup tab +// +// Copyright (c) Mark Donohoe 1997 +// lars Knoll 1999 +// Rik Hemsley 2000 +// +// Ported to kcontrol2 by Geert Jansen. + +#include + +#include "fonts.h" + +#include + +#include +#include +#include +#include +#include +#include + +//Added by qt3to4: +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../krdb/krdb.h" + +#ifdef HAVE_FREETYPE +#include +#ifdef FT_LCD_FILTER_H +#include FT_FREETYPE_H +#include FT_LCD_FILTER_H +#endif +#endif + +#if HAVE_X11 +#include +#endif + +#if HAVE_X11 +// X11 headers +#undef Bool +#undef Unsorted +#undef None +#endif + +static const char * const aa_rgb_xpm[]={ +"12 12 3 1", +"a c #0000ff", +"# c #00ff00", +". c #ff0000", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa"}; +static const char * const aa_bgr_xpm[]={ +"12 12 3 1", +". c #0000ff", +"# c #00ff00", +"a c #ff0000", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa", +"....####aaaa"}; +static const char * const aa_vrgb_xpm[]={ +"12 12 3 1", +"a c #0000ff", +"# c #00ff00", +". c #ff0000", +"............", +"............", +"............", +"............", +"############", +"############", +"############", +"############", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa"}; +static const char * const aa_vbgr_xpm[]={ +"12 12 3 1", +". c #0000ff", +"# c #00ff00", +"a c #ff0000", +"............", +"............", +"............", +"............", +"############", +"############", +"############", +"############", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa", +"aaaaaaaaaaaa"}; + +static const char* const * const aaPixmaps[]={ aa_rgb_xpm, aa_bgr_xpm, aa_vrgb_xpm, aa_vbgr_xpm }; + +/**** DLL Interface ****/ +K_PLUGIN_FACTORY(FontFactory, registerPlugin(); ) + +/**** FontUseItem ****/ + +FontUseItem::FontUseItem( + QWidget * parent, + const QString &name, + const QString &grp, + const QString &key, + const QString &rc, + const QFont &default_fnt, + bool f +) + : KFontRequester(parent, f), + _rcfile(rc), + _rcgroup(grp), + _rckey(key), + _default(default_fnt) +{ + KAcceleratorManager::setNoAccel( this ); + setTitle( name ); + readFont(); +} + +void FontUseItem::setDefault() +{ + setFont( _default, isFixedOnly() ); +} + +void FontUseItem::readFont() +{ + KConfig *config; + + bool deleteme = false; + if (_rcfile.isEmpty()) + config = KSharedConfig::openConfig().data(); + else + { + config = new KConfig(_rcfile); + deleteme = true; + } + + KConfigGroup group(config, _rcgroup); + QFont tmpFnt(_default); + setFont( group.readEntry(_rckey, tmpFnt), isFixedOnly() ); + if (deleteme) delete config; +} + +void FontUseItem::writeFont() +{ + KConfig *config; + + if (_rcfile.isEmpty()) { + config = KSharedConfig::openConfig().data(); + KConfigGroup(config, _rcgroup).writeEntry(_rckey, font(), KConfig::Normal|KConfig::Global); + } else { + config = new KConfig(KStandardDirs::locateLocal("config", _rcfile)); + KConfigGroup(config, _rcgroup).writeEntry(_rckey, font()); + config->sync(); + delete config; + } +} + +void FontUseItem::applyFontDiff( const QFont &fnt, int fontDiffFlags ) +{ + QFont _font( font() ); + + if (fontDiffFlags & KFontChooser::FontDiffSize) { + _font.setPointSizeF( fnt.pointSizeF() ); + } + if (fontDiffFlags & KFontChooser::FontDiffFamily) { + if (!isFixedOnly() || QFontInfo(fnt).fixedPitch()) _font.setFamily( fnt.family() ); + } + if (fontDiffFlags & KFontChooser::FontDiffStyle) { + _font.setWeight( fnt.weight() ); + _font.setStyle( fnt.style() ); + _font.setUnderline( fnt.underline() ); +#if QT_VERSION >= 0x040800 + _font.setStyleName( fnt.styleName() ); +#endif + } + + setFont( _font, isFixedOnly() ); +} + +/**** FontAASettings ****/ +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) +FontAASettings::FontAASettings(QWidget *parent) + : KDialog( parent ), + changesMade(false) +{ + setObjectName( "FontAASettings" ); + setModal( true ); + setCaption( i18n("Configure Anti-Alias Settings") ); + setButtons( Ok|Cancel ); + + QWidget *mw=new QWidget(this); + QFormLayout *layout=new QFormLayout(mw); + layout->setVerticalSpacing(0); + layout->setMargin(0); + + excludeRange=new QCheckBox(i18n("E&xclude range:"), mw); + QHBoxLayout *rangeLayout = new QHBoxLayout(); + excludeFrom=new KDoubleNumInput(0, 72, 8.0, mw, 1, 1); + excludeFrom->setSuffix(i18n(" pt")); + rangeLayout->addWidget(excludeFrom); + excludeToLabel=new QLabel(i18n(" to "), mw); + rangeLayout->addWidget(excludeToLabel); + excludeTo=new KDoubleNumInput(0, 72, 15.0, mw, 1, 1); + excludeTo->setSuffix(i18n(" pt")); + rangeLayout->addWidget(excludeTo); + layout->addRow(excludeRange, rangeLayout); + + QString subPixelWhatsThis = i18n("

    If you have a TFT or LCD screen you" + " can further improve the quality of displayed fonts by selecting" + " this option.
    Sub-pixel rendering is also known as ClearType(tm).
    " + " In order for sub-pixel rendering to" + " work correctly you need to know how the sub-pixels of your display" + " are aligned.

    " + "

    On TFT or LCD displays a single pixel is actually composed of" + " three sub-pixels, red, green and blue. Most displays" + " have a linear ordering of RGB sub-pixel, some have BGR.
    " + " This feature does not work with CRT monitors.

    " ); + + useSubPixel=new QCheckBox(i18n("&Use sub-pixel rendering:"), mw); + useSubPixel->setWhatsThis( subPixelWhatsThis ); + + subPixelType=new QComboBox(mw); + layout->addRow(useSubPixel, subPixelType); + + subPixelType->setEditable(false); + subPixelType->setWhatsThis( subPixelWhatsThis ); + + for(int t=KXftConfig::SubPixel::None+1; t<=KXftConfig::SubPixel::Vbgr; ++t) + subPixelType->addItem(QPixmap(aaPixmaps[t-1]), i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8())); + + QLabel *hintingLabel=new QLabel(i18n("Hinting style: "), mw); + hintingStyle=new QComboBox(mw); + hintingStyle->setEditable(false); + layout->addRow(hintingLabel, hintingStyle); + for(int s=KXftConfig::Hint::NotSet+1; s<=KXftConfig::Hint::Full; ++s) + hintingStyle->addItem(i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8())); + + QString hintingText(i18n("Hinting is a process used to enhance the quality of fonts at small sizes.")); + hintingStyle->setWhatsThis( hintingText); + hintingLabel->setWhatsThis( hintingText); + load(); + enableWidgets(); + setMainWidget(mw); + + connect(excludeRange, SIGNAL(toggled(bool)), SLOT(changed())); + connect(useSubPixel, SIGNAL(toggled(bool)), SLOT(changed())); + connect(excludeFrom, SIGNAL(valueChanged(double)), SLOT(changed())); + connect(excludeTo, SIGNAL(valueChanged(double)), SLOT(changed())); + connect(subPixelType, SIGNAL(activated(QString)), SLOT(changed())); + connect(hintingStyle, SIGNAL(activated(QString)), SLOT(changed())); +} + +bool FontAASettings::load() +{ + double from, to; + KXftConfig xft; + + if(xft.getExcludeRange(from, to)) + excludeRange->setChecked(true); + else + { + excludeRange->setChecked(false); + from=8.0; + to=15.0; + } + + excludeFrom->setValue(from); + excludeTo->setValue(to); + + KXftConfig::SubPixel::Type spType; + + if(!xft.getSubPixelType(spType) || KXftConfig::SubPixel::None==spType) + useSubPixel->setChecked(false); + else + { + int idx=getIndex(spType); + + if(idx>-1) + { + useSubPixel->setChecked(true); + subPixelType->setCurrentIndex(idx); + } + else + useSubPixel->setChecked(false); + } + + KXftConfig::Hint::Style hStyle; + + if(!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet==hStyle) + { + KConfig kglobals("kdeglobals", KConfig::NoGlobals); + + hStyle=KXftConfig::Hint::Medium; + xft.setHintStyle(hStyle); + xft.apply(); // Save this setting + KConfigGroup(&kglobals, "General").writeEntry("XftHintStyle", KXftConfig::toStr(hStyle)); + kglobals.sync(); + runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); + } + + hintingStyle->setCurrentIndex(getIndex(hStyle)); + + enableWidgets(); + + return xft.getAntiAliasing(); +} + +bool FontAASettings::save( bool useAA ) +{ + KXftConfig xft; + KConfig kglobals("kdeglobals", KConfig::NoGlobals); + KConfigGroup grp(&kglobals, "General"); + + xft.setAntiAliasing( useAA ); + + if(excludeRange->isChecked()) + xft.setExcludeRange(excludeFrom->value(), excludeTo->value()); + else + xft.setExcludeRange(0, 0); + + KXftConfig::SubPixel::Type spType(useSubPixel->isChecked() + ? getSubPixelType() + : KXftConfig::SubPixel::None); + + xft.setSubPixelType(spType); + grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType)); + grp.writeEntry("XftAntialias", useAA); + + bool mod=false; + KXftConfig::Hint::Style hStyle(getHintStyle()); + + xft.setHintStyle(hStyle); + + QString hs(KXftConfig::toStr(hStyle)); + + if(!hs.isEmpty() && hs!=grp.readEntry("XftHintStyle")) + { + grp.writeEntry("XftHintStyle", hs); + mod=true; + } + kglobals.sync(); + + if(!mod) + mod=xft.changed(); + + xft.apply(); + + return mod; +} + +void FontAASettings::defaults() +{ + excludeRange->setChecked(true); + excludeFrom->setValue(8.0); + excludeTo->setValue(15.0); + useSubPixel->setChecked(false); + hintingStyle->setCurrentIndex(getIndex(KXftConfig::Hint::Medium)); + enableWidgets(); +} + +int FontAASettings::getIndex(KXftConfig::SubPixel::Type spType) +{ + int pos=-1; + int index; + + for(index=0; indexcount(); ++index) + if(subPixelType->itemText(index)==i18n(KXftConfig::description(spType).toUtf8())) + { + pos=index; + break; + } + + return pos; +} + +KXftConfig::SubPixel::Type FontAASettings::getSubPixelType() +{ + int t; + + for(t=KXftConfig::SubPixel::None; t<=KXftConfig::SubPixel::Vbgr; ++t) + if(subPixelType->currentText()==i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8())) + return (KXftConfig::SubPixel::Type)t; + + return KXftConfig::SubPixel::None; +} + +int FontAASettings::getIndex(KXftConfig::Hint::Style hStyle) +{ + int pos=-1; + int index; + + for(index=0; indexcount(); ++index) + if(hintingStyle->itemText(index)==i18n(KXftConfig::description(hStyle).toUtf8())) + { + pos=index; + break; + } + + return pos; +} + + +KXftConfig::Hint::Style FontAASettings::getHintStyle() +{ + int s; + + for(s=KXftConfig::Hint::NotSet; s<=KXftConfig::Hint::Full; ++s) + if(hintingStyle->currentText()==i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8())) + return (KXftConfig::Hint::Style)s; + + return KXftConfig::Hint::Medium; +} + +void FontAASettings::enableWidgets() +{ + excludeFrom->setEnabled(excludeRange->isChecked()); + excludeTo->setEnabled(excludeRange->isChecked()); + excludeToLabel->setEnabled(excludeRange->isChecked()); + subPixelType->setEnabled(useSubPixel->isChecked()); +#ifdef FT_LCD_FILTER_H + static int ft_has_subpixel = -1; + if( ft_has_subpixel == -1 ) { + FT_Library ftLibrary; + if(FT_Init_FreeType(&ftLibrary) == 0) { + ft_has_subpixel = ( FT_Library_SetLcdFilter(ftLibrary, FT_LCD_FILTER_DEFAULT ) + == FT_Err_Unimplemented_Feature ) ? 0 : 1; + FT_Done_FreeType(ftLibrary); + } + } + useSubPixel->setEnabled(ft_has_subpixel); + subPixelType->setEnabled(ft_has_subpixel); +#endif +} +#endif + +void FontAASettings::changed() +{ +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + changesMade=true; + enableWidgets(); +#endif +} + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) +int FontAASettings::exec() +{ + int i=KDialog::exec(); + + if(!i) + load(); // Reset settings... + + return i && changesMade; +} +#endif + +/**** KFonts ****/ + +KFonts::KFonts(QWidget *parent, const QVariantList &args) + : KCModule(parent, args) +{ + QStringList nameGroupKeyRc; + + nameGroupKeyRc + << i18nc("font usage", "General") << "General" << "font" << "" + << i18nc("font usage", "Fixed width") << "General" << "fixed" << "" + << i18nc("font usage", "Small") << "General" << "smallestReadableFont" << "" + << i18nc("font usage", "Toolbar") << "General" << "toolBarFont" << "" + << i18nc("font usage", "Menu") << "General" << "menuFont" << "" + << i18nc("font usage", "Window title") << "WM" << "activeFont" << "" + << i18nc("font usage", "Taskbar") << "General" << "taskbarFont" << "" + << i18nc("font usage", "Desktop") << "General" << "desktopFont" << ""; + + QList defaultFontList; + + // NOTE: keep in sync with kdelibs/kdeui/kernel/kglobalsettings.cpp + +#ifdef Q_WS_MAC + QFont f0("Lucida Grande", 13); // general/menu/desktop + QFont f1("Monaco", 10); + QFont f2("Lucida Grande", 11); // toolbar +#elif defined(Q_WS_MAEMO_5) || defined(MEEGO_EDITION_HARMATTAN) + QFont f0("Sans Serif", 16); // general/menu/desktop + QFont f1("Monospace", 16; + QFont f2("Sans Serif", 16); // toolbar +#else + QFont f0("Sans Serif", 9); // general/menu/desktop + QFont f1("Monospace", 9); + QFont f2("Sans Serif", 8); // toolbar +#endif + QFont f3("Sans Serif", 8); // window title + QFont f4("Sans Serif", 9); // taskbar + QFont f5("Sans Serif", 8); // smallestReadableFont + + defaultFontList << f0 << f1 << f5 << f2 << f0 << f3 << f4 << f0; + + QList fixedList; + + fixedList + << false + << true + << false + << false + << false + << false + << false + << false; + + QStringList quickHelpList; + + quickHelpList + << i18n("Used for normal text (e.g. button labels, list items).") + << i18n("A non-proportional font (i.e. typewriter font).") + << i18n("Smallest font that is still readable well.") + << i18n("Used to display text beside toolbar icons.") + << i18n("Used by menu bars and popup menus.") + << i18n("Used by the window titlebar.") + << i18n("Used by the taskbar.") + << i18n("Used for desktop icons."); + + QVBoxLayout * layout = new QVBoxLayout(this ); + layout->setMargin(0); + + QGridLayout * fontUseLayout = new QGridLayout( ); + layout->addLayout( fontUseLayout ); + fontUseLayout->setColumnStretch(0, 0); + fontUseLayout->setColumnStretch(1, 1); + fontUseLayout->setColumnStretch(2, 0); + + QList::ConstIterator defaultFontIt(defaultFontList.begin()); + QList::ConstIterator fixedListIt(fixedList.begin()); + QStringList::ConstIterator quickHelpIt(quickHelpList.begin()); + QStringList::ConstIterator it(nameGroupKeyRc.begin()); + + unsigned int count = 0; + + while (it != nameGroupKeyRc.constEnd()) { + + QString name = *it; it++; + QString group = *it; it++; + QString key = *it; it++; + QString file = *it; it++; + + FontUseItem * i = + new FontUseItem( + this, + name, + group, + key, + file, + *defaultFontIt++, + *fixedListIt++ + ); + + fontUseList.append(i); + connect(i, SIGNAL(fontSelected(QFont)), SLOT(fontSelected())); + + QLabel * fontUse = new QLabel(i18nc("Font role", "%1: ", name), this); + fontUse->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + fontUse->setWhatsThis( *quickHelpIt++); + + fontUseLayout->addWidget(fontUse, count, 0); + fontUseLayout->addWidget(i, count, 1); + + ++count; + } + + QHBoxLayout *hblay = new QHBoxLayout(); + layout->addLayout(hblay); + hblay->addStretch(); + QPushButton * fontAdjustButton = new QPushButton(i18n("Ad&just All Fonts..."), this); + fontAdjustButton->setWhatsThis( i18n("Click to change all fonts")); + hblay->addWidget( fontAdjustButton ); + connect(fontAdjustButton, SIGNAL(clicked()), SLOT(slotApplyFontDiff())); + + layout->addSpacing(KDialog::spacingHint()); + + QGridLayout* lay = new QGridLayout(); + layout->addLayout(lay); + lay->setColumnStretch( 3, 10 ); +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + QLabel* label=0L; + label = new QLabel( i18n( "Use a&nti-aliasing:" ), this ); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + lay->addWidget( label, 0, 0 ); + cbAA = new QComboBox( this ); + cbAA->insertItem( AAEnabled, i18nc( "Use anti-aliasing", "Enabled" )); // change AASetting type if order changes + cbAA->insertItem( AASystem, i18nc( "Use anti-aliasing", "System Settings" )); + cbAA->insertItem( AADisabled, i18nc( "Use anti-aliasing", "Disabled" )); + cbAA->setWhatsThis( i18n("If this option is selected, KDE will smooth the edges of curves in " + "fonts.")); + aaSettingsButton = new QPushButton( i18n( "Configure..." ), this); + connect(aaSettingsButton, SIGNAL(clicked()), SLOT(slotCfgAa())); + label->setBuddy( cbAA ); + lay->addWidget( cbAA, 0, 1 ); + lay->addWidget( aaSettingsButton, 0, 2 ); + connect(cbAA, SIGNAL(activated(int)), SLOT(slotUseAntiAliasing())); +#endif +#if HAVE_X11 + checkboxForceDpi = new QCheckBox( i18n( "Force fonts DPI:" ), this ); + lay->addWidget( checkboxForceDpi, 1, 0 ); + spinboxDpi = new QSpinBox( this ); + spinboxDpi->setRange(1, 1000); + spinboxDpi->setSingleStep(24); // The common DPI values 72, 96 and 120 are multiples of 24 + QString whatsthis = i18n( + "

    This option forces a specific DPI value for fonts. It may be useful" + " when the real DPI of the hardware is not detected properly and it" + " is also often misused when poor quality fonts are used that do not" + " look well with DPI values other than 96 or 120 DPI.

    " + "

    The use of this option is generally discouraged. For selecting proper DPI" + " value a better option is explicitly configuring it for the whole X server if" + " possible (e.g. DisplaySize in xorg.conf or adding -dpi value to" + " ServerLocalArgs= in $KDEDIR/share/config/kdm/kdmrc). When fonts do not render" + " properly with real DPI value better fonts should be used or configuration" + " of font hinting should be checked.

    " ); + spinboxDpi->setWhatsThis(whatsthis); + checkboxForceDpi->setChecked(false); + spinboxDpi->setEnabled(false); + connect( spinboxDpi, SIGNAL( valueChanged(int)), SLOT( changed())); + connect( checkboxForceDpi, SIGNAL( toggled(bool)), SLOT( changed())); + connect( checkboxForceDpi, SIGNAL( toggled(bool)), spinboxDpi, SLOT( setEnabled(bool))); + lay->addWidget( spinboxDpi, 1, 1 ); +#endif + layout->addStretch(1); + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + aaSettings=new FontAASettings(this); +#endif + +} + +KFonts::~KFonts() +{ + QList::Iterator it(fontUseList.begin()), + end(fontUseList.end()); + + for(; it!=end; ++it) + delete (*it); + fontUseList.clear(); +} + +void KFonts::fontSelected() +{ + emit changed(true); +} + +void KFonts::defaults() +{ + for ( int i = 0; i < (int) fontUseList.count(); i++ ) + fontUseList.at( i )->setDefault(); + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + useAA = AASystem; + cbAA->setCurrentIndex( useAA ); + aaSettings->defaults(); +#endif +#if HAVE_X11 + checkboxForceDpi->setChecked( false ); + spinboxDpi->setValue( 96 ); +#endif + emit changed(true); +} + +void KFonts::load() +{ + QList::Iterator it(fontUseList.begin()), + end(fontUseList.end()); + + for(; it!=end; ++it) + (*it)->readFont(); + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + useAA_original = useAA = aaSettings->load() ? AAEnabled : AADisabled; + cbAA->setCurrentIndex( useAA ); +#endif + + KConfig _cfgfonts( "kcmfonts" ); + KConfigGroup cfgfonts(&_cfgfonts, "General"); +#if HAVE_X11 + int dpicfg = cfgfonts.readEntry( "forceFontDPI", 0 ); + if (dpicfg <= 0) { + checkboxForceDpi->setChecked(false); + spinboxDpi->setValue(96); + dpi_original = 0; + } else { + checkboxForceDpi->setChecked(true); + spinboxDpi->setValue(dpicfg); + dpi_original = dpicfg; + }; +#endif +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + if( cfgfonts.readEntry( "dontChangeAASettings", true )) { + useAA_original = useAA = AASystem; + cbAA->setCurrentIndex( useAA ); + } + aaSettingsButton->setEnabled( cbAA->currentIndex() == AAEnabled ); +#endif + + emit changed(false); +} + +void KFonts::save() +{ + QList::Iterator it(fontUseList.begin()), + end(fontUseList.end()); + + for(; it!=end; ++it) + (*it)->writeFont(); + + KSharedConfig::openConfig()->sync(); + + KConfig _cfgfonts( "kcmfonts" ); + KConfigGroup cfgfonts(&_cfgfonts, "General"); +#if HAVE_X11 + int dpi = ( checkboxForceDpi->isChecked() ? spinboxDpi->value() : 0 ); + cfgfonts.writeEntry( "forceFontDPI", dpi ); +#endif +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + cfgfonts.writeEntry( "dontChangeAASettings", cbAA->currentIndex() == AASystem ); +#endif + cfgfonts.sync(); +#if HAVE_X11 + // if the setting is reset in the module, remove the dpi value, + // otherwise don't explicitly remove it and leave any possible system-wide value + if( dpi == 0 && dpi_original != 0 ) { + KProcess proc; + proc << "xrdb" << "-quiet" << "-remove" << "-nocpp"; + proc.start(); + if (proc.waitForStarted()) { + proc.write( QByteArray( "Xft.dpi\n" ) ); + proc.closeWriteChannel(); + proc.waitForFinished(); + } + } +#endif + + KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged); + + kapp->processEvents(); // Process font change ourselves + + + // Don't overwrite global settings unless explicitly asked for - e.g. the system + // fontconfig setup may be much more complex than this module can provide. + // TODO: With AASystem the changes already made by this module should be reverted somehow. +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + bool aaSave = false; + if( cbAA->currentIndex() != AASystem ) + aaSave = aaSettings->save( useAA == AAEnabled ); + + if( aaSave || (useAA != useAA_original) || dpi != dpi_original) { + KMessageBox::information(this, + i18n( + "

    Some changes such as anti-aliasing or DPI will only affect newly started applications.

    " + ), i18n("Font Settings Changed"), "FontSettingsChanged"); + useAA_original = useAA; + dpi_original = dpi; + } +#else +#if HAVE_X11 + if(dpi != dpi_original) { + KMessageBox::information(this, + i18n( + "

    Some changes such as DPI will only affect newly started applications.

    " + ), i18n("Font Settings Changed"), "FontSettingsChanged"); + dpi_original = dpi; + } +#endif +#endif + runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); + + emit changed(false); +} + + +void KFonts::slotApplyFontDiff() +{ + QFont font = QFont(fontUseList.first()->font()); + KFontChooser::FontDiffFlags fontDiffFlags = 0; + int ret = KFontDialog::getFontDiff(font,fontDiffFlags,KFontChooser::NoDisplayFlags,this); + + if (ret == KDialog::Accepted && fontDiffFlags) + { + for ( int i = 0; i < (int) fontUseList.count(); i++ ) + fontUseList.at( i )->applyFontDiff( font,fontDiffFlags ); + emit changed(true); + } +} + +void KFonts::slotUseAntiAliasing() +{ +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + useAA = static_cast< AASetting >( cbAA->currentIndex()); + aaSettingsButton->setEnabled( cbAA->currentIndex() == AAEnabled ); + emit changed(true); +#endif +} + +void KFonts::slotCfgAa() +{ +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + if(aaSettings->exec()) + { + emit changed(true); + } +#endif +} + +#include "fonts.moc" + +// vim:ts=2:sw=2:tw=78 diff --git a/kcms/fonts/fonts.desktop b/kcms/fonts/fonts.desktop new file mode 100644 index 0000000000..2a5a7a7111 --- /dev/null +++ b/kcms/fonts/fonts.desktop @@ -0,0 +1,241 @@ +[Desktop Entry] +Exec=kcmshell5 fonts +Icon=preferences-desktop-font +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/fonts/index.html + +X-KDE-Library=kcm_fonts +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=application-appearance +X-KDE-Weight=80 + +Name=Fonts +Name[af]=Skriftipes +Name[ar]=الخطوط +Name[ast]=Tribes de lletra +Name[be]=Шрыфты +Name[be@latin]=Šryfty +Name[bg]=Шрифтове +Name[bn]=ফন্ট +Name[bn_IN]=ফন্ট +Name[br]=Fontoù +Name[bs]=Fontovi +Name[ca]=Tipus de lletra +Name[ca@valencia]=Tipus de lletra +Name[cs]=Písma +Name[csb]=Fòntë +Name[cy]=Ffontiau +Name[da]=Skrifttyper +Name[de]=Schriftarten +Name[el]=Γραμματοσειρές +Name[en_GB]=Fonts +Name[eo]=Tiparoj +Name[es]=Tipos de letra +Name[et]=Fondid +Name[eu]=Letra-tipoak +Name[fa]=قلمها +Name[fi]=Kirjasimet +Name[fr]=Polices de caractères +Name[fy]=Lettertypen +Name[ga]=Clónna +Name[gl]=Tipos de letra +Name[gu]=ફોન્ટ્સ +Name[he]=גופנים +Name[hi]=फ़ॉन्ट्स +Name[hne]=फोंट +Name[hr]=Fontovi +Name[hsb]=Pisma +Name[hu]=Betűtípusok +Name[ia]=Fontes +Name[id]=Fonta +Name[is]=Letur +Name[it]=Caratteri +Name[ja]=フォント +Name[ka]=ფონტები +Name[kk]=Қаріптер +Name[km]=ពុម្ព​អក្សរ +Name[kn]=ಅಕ್ಷರಶೈಲಿಗಳು +Name[ko]=글꼴 +Name[ku]=Curenivîs +Name[lt]=Šriftai +Name[lv]=Fonti +Name[mai]=फान्ट +Name[mk]=Фонтови +Name[ml]=അക്ഷരസഞ്ചയങ്ങള്‍ +Name[mr]=फॉन्ट +Name[ms]=Fon +Name[nb]=Skrifttype +Name[nds]=Schriftoorden +Name[ne]=फन्ट +Name[nl]=Lettertypen +Name[nn]=Skrifter +Name[oc]=Poliças +Name[or]=ଅକ୍ଷର ରୂପ +Name[pa]=ਫੋਂਟ +Name[pl]=Czcionki +Name[pt]=Tipos de Letra +Name[pt_BR]=Fontes +Name[ro]=Fonturi +Name[ru]=Шрифты +Name[se]=Fonttat +Name[si]=අකුරු +Name[sk]=Písma +Name[sl]=Pisave +Name[sr]=Фонтови +Name[sr@ijekavian]=Фонтови +Name[sr@ijekavianlatin]=Fontovi +Name[sr@latin]=Fontovi +Name[sv]=Teckensnitt +Name[ta]=எழுத்துருக்கள் +Name[te]=ఫాంట్‍స్ +Name[tg]=Ҳарфҳо +Name[th]=แบบอักษรต่างๆ +Name[tr]=Yazı Tipleri +Name[ug]=خەت نۇسخىلىرى +Name[uk]=Шрифти +Name[uz]=Shriftlar +Name[uz@cyrillic]=Шрифтлар +Name[vi]=Phông chữ +Name[wa]=Fontes +Name[xh]=Uhlobo lwamagama +Name[x-test]=xxFontsxx +Name[zh_CN]=字体 +Name[zh_TW]=字型 + +Comment=Font settings +Comment[af]=Skrif tipe instellings +Comment[ar]=إعدادات الخطوط +Comment[ast]=Preferencies de les tribes de lletra +Comment[be]=Настаўленні шрыфтоў +Comment[be@latin]=Nałady šryftoŭ +Comment[bg]=Настройки на системните шрифтове +Comment[bn]=ফন্ট সেটিংস +Comment[bn_IN]=ফন্ট সংক্রান্ত বৈশিষ্ট্য +Comment[br]=Kefluniañ ar fontoù +Comment[bs]=Postavke fonta +Comment[ca]=Arranjament del tipus de lletra +Comment[ca@valencia]=Arranjament del tipus de lletra +Comment[cs]=Nastavení písem +Comment[csb]=Nastôw fòntów +Comment[cy]=Gosodiadau Ffontiau +Comment[da]=Skrifttypeindstillinger +Comment[de]=Schriftarten-Einstellungen +Comment[el]=Ρυθμίσεις γραμματοσειρών +Comment[en_GB]=Font settings +Comment[eo]=Tiparagordo +Comment[es]=Preferencias de los tipos de letra +Comment[et]=Fontide seadistused +Comment[eu]=Letra-tipoen ezarpenak +Comment[fa]=تنظیمات قلم +Comment[fi]=Kirjasinten asetukset +Comment[fr]=Configuration des polices de caractères +Comment[fy]=Lettertypen ynstellings +Comment[ga]=Socruithe na gclónna +Comment[gl]=Configuración dos tipos de letra +Comment[gu]=ફોન્ટ ગોઠવણીઓ +Comment[he]=הגדרות גופנים +Comment[hi]=फ़ॉन्ट्स विन्यास +Comment[hne]=फोंट सेटिंग +Comment[hr]=Postavke fontova +Comment[hsb]=Nastajenja za pisma +Comment[hu]=Betűtípus-beállítások +Comment[ia]=Preferentias de font +Comment[id]=Pengaturan fonta +Comment[is]=Stillingar leturs +Comment[it]=Impostazioni dei caratteri +Comment[ja]=フォントの設定 +Comment[ka]=ფონტების კონფიგურაცია +Comment[kk]=Қаріптерін орнату +Comment[km]=ការ​កំណត់​ពុម្ព​អក្សរ +Comment[kn]=ಅಕ್ಷರಶೈಲಿ ಸಂಯೋಜನೆಗಳು +Comment[ko]=글꼴 설정 +Comment[ku]=Mîhengên curenivîsan +Comment[lt]=Šriftų nustatymai +Comment[lv]=Fontu parametri +Comment[mai]=फान्ट्स बिन्यास +Comment[mk]=Поставувања на фонтовите +Comment[ml]=അക്ഷരസഞ്ചയത്തിന്റെ സജ്ജീകരണങ്ങള്‍ +Comment[mr]=फॉन्ट संयोजना +Comment[ms]=Seting Fon +Comment[nb]=Skriftinnstillinger +Comment[nds]=Schriftoorden instellen +Comment[ne]=फन्ट सेटिङ +Comment[nl]=Lettertypeninstellingen +Comment[nn]=Skriftinnstillingar +Comment[oc]=Paramètres de poliça +Comment[or]=ଅକ୍ଷର ରୂପ ସଂଚଚନା +Comment[pa]=ਫੋਂਟ ਸੈਟਿੰਗ +Comment[pl]=Ustawienia czcionek +Comment[pt]=Configuração dos tipos de letra +Comment[pt_BR]=Configurações das fontes +Comment[ro]=Configurări font +Comment[ru]=Настройка шрифтов +Comment[se]=Fontaheivehusat +Comment[si]=අකුරු සැකසුම් +Comment[sk]=Nastavenie písiem +Comment[sl]=Nastavitve pisav +Comment[sr]=Поставке фонта +Comment[sr@ijekavian]=Поставке фонта +Comment[sr@ijekavianlatin]=Postavke fonta +Comment[sr@latin]=Postavke fonta +Comment[sv]=Anpassa teckensnitt +Comment[ta]=எழுத்துரு அமைப்புகள் +Comment[te]=ఫాంట్ అమరికలు +Comment[tg]=Танзимоти ҳарфҳо +Comment[th]=ตั้งค่าแบบอักษรต่างๆ +Comment[tr]=Yazı tipi ayarları +Comment[ug]=خەت نۇسخا تەڭشەك +Comment[uk]=Налаштування шрифтів +Comment[uz]=Shriftlarni moslash +Comment[uz@cyrillic]=Шрифтларни мослаш +Comment[vi]=Thiết lập phông chữ +Comment[wa]=Apontiaedje des fontes +Comment[xh]=Izicwangciso zohlobo lwamagama +Comment[x-test]=xxFont settingsxx +Comment[zh_CN]=字体设置 +Comment[zh_TW]=字型設定 + +X-KDE-Keywords=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts +X-KDE-Keywords[bs]=slova,veličina slova,stil,znakovi,postaviti znakove,ploča,kontrolna ploča,pozadina,upravitelj datoteka,alatne trake,meni,naslov prozora,naslov,DPI,niskopropusni,slova pozadine,slova na alatnoj traci,obilježja,opći fontovi +X-KDE-Keywords[ca]=tipus de lletres,mida de tipus de lletra,estils,joc de caràcters,jocs de caràcters,plafó,plafó de control,escriptoris,Gestor de fitxers,Barres d'eines,Menú,Títol de finestra,Títol,DPI,antialiàsing,tipus de lletra d'escriptori,tipus de lletra de barra d'eines,caràcter,tipus de lletra general +X-KDE-Keywords[ca@valencia]=tipus de lletres,mida de tipus de lletra,estils,joc de caràcters,jocs de caràcters,plafó,plafó de control,escriptoris,Gestor de fitxers,Barres d'eines,Menú,Títol de finestra,Títol,DPI,antialiàsing,tipus de lletra d'escriptori,tipus de lletra de barra d'eines,caràcter,tipus de lletra general +X-KDE-Keywords[da]=skrifttyper,skriftstørrelse,stile,tegnsæt,panel,kontrolpanel,skriveborde,filhåndtering,værktøjslinjer,menu,vinduestitel,titel,DPI,anti-aliasing,værktøjslinjer,tegn +X-KDE-Keywords[de]=Schriftarten,Schriftgrößen,Stile,Zeichensätze,Kontrollleiste,Stile,Dateiverwaltung,Arbeitsflächen,Werkzeugleisten,Menüs,Fenstertitel,Titel,DPI,Antialiasing,Arbeitsflächeschriften,Werkzeugleistenschriften,Zeichen,Allgemeine Schriftarten +X-KDE-Keywords[el]=γραμματοσειρές,μέγεθος γραμματοσειράς,στιλ,σύνολα χαρακτήρων,πίνακας,πίνακας ελέγχου,επιφάνειες εργασίας,διαχειριστής αρχείων,γραμμές εργαλείων,μενού,τίτλος παραθύρου,τίτλος,DPI,εξομάλυνση,γραμματοσειρές επιφάνειας εργασίας,γραμματοσειρές γραμμής εργαλείων,χαρακτήρας,γενικές γραμματοσειρές +X-KDE-Keywords[es]=tipos de letra,tamaño del tipo de letra,estilos,juegos de caracteres,panel,panel de control panel,escritorios,Gestor de archivos,Barras de herramientas,Menú,Título de la ventana,Título,DPI,suavizado de texto,tipos de letra del escritorio,tipos de letra de las barras de herramientas,carácter,tipos de letra generales +X-KDE-Keywords[et]=fondid,fondi suurus,kodeering,kooditabel,paneel,juhtpaneel,töölauad,failihaldur,tööriistaribad,menüü,aken,tiitel,nimetus,nimi,DPI,antialias,töölaua fondid,tööriistariba fondid,märk,märgid,sümbolid,üldised fondid +X-KDE-Keywords[eu]=letra-tipoak,letra-tamaina,estiloak,karaktere-jokoak,panela,kontrol-panela,mahaigain,fitxategi-kudeatzaile,tresna-barra,menu,leihoaren titulu,titulu,DPI,antialiasing,mahaigaineko letra-tripo,tresna-barrako letra-tipo,karaktere,letra-tipo orokor +X-KDE-Keywords[fi]=kirjasimet,fontit,kirjasinkoko,fonttikoko,tyylit,merkistöt,paneeli,ohjauskeskus,työpöydät,Tiedostonhallinta,Työkalurivit,Työkalupalkit,Valikko,Ikkunan otsikko,Otsikko,DPI,antialiasointi,työpöytäkirjasimet,työpöytäfontit,työkalurivikirjasimet, työkalurivien kirjasimet, työkalurivifontit, työkalurivien fontit,merkki,yleiskirjasimet,yleiset kirjasimet,yleisfontit,yleiset fontit +X-KDE-Keywords[fr]=polices, taille de police, styles, tables de caractères, jeux de caractères, tableau de bord, bureaux, Gestionnaire de Fichiers, Barre d'outils, Menu, Titre de fenêtre, Titre, DPI, anti crénelage, polices du bureau, police de barre d'outils, caractère, polices générales +X-KDE-Keywords[ga]=clónna,clófhoirne,clómhéid,stíleanna,tacair charachtar,painéal,painéal rialaithe,deasca,Bainisteoir Comhad,Barraí Uirlisí,Roghchlár,Teideal Fuinneoige,Teideal,PSO,frithailiasáil,clónna deisce,clófhoirne deisce,clónna barra uirlisí,carachtar,clónna ginearálta,clófhoirne ginearálta +X-KDE-Keywords[gl]=tipo de letra, letra, tamaño da letra, carácter, caracteres, conxunto de caracteres, glifo, panel, control, panel de control, antialiasing, suavizado +X-KDE-Keywords[hu]=betűkészletek,betűméret,stílusok,karakterkészletek,karakterkészletek,panel,beállítópanel,asztalok,Fájlkezelő,Eszköztárak,Menü,Ablakcím,Cím,DPI,élsimítás,asztal betűkészletek,eszköztár betűkészletek,karakter,általános betűkészletek +X-KDE-Keywords[ia]=fonts,grandor de font,stilos,insimules de characteres,insimules de characteres,pannello,pannello de controlo,scriptorios,Gerente de File,Barra de instrumentos,menu,Titulo de Fenestra,Titulo,DPI,anti-aliasing,fonts de scriptorio, fonts de barra de titulo, character,fonts general +X-KDE-Keywords[it]=caratteri,dimensione dei caratteri,stili,codifiche,insiemi di caratteri,pannello,pannello di controllo,desktop,gestore dei file,barre degli strumenti,menu,titolo della finestra,titolo,DPI,anti-aliasing,caratteri del desktop,caratteri della barra degli strumenti,carattere,caratteri generali +X-KDE-Keywords[kk]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts +X-KDE-Keywords[km]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts +X-KDE-Keywords[ko]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,글꼴,스타일,창 제목,글자 +X-KDE-Keywords[mr]=फॉन्ट्स, फॉन्ट साईज, कॅरेक्टर, कॅरेक्टर सेटस, पँनल, कन्ट्रोल पँनल, डेस्कटॉप्स, फाईल मेनेजर, टूलबार्स, मेन्यू, चौकट टाईटल, टाईटल, डी पी आय , अन्टी अलायझिंग, डेस्कटॉप फॉन्टस, टूलबार फॉन्टस, कॅरेक्टर, जनरल फॉन्ट्स +X-KDE-Keywords[nb]=skrifter,skriftstørrelse,stiler,tegnsett,panel,kontrollpanel,skrivebord,filbehandler,Verktøylinje,Meny,Vindiustittel,tittel,DPI,kantutjevning,skrivebordsskrifter,verktøylinjeskrifter,generelle skrifter +X-KDE-Keywords[nds]=Schriftoorden,Schrift,Stilen,Tekensetten,Paneel,Stüerpaneel,Schriefdisch,Dateipleger,Warktüüchbalkens,Menü,Finstertitel,Titel,DPI,Kantstreken,anti-aliasing,Schriefdisch,Teken +X-KDE-Keywords[nl]=lettertypes,lettertype,tekengrootte,stijlen,tekensets,paneel,besturingspaneel,bureaubladen,bestandsbeheerder,werkbalken,menu,venstertitel,titel,DPI,anti-aliasing,lettertypen van bureaublad,lettertypen van werkbalk,teken,algemene lettertypes +X-KDE-Keywords[pl]=czcionki,rozmiar czcionki,style,zestaw znaków,panel,panel sterowania,pulpity,Menadżer plików,Paski narzędzi,Menu,Tytuł okna,Tytuł,DPI,wygładzanie,czcionki pulpitu,czcionki pasków narzędzi,znak,czcionki ogólne +X-KDE-Keywords[pt]=tipos de letra,tamanho de letra,estilos,codificações,codificações de caracteres,painel,painel de controlo,ecrãs,gestor de ficheiros,barras de ferramentas,menu,título da janela,título,PPP,suavização,tipos de letra do ecrã,tipos de letra da barra de ferramentas,carácter,tipos de letra gerais +X-KDE-Keywords[pt_BR]=fontes,tamanho da fonte,estilos,codificações,codificações de caracteres,painel,painel de controle,áreas de trabalho,gerenciador de arquivos,barras de ferramentas,Menu,Título da janela,Título,PPP,anti-aliasing,fontes da área de trabalho,fontes da barra de ferramentas,caractere,fontes gerais +X-KDE-Keywords[ru]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,шрифты,размер шрифтов,стили,кодировки,панель,панель управления,рабочие столы,диспетчер файлов,панель инструментов,меню,заголовок окна,заголовок,сглаживание,шрифты рабочего стола,шрифты панели инструментов,символы,общие шрифты +X-KDE-Keywords[sk]=písmo,veľkosť písma,štýly,znakové sady,sady znakov,panel,ovládací panel,plochy,Správca súborov,Panely nástrojov,Ponuka,Titulok okna,Titulok,DPI,anti-aliasing,písma plochy,písma nástrojových panelov,znak,všeobecné písma +X-KDE-Keywords[sl]=pisave,velikost pisav,slogi,nabori znakov,znakovni nabori,pult,nadzorna plošča,namizja,upravljalnik datotek,datotečni upravljalnik,orodjarne,orodne vrstice,meni,naslov okna,naslovna vrstica,naslov,ločljivost,točk na palec,glajenje robov,namizne pisave,pisave namizja,pisave orodjarne, pisave orodne vrstice,znak,splošne pisave +X-KDE-Keywords[sr]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,фонт,величина фонта,стил,кодирање,панел,контролни панел,површ,менаџер фајлова,траке алатки,мени,наслов прозора,тпи,омекшавање,фонт површи,фонт траке алатки,знакови,општи фонт +X-KDE-Keywords[sr@ijekavian]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,фонт,величина фонта,стил,кодирање,панел,контролни панел,површ,менаџер фајлова,траке алатки,мени,наслов прозора,тпи,омекшавање,фонт површи,фонт траке алатки,знакови,општи фонт +X-KDE-Keywords[sr@ijekavianlatin]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,font,veličina fonta,stil,kodiranje,panel,kontrolni panel,površ,menadžer fajlova,trake alatki,meni,naslov prozora,tpi,omekšavanje,font površi,font trake alatki,znakovi,opšti font +X-KDE-Keywords[sr@latin]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,font,veličina fonta,stil,kodiranje,panel,kontrolni panel,površ,menadžer fajlova,trake alatki,meni,naslov prozora,tpi,omekšavanje,font površi,font trake alatki,znakovi,opšti font +X-KDE-Keywords[sv]=teckensnitt,teckenstorlek,stil,teckenuppsättningar,panel,kontrollpanel,skrivbord,Filhanterare,Verktygsrader,Meny,Fönsternamn,Namn,Punkter/tum,kantutjämning,skrivbordsteckensnitt,verktygsradsteckensnitt,tecken,allmänna teckensnitt +X-KDE-Keywords[tr]=yazı tipi,yazı tipi boyutu,karakterler,karakter setleri,panel,denetim paneli,masaüstleri,Dosya Yöneticisi,Araç Çubukları,Menü,Pencere Başlığı,Başlık,DPI,yumuşatma,anti-aliasing,masaüstü yazı tipleri,araç çubuğu yazı tipleri,karakter,genel yazı tipleri +X-KDE-Keywords[uk]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,шрифт,шрифти,розмір,розмір шрифту,стиль,стилі,гарнітура,гарнітури,кодування,набір,символ,символи,набір символів,панель,панель керування,стільниця,стільниці,файл,керування,керування файлами,менеджер,панель інструментів,меню,заголовок,заголовок вікна,роздільність,згладжування,шрифти стільниці,шрифти панелі,символ,загальні шрифти +X-KDE-Keywords[x-test]=xxfonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fontsxx +X-KDE-Keywords[zh_CN]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts,字体字体大小,样式,字符集,面板,控制面板,桌面,文件管理器,工具栏,菜单,窗口标题,标题,反锯齿,桌面字体,工具栏字体,字符,常规字体 +X-KDE-Keywords[zh_TW]=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts + +Categories=Qt;KDE;X-KDE-settings-looknfeel; diff --git a/kcms/fonts/fonts.h b/kcms/fonts/fonts.h new file mode 100644 index 0000000000..241fbfb192 --- /dev/null +++ b/kcms/fonts/fonts.h @@ -0,0 +1,127 @@ +//----------------------------------------------------------------------------- +// +// kdisplay, fonts tab +// +// Copyright (c) Mark Donohoe 1997 +// Lars Knoll 1999 + +#ifndef FONTS_H +#define FONTS_H + +#include +#include + +#include +#include +#include + +#include "kxftconfig.h" + +class QCheckBox; +class QComboBox; +class QSpinBox; +class KDoubleNumInput; +class FontAASettings; + +class FontUseItem : public KFontRequester +{ + Q_OBJECT + +public: + FontUseItem(QWidget * parent, const QString &name, const QString &grp, + const QString &key, const QString &rc, const QFont &default_fnt, + bool fixed = false); + + void readFont(); + void writeFont(); + void setDefault(); + void applyFontDiff(const QFont &fnt, int fontDiffFlags); + + const QString& rcFile() { return _rcfile; } + const QString& rcGroup() { return _rcgroup; } + const QString& rcKey() { return _rckey; } + +private: + QString _rcfile; + QString _rcgroup; + QString _rckey; + QFont _default; +}; + +class FontAASettings : public KDialog +{ + Q_OBJECT + +public: + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + FontAASettings(QWidget *parent); + + bool save( bool useAA ); + bool load(); + void defaults(); + int getIndex(KXftConfig::SubPixel::Type spType); + KXftConfig::SubPixel::Type getSubPixelType(); + int getIndex(KXftConfig::Hint::Style hStyle); + KXftConfig::Hint::Style getHintStyle(); + void enableWidgets(); + int exec(); +#endif + +protected Q_SLOTS: + + void changed(); + +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) +private: + + QCheckBox *excludeRange; + QCheckBox *useSubPixel; + KDoubleNumInput *excludeFrom; + KDoubleNumInput *excludeTo; + QComboBox *subPixelType; + QComboBox *hintingStyle; + QLabel *excludeToLabel; + bool changesMade; +#endif +}; + +/** + * The Desktop/fonts tab in kcontrol. + */ +class KFonts : public KCModule +{ + Q_OBJECT + +public: + KFonts(QWidget *parent, const QVariantList &); + ~KFonts(); + + virtual void load(); + virtual void save(); + virtual void defaults(); + +protected Q_SLOTS: + void fontSelected(); + void slotApplyFontDiff(); + void slotUseAntiAliasing(); + void slotCfgAa(); + +private: +#if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) + enum AASetting { AAEnabled, AASystem, AADisabled }; + AASetting useAA, useAA_original; + QComboBox *cbAA; + QPushButton *aaSettingsButton; + FontAASettings *aaSettings; +#endif +#if HAVE_X11 + int dpi_original; + QCheckBox *checkboxForceDpi; + QSpinBox* spinboxDpi; +#endif + QList fontUseList; +}; + +#endif + diff --git a/kcms/fonts/kxftconfig.cpp b/kcms/fonts/kxftconfig.cpp new file mode 100644 index 0000000000..6fc02336e8 --- /dev/null +++ b/kcms/fonts/kxftconfig.cpp @@ -0,0 +1,847 @@ +/* + Copyright (c) 2002 Craig Drummond + + 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 "kxftconfig.h" +#ifdef HAVE_FONTCONFIG + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace std; + +static int point2Pixel(double point) +{ + return (int)(((point*QX11Info::appDpiY())/72.0)+0.5); +} + +static int pixel2Point(double pixel) +{ + return (int)(((pixel*72.0)/(double)QX11Info::appDpiY())+0.5); +} + +static bool equal(double d1, double d2) +{ + return (fabs(d1 - d2) < 0.0001); +} + +static QString dirSyntax(const QString &d) +{ + if(!d.isNull()) + { + QString ds(d); + + ds.replace("//", "/"); + + int slashPos=ds.lastIndexOf('/'); + + if(slashPos!=(((int)ds.length())-1)) + ds.append('/'); + + return ds; + } + + return d; +} + +static bool check(const QString &path, unsigned int fmt, bool checkW=false) +{ + KDE_struct_stat info; + QByteArray pathC(QFile::encodeName(path)); + + return 0==KDE_lstat(pathC, &info) && (info.st_mode&S_IFMT)==fmt && + (!checkW || 0==::access(pathC, W_OK)); +} + +inline bool fExists(const QString &p) +{ + return check(p, S_IFREG, false); +} + +inline bool dWritable(const QString &p) +{ + return check(p, S_IFDIR, true); +} + +static QString getDir(const QString &f) +{ + QString d(f); + + int slashPos=d.lastIndexOf('/'); + + if(-1!=slashPos) + d.remove(slashPos+1, d.length()); + + return dirSyntax(d); +} + +static time_t getTimeStamp(const QString &item) +{ + KDE_struct_stat info; + + return !item.isNull() && 0==KDE_lstat(QFile::encodeName(item), &info) ? info.st_mtime : 0; +} + +// +// Obtain location of config file to use. +QString getConfigFile() +{ + FcStrList *list=FcConfigGetConfigFiles(FcConfigGetCurrent()); + QStringList files; + FcChar8 *file; + QString home(dirSyntax(QDir::homePath())); + + while((file=FcStrListNext(list))) + { + QString f((const char *)file); + + if(fExists(f) && 0==f.indexOf(home)) + files.append(f); + } + FcStrListDone(list); + + // + // Go through list of files, looking for the preferred one... + if(files.count()) + { + QStringList::const_iterator it(files.begin()), + end(files.end()); + + for(; it!=end; ++it) + if(-1!=(*it).indexOf(QRegExp("/\\.?fonts\\.conf$"))) + return *it; + return files.front(); // Just return the 1st one... + } + else // Hmmm... no known files? + { + if(FcGetVersion() >= 21000) + { + QString targetPath(KGlobal::dirs()->localxdgconfdir()+"fontconfig"); + QDir target(targetPath); + if(!target.exists()) + target.mkpath(targetPath); + return targetPath+"/fonts.conf"; + } + else + return home+"/.fonts.conf"; + } +} + +static QString getEntry(QDomElement element, const char *type, unsigned int numAttributes, ...) +{ + if(numAttributes==element.attributes().length()) + { + va_list args; + unsigned int arg; + bool ok=true; + + va_start(args, numAttributes); + + for(arg=0; arg"; + static const char qtDocTypeLine[] = ""; + static const char docTypeLine[] = ""; + + QString str(m_doc.toString()); + int idx; + + if(0!=str.indexOf("=0 || to>=0) && foundFalse) + { + m_excludeRange.from=from < to ? from : to; + m_excludeRange.to =from < to ? to : from; + m_excludeRange.node=n; + } + else if((pixelFrom>=0 || pixelTo>=0) && foundFalse) + { + m_excludePixelRange.from=pixelFrom < pixelTo ? pixelFrom : pixelTo; + m_excludePixelRange.to =pixelFrom < pixelTo ? pixelTo : pixelFrom; + m_excludePixelRange.node=n; + } + } + break; + default: + break; + } + } + } + n=n.nextSibling(); + } +} + +void KXftConfig::applySubPixelType() +{ + QDomElement matchNode = m_doc.createElement("match"), + typeNode = m_doc.createElement("const"), + editNode = m_doc.createElement("edit"); + QDomText typeText = m_doc.createTextNode(toStr(m_subPixel.type)); + + matchNode.setAttribute("target", "font"); + editNode.setAttribute("mode", "assign"); + editNode.setAttribute("name", "rgba"); + editNode.appendChild(typeNode); + typeNode.appendChild(typeText); + matchNode.appendChild(editNode); + if(m_subPixel.node.isNull()) + m_doc.documentElement().appendChild(matchNode); + else + m_doc.documentElement().replaceChild(matchNode, m_subPixel.node); + m_subPixel.node=matchNode; +} + +void KXftConfig::applyHintStyle() +{ + applyHinting(); + + if(Hint::NotSet==m_hint.style || m_hint.toBeRemoved) + { + if(!m_hint.node.isNull()) + { + m_doc.documentElement().removeChild(m_hint.node); + m_hint.node.clear(); + } + } + else + { + QDomElement matchNode = m_doc.createElement("match"), + typeNode = m_doc.createElement("const"), + editNode = m_doc.createElement("edit"); + QDomText typeText = m_doc.createTextNode(toStr(m_hint.style)); + + matchNode.setAttribute("target", "font"); + editNode.setAttribute("mode", "assign"); + editNode.setAttribute("name", "hintstyle"); + editNode.appendChild(typeNode); + typeNode.appendChild(typeText); + matchNode.appendChild(editNode); + if(m_hint.node.isNull()) + m_doc.documentElement().appendChild(matchNode); + else + m_doc.documentElement().replaceChild(matchNode, m_hint.node); + m_hint.node=matchNode; + } +} + +void KXftConfig::applyHinting() +{ + QDomElement matchNode = m_doc.createElement("match"), + typeNode = m_doc.createElement("bool"), + editNode = m_doc.createElement("edit"); + QDomText typeText = m_doc.createTextNode(m_hinting.set ? "true" : "false"); + + matchNode.setAttribute("target", "font"); + editNode.setAttribute("mode", "assign"); + editNode.setAttribute("name", "hinting"); + editNode.appendChild(typeNode); + typeNode.appendChild(typeText); + matchNode.appendChild(editNode); + if(m_hinting.node.isNull()) + m_doc.documentElement().appendChild(matchNode); + else + m_doc.documentElement().replaceChild(matchNode, m_hinting.node); + m_hinting.node=matchNode; +} + +void KXftConfig::applyExcludeRange(bool pixel) +{ + Exclude &range=pixel ? m_excludePixelRange : m_excludeRange; + + if(equal(range.from, 0) && equal(range.to, 0)) + { + if(!range.node.isNull()) + { + m_doc.documentElement().removeChild(range.node); + range.node.clear(); + } + } + else + { + QString fromString, + toString; + + fromString.setNum(range.from); + toString.setNum(range.to); + + QDomElement matchNode = m_doc.createElement("match"), + fromTestNode = m_doc.createElement("test"), + fromNode = m_doc.createElement("double"), + toTestNode = m_doc.createElement("test"), + toNode = m_doc.createElement("double"), + editNode = m_doc.createElement("edit"), + boolNode = m_doc.createElement("bool"); + QDomText fromText = m_doc.createTextNode(fromString), + toText = m_doc.createTextNode(toString), + boolText = m_doc.createTextNode("false"); + + matchNode.setAttribute("target", "font"); // CPD: Is target "font" or "pattern" ???? + fromTestNode.setAttribute("qual", "any"); + fromTestNode.setAttribute("name", pixel ? "pixelsize" : "size"); + fromTestNode.setAttribute("compare", "more_eq"); + fromTestNode.appendChild(fromNode); + fromNode.appendChild(fromText); + toTestNode.setAttribute("qual", "any"); + toTestNode.setAttribute("name", pixel ? "pixelsize" : "size"); + toTestNode.setAttribute("compare", "less_eq"); + toTestNode.appendChild(toNode); + toNode.appendChild(toText); + editNode.setAttribute("mode", "assign"); + editNode.setAttribute("name", "antialias"); + editNode.appendChild(boolNode); + boolNode.appendChild(boolText); + matchNode.appendChild(fromTestNode); + matchNode.appendChild(toTestNode); + matchNode.appendChild(editNode); + + if(!m_antiAliasing.node.isNull()) + m_doc.documentElement().removeChild(range.node); + m_doc.documentElement().appendChild(matchNode); + range.node=matchNode; + } +} + +bool KXftConfig::getAntiAliasing() const +{ + return m_antiAliasing.set; +} + +void KXftConfig::setAntiAliasing( bool set ) +{ + if(set!=m_antiAliasing.set) + { + m_antiAliasing.set = set; + m_madeChanges = true; + } +} + +void KXftConfig::applyAntiAliasing() +{ + QDomElement matchNode = m_doc.createElement("match"), + typeNode = m_doc.createElement("bool"), + editNode = m_doc.createElement("edit"); + QDomText typeText = m_doc.createTextNode(m_antiAliasing.set ? "true" : "false"); + + matchNode.setAttribute("target", "font"); + editNode.setAttribute("mode", "assign"); + editNode.setAttribute("name", "antialias"); + editNode.appendChild(typeNode); + typeNode.appendChild(typeText); + matchNode.appendChild(editNode); + if(!m_antiAliasing.node.isNull()) + m_doc.documentElement().removeChild(m_antiAliasing.node); + m_doc.documentElement().appendChild(matchNode); + m_antiAliasing.node=matchNode; +} + +// KXftConfig only parses one config file, user's .fonts.conf usually. +// If that one doesn't exist, then KXftConfig doesn't know if antialiasing +// is enabled or not. So try to find out the default value from the default font. +// Maybe there's a better way *shrug*. +bool KXftConfig::aliasingEnabled() +{ + FcPattern *pattern = FcPatternCreate(); + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + FcResult result; + FcPattern *f = FcFontMatch( 0, pattern, &result ); + FcBool antialiased = FcTrue; + FcPatternGetBool( f, FC_ANTIALIAS, 0, &antialiased ); + FcPatternDestroy( f ); + FcPatternDestroy( pattern ); + return antialiased == FcTrue; +} + +#endif diff --git a/kcms/fonts/kxftconfig.h b/kcms/fonts/kxftconfig.h new file mode 100644 index 0000000000..0df6164591 --- /dev/null +++ b/kcms/fonts/kxftconfig.h @@ -0,0 +1,167 @@ +#ifndef __KXFTCONFIG_H__ +#define __KXFTCONFIG_H__ + +/* + Copyright (c) 2002 Craig Drummond + + 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 + +#ifdef HAVE_FONTCONFIG + +#include + +#include +#include + +class KXftConfig +{ + public: + + struct Item + { + Item(QDomNode &n) : node(n), toBeRemoved(false) {} + Item() : toBeRemoved(false) {} + virtual void reset() { node.clear(); toBeRemoved=false; } + bool added() { return node.isNull(); } + + QDomNode node; + + virtual ~Item() {} + bool toBeRemoved; + }; + + struct SubPixel : public Item + { + enum Type + { + None, + Rgb, + Bgr, + Vrgb, + Vbgr + }; + + SubPixel(Type t, QDomNode &n) : Item(n), type(t) {} + SubPixel(Type t=None) : type(t) {} + + void reset() { Item::reset(); type=None; } + + Type type; + }; + + struct Exclude : public Item + { + Exclude(double f, double t, QDomNode &n) : Item(n), from(f), to(t) {} + Exclude(double f=0, double t=0) : from(f), to(t) {} + + void reset() { Item::reset(); from=to=0; } + + double from, + to; + }; + + struct Hint : public Item + { + enum Style + { + NotSet, + None, + Slight, + Medium, + Full + }; + + Hint(Style s, QDomNode &n) : Item(n), style(s) {} + Hint(Style s=NotSet) : style(s) {} + + void reset() { Item::reset(); style=NotSet; } + + Style style; + }; + + struct Hinting : public Item + { + Hinting(bool s, QDomNode &n) : Item(n), set(s) {} + Hinting(bool s=true) : set(s) {} + + void reset() { Item::reset(); set=true; } + + bool set; + }; + + struct AntiAliasing : public Item + { + AntiAliasing(bool s, QDomNode &n) : Item(n), set(s) {} + AntiAliasing(bool s=true) : set(s) {} + + void reset() { Item::reset(); set=true; } + + bool set; + }; + + public: + + explicit KXftConfig(); + + virtual ~KXftConfig(); + + bool reset(); + bool apply(); + bool getSubPixelType(SubPixel::Type &type); + void setSubPixelType(SubPixel::Type type); // SubPixel::None => turn off sub-pixel rendering + bool getExcludeRange(double &from, double &to); + void setExcludeRange(double from, double to); // from:0, to:0 => turn off exclude range + bool getHintStyle(Hint::Style &style); + void setHintStyle(Hint::Style style); + void setAntiAliasing(bool set); + bool getAntiAliasing() const; + bool changed() { return m_madeChanges; } + static QString description(SubPixel::Type t); + static const char * toStr(SubPixel::Type t); + static QString description(Hint::Style s); + static const char * toStr(Hint::Style s); + + private: + + void readContents(); + void applySubPixelType(); + void applyHintStyle(); + void applyAntiAliasing(); + void setHinting(bool set); + void applyHinting(); + void applyExcludeRange(bool pixel); + bool aliasingEnabled(); + + private: + + SubPixel m_subPixel; + Exclude m_excludeRange, + m_excludePixelRange; + Hint m_hint; + Hinting m_hinting; + AntiAliasing m_antiAliasing; + QDomDocument m_doc; + QString m_file; + bool m_madeChanges; + time_t m_time; +}; + +#endif + +#endif diff --git a/kcms/hardware/CMakeLists.txt b/kcms/hardware/CMakeLists.txt new file mode 100644 index 0000000000..ab22293590 --- /dev/null +++ b/kcms/hardware/CMakeLists.txt @@ -0,0 +1,9 @@ + +add_subdirectory( display ) + +if (CMAKE_SYSTEM_NAME MATCHES Linux) + # this one doesn't seem to be very portable, Alex + add_subdirectory( joystick ) +endif () + + diff --git a/kcms/hardware/display/CMakeLists.txt b/kcms/hardware/display/CMakeLists.txt new file mode 100644 index 0000000000..f3c0efd52a --- /dev/null +++ b/kcms/hardware/display/CMakeLists.txt @@ -0,0 +1,23 @@ + + + +########### next target ############### + +set(kcm_display_PART_SRCS display.cpp ) + + +add_library(kcm_display MODULE ${kcm_display_PART_SRCS}) + + +target_link_libraries(kcm_display + KF5::KCMUtils + KF5::I18n + KF5::KDE4Support +) + +install(TARGETS kcm_display DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES display.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/kcms/hardware/display/Messages.sh b/kcms/hardware/display/Messages.sh new file mode 100644 index 0000000000..561ccd0d8b --- /dev/null +++ b/kcms/hardware/display/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/display.pot diff --git a/kcms/hardware/display/display.cpp b/kcms/hardware/display/display.cpp new file mode 100644 index 0000000000..c24d1429bd --- /dev/null +++ b/kcms/hardware/display/display.cpp @@ -0,0 +1,117 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan + + This program is free software; you can redistribute it and/or + modify it under the terms of the 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 +#include +#include +#include + +#include +#include +#include + +#include "display.h" +#include +#include + +K_PLUGIN_FACTORY(DisplayFactory, + registerPlugin(); + ) + +KCMDisplay::KCMDisplay( QWidget *parent, const QVariantList & ) + : KCModule( parent ) + , m_changed(false) +{ + m_tabs = new QTabWidget( this ); + + addTab( "randr", i18n( "Size && Orientation" ) ); + addTab( "nvidiadisplay", i18n( "Graphics Adaptor" ) ); + addTab( "nvidia3d", i18n( "3D Options" ) ); + addTab( "kgamma", i18n( "Monitor Gamma" ) ); + if ( QApplication::desktop()->isVirtualDesktop() ) + addTab( "xinerama", i18n( "Multiple Monitors" ) ); + addTab( "energy", i18n( "Power Control" ) ); + + QVBoxLayout *top = new QVBoxLayout( this ); + top->setMargin( 0 ); + top->setSpacing( KDialog::spacingHint() ); + top->addWidget( m_tabs ); + + setButtons( Apply ); + load(); +} + +void KCMDisplay::addTab( const QString &name, const QString &label ) +{ + QWidget *page = new QWidget( m_tabs ); + QVBoxLayout *top = new QVBoxLayout( page ); + top->setMargin( KDialog::marginHint() ); + + KCModule *kcm = KCModuleLoader::loadModule( name, KCModuleLoader::None,page ); + + if ( kcm ) + { + top->addWidget( kcm ); + m_tabs->addTab( page, label ); + + connect( kcm, SIGNAL(changed(bool)), SLOT(moduleChanged(bool)) ); + m_modules.insert(kcm, false); + } + else + delete page; +} + +void KCMDisplay::load() +{ + for (QMap::ConstIterator it = m_modules.constBegin(); it != m_modules.constEnd(); ++it) + it.key()->load(); +} + +void KCMDisplay::save() +{ + for (QMap::Iterator it = m_modules.begin(); it != m_modules.end(); ++it) + if (it.value()) + it.key()->save(); +} + +void KCMDisplay::moduleChanged( bool isChanged ) +{ + QMap::Iterator currentModule = m_modules.find(static_cast(const_cast(sender()))); + Q_ASSERT(currentModule != m_modules.end()); + if (currentModule.value() == isChanged) + return; + + currentModule.value() = isChanged; + + bool c = false; + + for (QMap::ConstIterator it = m_modules.constBegin(); it != m_modules.constEnd(); ++it) { + if (it.value()) { + c = true; + break; + } + } + + if (m_changed != c) { + m_changed = c; + emit changed(c); + } +} + +#include "display.moc" diff --git a/kcms/hardware/display/display.desktop b/kcms/hardware/display/display.desktop new file mode 100644 index 0000000000..fad2e876d2 --- /dev/null +++ b/kcms/hardware/display/display.desktop @@ -0,0 +1,191 @@ +[Desktop Entry] +Exec=kcmshell5 display +Icon=preferences-desktop-display +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kcm_display +X-KDE-ParentApp=kcontrol + +Name=Display +Name[af]=Skerm +Name[ar]=العرض +Name[ast]=Pantalla +Name[be]=Экран +Name[be@latin]=Ekran +Name[bg]=Екран +Name[bn]=ডিসপ্লে +Name[bn_IN]=প্রদর্শন +Name[br]=Diskwel +Name[bs]=Ekran +Name[ca]=Pantalla +Name[ca@valencia]=Pantalla +Name[cs]=Obrazovka +Name[csb]=Ekran +Name[cy]= Arddangos +Name[da]=Skærm +Name[de]=Anzeige +Name[el]=Οθόνη +Name[en_GB]=Display +Name[eo]=Vidigilo +Name[es]=Pantalla +Name[et]=Monitor +Name[eu]=Pantaila +Name[fa]=نمایش +Name[fi]=Näyttö +Name[fr]=Affichage +Name[fy]=Byldskerm +Name[ga]=Scáileán +Name[gl]=Pantalla +Name[gu]=ડિસ્પ્લે +Name[he]=תצוגה +Name[hi]=प्रदर्शक +Name[hne]=प्रदर्सक +Name[hr]=Zaslon +Name[hsb]=Wobrazowka +Name[hu]=Megjelenítés +Name[ia]=Monstrator +Name[id]=Tampilan +Name[is]=Skjár +Name[it]=Schermo +Name[ja]=ディスプレイ +Name[ka]=ჩვენება +Name[kk]=Дисплей +Name[km]=ការ​បង្ហាញ +Name[kn]=ಪ್ರದರ್ಶಕ +Name[ko]=디스플레이 +Name[ku]=Dîmender +Name[lt]=Ekranas +Name[lv]=Ekrāns +Name[mai]=देखाबू +Name[mk]=Приказ +Name[ml]=പ്രദര്‍ശനം +Name[mr]=डिस्प्ले +Name[ms]=Paparan +Name[nb]=Skjerm +Name[nds]=Dorstellen +Name[ne]=प्रदर्शन गर्नुहोस् +Name[nl]=Beeldscherm +Name[nn]=Skjerm +Name[oc]=Visualizar +Name[or]=ପ୍ରଦର୍ଶକ +Name[pa]=ਡਿਸਪਲੇਅ +Name[pl]=Ekran +Name[pt]=Ecrã +Name[pt_BR]=Tela +Name[ro]=Afișare +Name[ru]=Экран +Name[se]=Šearbma +Name[si]=සංදර්ශනය +Name[sk]=Obrazovka +Name[sl]=Zaslon +Name[sr]=Екран +Name[sr@ijekavian]=Екран +Name[sr@ijekavianlatin]=Ekran +Name[sr@latin]=Ekran +Name[sv]=Bildskärm +Name[ta]=காட்சி +Name[te]=ప్రదర్శన +Name[tg]=Экран +Name[th]=การแสดงผล +Name[tr]=Ekran +Name[ug]=كۆرسەتكۈچ +Name[uk]=Дисплей +Name[uz]=Displey +Name[uz@cyrillic]=Дисплей +Name[vi]=Màn hình +Name[wa]=Håynaedje +Name[x-test]=xxDisplayxx +Name[zh_CN]=显示 +Name[zh_TW]=顯示 +Comment=Display Settings +Comment[af]=Skerm Instellings +Comment[ar]=إعدادات العرض +Comment[ast]=Preferencies de la pantalla +Comment[be]=Настаўленні экрану +Comment[be@latin]=Nałady ekrana +Comment[bg]=Настройки на екрана +Comment[bn]=ডিসপ্লে সেটিংস +Comment[bn_IN]=প্রদর্শন সংক্রান্ত বৈশিষ্ট্য +Comment[br]=Kefluniañ an diskwel +Comment[bs]=Postavke ekrana +Comment[ca]=Arranjament de la pantalla +Comment[ca@valencia]=Arranjament de la pantalla +Comment[cs]=Nastavení obrazovky +Comment[csb]=Ùstôw ekranu +Comment[cy]=Gosodiadau Arddangos +Comment[da]=Skærmindstillinger +Comment[de]=Anzeige-Einstellungen +Comment[el]=Ρυθμίσεις οθόνης +Comment[en_GB]=Display Settings +Comment[eo]=Vidigila agordo +Comment[es]=Preferencias de la pantalla +Comment[et]=Monitoride seadistused +Comment[eu]=Pantailaren ezarpenak +Comment[fa]=نمایش تنظیمات +Comment[fi]=Näytön asetukset +Comment[fr]=Configuration de l'affichage +Comment[fy]=Byldskerm ynstellings +Comment[ga]=Socruithe an Scáileáin +Comment[gl]=Configuración da pantalla +Comment[gu]=ડિસ્પ્લે ગોઠવણીઓ +Comment[he]=הגדרות תצוגה +Comment[hi]=प्रकटन विन्यास +Comment[hne]=देखइया सेटिंग +Comment[hr]=Postavke zaslona +Comment[hsb]=Nastajenja za wobrazowku +Comment[hu]=Megjelenési beállítások +Comment[ia]=Monstra preferentias +Comment[id]=Pengaturan Tampilan +Comment[is]=Stillingar skjás +Comment[it]=Impostazioni dello schermo +Comment[ja]=ディスプレイの設定 +Comment[ka]=დისპლეის კონფიგურირება +Comment[kk]=Дисплей баптаулары +Comment[km]=កំណត់​ការ​បង្ហាញ +Comment[kn]=ಪ್ರದರ್ಶಕದ ಸಂಯೋಜನೆಗಳು +Comment[ko]=디스플레이 설정 +Comment[ku]=Mîhengên Dîmenderê +Comment[lt]=Ekrano parametrai +Comment[lv]=Ekrāna parametri +Comment[mai]=जमावट देखाबू +Comment[mk]=Поставувања на приказот +Comment[ml]=പ്രദര്‍ശനത്തിന്റെ സജ്ജീകരണങ്ങള്‍ +Comment[mr]=डिस्प्ले संयोजना +Comment[ms]=Seting Paparan +Comment[nb]=Skjerminnstillinger +Comment[nds]=Dorstellen inrichten +Comment[ne]=सेटिङ प्रदर्शन गर्नुहोस् +Comment[nl]=Beeldscherminstellingen +Comment[nn]=Skjerminnstillingar +Comment[or]=ପ୍ରଦର୍ଶକ ସଂରଚନା +Comment[pa]=ਡਿਸਪਲੇਅ ਸੈਟਿੰਗ +Comment[pl]=Ustawienia ekranu +Comment[pt]=Configuração do ecrã +Comment[pt_BR]=Configurações da tela +Comment[ro]=Configurări afișare +Comment[ru]=Настройка экрана +Comment[se]=Šearbmaheivehusat +Comment[si]=සංදර්ශන සැකසුම් +Comment[sk]=Nastavenie obrazovky +Comment[sl]=Nastavitve zaslona +Comment[sr]=Поставке екрана +Comment[sr@ijekavian]=Поставке екрана +Comment[sr@ijekavianlatin]=Postavke ekrana +Comment[sr@latin]=Postavke ekrana +Comment[sv]=Anpassa bildskärm +Comment[ta]=அமைப்புகளை காட்டு +Comment[te]=ప్రదర్శన అమరికలు +Comment[tg]=Танзимоти экран +Comment[th]=ตั้งค่าต่าง ๆ ของการแสดงผล +Comment[tr]=Ekran Ayarları +Comment[ug]=كۆرۈنمە يۈز تەڭشىكى +Comment[uk]=Налаштування дисплея +Comment[uz]=Displeyning moslamalari +Comment[uz@cyrillic]=Дисплейнинг мосламалари +Comment[vi]=Thiết lập hiển thị +Comment[wa]=Apontiaedjes do Håynaedje +Comment[x-test]=xxDisplay Settingsxx +Comment[zh_CN]=显示设置 +Comment[zh_TW]=顯示設定 +Categories=Qt;KDE;X-KDE-settings-hardware; diff --git a/kcms/hardware/display/display.h b/kcms/hardware/display/display.h new file mode 100644 index 0000000000..7e0c342240 --- /dev/null +++ b/kcms/hardware/display/display.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Nadeem Hasan + + This program is free software; you can redistribute it and/or + modify it under the terms of the 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 DISPLAY_H +#define DISPLAY_H + +#include + +class QTabWidget; + +class KCMDisplay : public KCModule +{ + Q_OBJECT + + public: + KCMDisplay( QWidget *parent, const QVariantList & ); + void load(); + void save(); + + private Q_SLOTS: + void moduleChanged(bool isChanged); + + private: + void addTab( const QString &name, const QString &label ); + + QTabWidget *m_tabs; + QMap m_modules; + bool m_changed; +}; + +#endif // DISPLAY_H + diff --git a/kcms/hardware/joystick/CMakeLists.txt b/kcms/hardware/joystick/CMakeLists.txt new file mode 100644 index 0000000000..8427b4c128 --- /dev/null +++ b/kcms/hardware/joystick/CMakeLists.txt @@ -0,0 +1,32 @@ + + + +########### next target ############### + +set(kcm_joystick_PART_SRCS + joystick.cpp + joywidget.cpp + poswidget.cpp + joydevice.cpp + caldialog.cpp ) + + +add_library(kcm_joystick MODULE ${kcm_joystick_PART_SRCS}) + + +target_link_libraries(kcm_joystick + KF5::Completion + KF5::KCMUtils + KF5::I18n + KF5::KIOWidgets + KF5::KDE4Support +) + +install(TARGETS kcm_joystick DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES joystick.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + +# diff --git a/kcms/hardware/joystick/Messages.sh b/kcms/hardware/joystick/Messages.sh new file mode 100644 index 0000000000..1d116ceb76 --- /dev/null +++ b/kcms/hardware/joystick/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/joystick.pot diff --git a/kcms/hardware/joystick/caldialog.cpp b/kcms/hardware/joystick/caldialog.cpp new file mode 100644 index 0000000000..76e960b40f --- /dev/null +++ b/kcms/hardware/joystick/caldialog.cpp @@ -0,0 +1,200 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller + * kollix@aon.at + * This file is part of the KDE Control Center Module for Joysticks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "caldialog.h" +#include "joydevice.h" + +#include +#include +#include + +#include +#include +#include +#include +//-------------------------------------------------------------- + +CalDialog::CalDialog(QWidget *parent, JoyDevice *joy) + : KDialog( parent ), + joydev(joy) +{ + setObjectName( "calibrateDialog" ); + setModal( true ); + setCaption( i18n("Calibration") ); + setButtons( Cancel | User1 ); + setDefaultButton( User1 ); + setButtonGuiItem( User1, KGuiItem( i18n("Next") ) ); + + KVBox *main = new KVBox( this ); + setMainWidget( main ); + + text = new QLabel(main); + text->setMinimumHeight(200); + valueLbl = new QLabel(main); + connect(this,SIGNAL(user1Clicked()),this,SLOT(slotUser1())); +} + +//-------------------------------------------------------------- + +void CalDialog::calibrate() +{ + text->setText(i18n("Please wait a moment to calculate the precision")); + setResult(-1); + show(); + + // calibrate precision (which min,max delivers the joystick in its center position) + // get values through the normal idle procedure + QTimer ti; + ti.setSingleShot(true); // single shot + ti.start(2000); // in 2 seconds + + // normally I'd like to hide the 'Next' button in this step, + // but it does not work - which means: in the steps after the first, + // the 'Next' button does not have the focus (to be the default button) + + do + { + qApp->processEvents(QEventLoop::AllEvents, 2000); + } + while ( ti.isActive() && (result() != QDialog::Rejected) ); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->calcPrecision(); + + int i, lastVal; + int min[2], center[2], max[2]; + QString hint; + + for (i = 0; i < joydev->numAxes(); i++) + { + if ( i == 0 ) + hint = i18n("(usually X)"); + else if ( i == 1 ) + hint = i18n("(usually Y)"); + else + hint = ""; + + // minimum position + text->setText(i18n("Calibration is about to check the value range your device delivers.

    " + "Please move axis %1 %2 on your device to the minimum position.

    " + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.
    ", i+1, hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + min[0] = joydev->axisMin(i); + min[1] = joydev->axisMax(i); + + // center position + text->setText(i18n("Calibration is about to check the value range your device delivers.

    " + "Please move axis %1 %2 on your device to the center position.

    " + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.
    ", i+1, hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user canceled the dialog + + center[0] = joydev->axisMin(i); + center[1] = joydev->axisMax(i); + + // maximum position + text->setText(i18n("Calibration is about to check the value range your device delivers.

    " + "Please move axis %1 %2 on your device to the maximum position.

    " + "Press any button on the device or click on the 'Next' button " + "to continue with the next step.
    ", i+1, hint)); + waitButton(i, true, lastVal); + + if ( result() == QDialog::Rejected ) return; // user cancelled the dialog + + joydev->resetMinMax(i, lastVal); + if ( result() != -2 ) waitButton(i, false, lastVal); + + if ( result() == QDialog::Rejected ) return; // user canceled the dialog + + max[0] = joydev->axisMin(i); + max[1] = joydev->axisMax(i); + + joydev->calcCorrection(i, min, center, max); + } + + JoyDevice::ErrorCode ret = joydev->applyCalibration(); + + if ( ret != JoyDevice::SUCCESS ) + { + KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error")); + reject(); + } + + KMessageBox::information(this, i18n("You have successfully calibrated your device"), i18n("Calibration Success")); + accept(); +} + +//-------------------------------------------------------------- + +void CalDialog::waitButton(int axis, bool press, int &lastVal) +{ + JoyDevice::EventType type; + int number, value; + bool button = false; + lastVal = 0; + + setResult(-1); + // loop until the user presses a button on the device or on the dialog + do + { + qApp->processEvents(QEventLoop::AllEvents, 100); + + if ( joydev->getEvent(type, number, value) ) + { + button = ( (type == JoyDevice::BUTTON) && (press ? (value == 1) : (value == 0)) ); + + if ( (type == JoyDevice::AXIS) && (number == axis) ) + valueLbl->setText(i18n("Value Axis %1: %2", axis+1, lastVal = value)); + } + } + while ( !button && (result() == -1) ); +} + +//-------------------------------------------------------------- +// Next button + +void CalDialog::slotUser1() +{ + setResult(-2); +} + +//-------------------------------------------------------------- + +#include "caldialog.moc" + +//-------------------------------------------------------------- diff --git a/kcms/hardware/joystick/caldialog.h b/kcms/hardware/joystick/caldialog.h new file mode 100644 index 0000000000..e1a1fd7f7f --- /dev/null +++ b/kcms/hardware/joystick/caldialog.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 _CALDIALOG_H_ +#define _CALDIALOG_H_ + +#include + +#include + +class JoyDevice; + +// the dialog which tells the user all steps to calibrate the device + +class CalDialog : public KDialog +{ + Q_OBJECT + + public: + CalDialog(QWidget *parent, JoyDevice *joy); + + void calibrate(); + + private: + void waitButton(int axis, bool press, int &lastVal); + + private Q_SLOTS: + virtual void slotUser1(); + + private: + JoyDevice *joydev; + + QLabel *text; + QLabel *valueLbl; +}; + +#endif diff --git a/kcms/hardware/joystick/joydevice.cpp b/kcms/hardware/joystick/joydevice.cpp new file mode 100644 index 0000000000..7dffb10faf --- /dev/null +++ b/kcms/hardware/joystick/joydevice.cpp @@ -0,0 +1,403 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "joydevice.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//-------------------------------------------------------------- + +JoyDevice::JoyDevice(const QString &devicefile) + : devName(devicefile), joyFd(-1), buttons(0), axes(0), + amin(0), amax(0), corr(0), origCorr(0) +{ +} + +//-------------------------------------------------------------- + +QString JoyDevice::errText(ErrorCode code) const +{ + switch ( code ) + { + case SUCCESS: return ""; + + case OPEN_FAILED: + { + return i18n("The given device %1 could not be opened: %2", + devName, strerror(errno)); + } + + case NO_JOYSTICK: + { + return i18n("The given device %1 is not a joystick.", devName); + } + + case ERR_GET_VERSION: + { + return i18n("Could not get kernel driver version for joystick device %1: %2", + devName, strerror(errno)); + } + + case WRONG_VERSION: + { + int version = 0; + int fd = ::open(devName.toLatin1(), O_RDONLY); + if ( fd != -1 ) + { + ::ioctl(fd, JSIOCGVERSION, &version); + ::close(fd); + } + + KLocalizedString loc = ki18n("The current running kernel driver version (%1.%2.%3) is not the one this module was compiled for (%4.%5.%6)."); + loc.subs(version >> 16); + loc.subs((version >> 8) & 0xFF); + loc.subs(version & 0xFF); + loc.subs(JS_VERSION >> 16); + loc.subs((JS_VERSION >> 8) & 0xFF); + loc.subs(JS_VERSION & 0xFF); + return loc.toString(); + } + + case ERR_GET_BUTTONS: + { + return i18n("Could not get number of buttons for joystick device %1: %2", + devName, strerror(errno)); + } + + case ERR_GET_AXES: + { + return i18n("Could not get number of axes for joystick device %1: %2", + devName, strerror(errno)); + } + + case ERR_GET_CORR: + { + return i18n("Could not get calibration values for joystick device %1: %2", + devName, strerror(errno)); + } + + case ERR_RESTORE_CORR: + { + return i18n("Could not restore calibration values for joystick device %1: %2", + devName, strerror(errno)); + } + + case ERR_INIT_CAL: + { + return i18n("Could not initialize calibration values for joystick device %1: %2", + devName, strerror(errno)); + } + + case ERR_APPLY_CAL: + { + return i18n("Could not apply calibration values for joystick device %1: %2", + devName, strerror(errno)); + } + + default: return i18n("internal error - code %1 unknown", int(code)); + } +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::open() +{ + if ( joyFd != -1 ) return JoyDevice::SUCCESS; // already open + + int fd = ::open(devName.toLatin1(), O_RDONLY); + + if ( fd == -1 ) + return JoyDevice::OPEN_FAILED; + + // we could open the devicefile, now check if a joystick is attached + char name[128]; + + if ( ::ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1 ) + { + ::close(fd); + return JoyDevice::NO_JOYSTICK; + } + + // check the kernel driver version + int version; + if ( ::ioctl(fd, JSIOCGVERSION, &version) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_VERSION; + } + + if ( version != JS_VERSION ) + { + ::close(fd); + return JoyDevice::WRONG_VERSION; + } + + char bt = 0, ax = 0; + if ( ::ioctl(fd, JSIOCGBUTTONS, &bt) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_BUTTONS; + } + + if ( ::ioctl(fd, JSIOCGAXES, &ax) == -1 ) + { + ::close(fd); + return JoyDevice::ERR_GET_AXES; + } + + struct js_corr *oldCorr = new struct js_corr[ax]; + + if ( ::ioctl(fd, JSIOCGCORR, oldCorr) == -1 ) + { + ::close(fd); + delete [] oldCorr; + return JoyDevice::ERR_GET_CORR; + } + + descr = name; + joyFd = fd; + axes = ax; + buttons = bt; + origCorr = oldCorr; + corr = new struct js_corr[axes]; + + amin = new int[axes]; + amax = new int[axes]; + + int i; + + for (i = 0; i < axes; i++) + resetMinMax(i); + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +void JoyDevice::close() +{ + if ( joyFd == -1 ) return; + + ::close(joyFd); + + joyFd = -1; + descr = ""; + + delete [] amin; + delete [] amax; + amin = 0; + amax = 0; + + delete [] corr; + corr = 0; + delete [] origCorr; + origCorr = 0; +} + +//-------------------------------------------------------------- + +int JoyDevice::axisMin(int axis) const +{ + if ( (axis < 0) || (axis >= axes) ) return 0; + + return amin[axis]; +} + +//-------------------------------------------------------------- + +int JoyDevice::axisMax(int axis) const +{ + if ( (axis < 0) || (axis >= axes) ) return 0; + + return amax[axis]; +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::initCalibration() +{ + if ( joyFd == -1 ) return JoyDevice::ERR_INIT_CAL; + + int i; + + // Reset all current correction values + for (i = 0; i < axes; i++) + { + corr[i].type = JS_CORR_NONE; + corr[i].prec = 0; + } + + if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 ) + return JoyDevice::ERR_INIT_CAL; + + for (i = 0; i < axes; i++) + corr[i].type = JS_CORR_BROKEN; + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::applyCalibration() +{ + if ( joyFd == -1 ) return JoyDevice::ERR_APPLY_CAL; + + if ( ::ioctl(joyFd, JSIOCSCORR, corr) == -1 ) + return JoyDevice::ERR_APPLY_CAL; + + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +void JoyDevice::resetMinMax(int axis, int value) +{ + amin[axis] = value; + amax[axis] = value; +} + +//-------------------------------------------------------------- + +void JoyDevice::calcPrecision() +{ + if ( !corr ) return; + + int i; + + for (i = 0; i < axes; i++) + { + corr[i].prec = amax[i] - amin[i]; + kDebug() << "Precision for axis: " << i << ": " << corr[i].prec; + } +} + +//-------------------------------------------------------------- + +JoyDevice::ErrorCode JoyDevice::restoreCorr() +{ + if ( joyFd == -1 ) return JoyDevice::SUCCESS; + + if ( ::ioctl(joyFd, JSIOCSCORR, origCorr) == -1 ) + return JoyDevice::ERR_RESTORE_CORR; + else + return JoyDevice::SUCCESS; +} + +//-------------------------------------------------------------- + +JoyDevice::~JoyDevice() +{ + close(); +} + +//-------------------------------------------------------------- + +bool JoyDevice::getEvent(JoyDevice::EventType &type, int &number, int &value) +{ + number = value = 0; + + int ret; + + fd_set readSet; + + FD_ZERO(&readSet); + FD_SET(joyFd, &readSet); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + + ret = ::select(joyFd + 1, &readSet, 0, 0, &timeout); + + if ( ret == 1 ) // got an event from the joystick + { + struct js_event e; + + if ( ::read(joyFd, &e, sizeof(struct js_event)) == sizeof(struct js_event) ) + { + if ( e.type & JS_EVENT_BUTTON ) + { + type = JoyDevice::BUTTON; + value = e.value; + number = e.number; + + return true; + } + + if ( e.type & JS_EVENT_AXIS ) + { + type = JoyDevice::AXIS; + value = e.value; + number = e.number; + + // store min, max values + if ( e.value < amin[number] ) amin[number] = e.value; + if ( e.value > amax[number] ) amax[number] = e.value; + + return true; + } + } + } + + return false; // no event +} + +//-------------------------------------------------------------- + +void JoyDevice::calcCorrection(int axis, int *min, int *center, int *max) +{ + const int MIN = 0; + const int MAX = 1; + + double a, b, c, d; + + a = center[MIN]; // inputs.cmin[1]; + b = center[MAX]; // inputs.cmax[1]; + c = 32767.0 / (center[MIN] - min[MAX]); // (inputs.cmin[1] - inputs.cmax[0]); + d = 32767.0 / (max[MIN] - center[MAX]); // (inputs.cmin[2] - inputs.cmax[1]); + + corr[axis].coef[0] = (int)rint(a); + corr[axis].coef[1] = (int)rint(b); + corr[axis].coef[2] = (int)rint(c*16384.0); + corr[axis].coef[3] = (int)rint(d*16384.0); + + kDebug() << "min min: " << min[0] << " max: " << min[1] ; + kDebug() << "max min: " << max[0] << " max: " << max[1] ; + kDebug() << "Correction values for axis: " << axis << ": " + << corr[axis].coef[0] << ", " + << corr[axis].coef[1] << ", " + << corr[axis].coef[2] << ", " + << corr[axis].coef[3] << endl; +} + +//-------------------------------------------------------------- diff --git a/kcms/hardware/joystick/joydevice.h b/kcms/hardware/joystick/joydevice.h new file mode 100644 index 0000000000..4c26581e44 --- /dev/null +++ b/kcms/hardware/joystick/joydevice.h @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 _JOYDEVICE_H_ +#define _JOYDEVICE_H_ + +#include + +#include + +#ifdef Q_OS_LINUX +#undef __STRICT_ANSI__ +#include +#define __STRICT_ANSI__ +#endif + +#ifdef Q_OS_FREEBSD +#include +#endif + +// helper class which holds all current values, file descriptor, etc. for +// one device +class JoyDevice +{ + public: + enum ErrorCode + { + SUCCESS, + OPEN_FAILED, + NO_JOYSTICK, + WRONG_VERSION, + ERR_GET_VERSION, + ERR_GET_BUTTONS, + ERR_GET_AXES, + ERR_GET_CORR, + ERR_RESTORE_CORR, + ERR_INIT_CAL, + ERR_APPLY_CAL + }; + + enum EventType + { + BUTTON, + AXIS + }; + + // devicefile to use, e.g. "/dev/js0" + JoyDevice(const QString &devicefile); + ~JoyDevice(); + + // returns one of the error-codes from above + ErrorCode open(); + + // return descriptive error text for given error code + QString errText(ErrorCode code) const; + + int fd() const { return joyFd; } + void close(); + ErrorCode restoreCorr(); + + // return devicefilename from constructor + const QString &device() const { return devName; } + + // descriptive text for this device read from the driver + QString text() const { return descr; } + + int numButtons() const { return buttons; } + int numAxes() const { return axes; } + int axisMin(int axis) const; + int axisMax(int axis) const; + + // read next event from device; returns true if there was an event during the short timeout + bool getEvent(JoyDevice::EventType &type, int &number, int &value); + + // methods for calibration + ErrorCode initCalibration(); // must be called first + void calcPrecision(); + + void resetMinMax(int axis, int value = 0); + + // calculate correction values + // min[2], center[2], max[2], index 0 == minimum, index 1 == maximum + void calcCorrection(int axis, int *min, int *center, int *max); + ErrorCode applyCalibration(); + + private: + QString devName; // device filename + QString descr; // descriptive text + int joyFd; + + int buttons; + int axes; + int *amin; // axes min values + int *amax; // axes max values + + struct js_corr *corr; // calibration values during the calib. steps + struct js_corr *origCorr; // original calibration correction values +}; + +#endif diff --git a/kcms/hardware/joystick/joystick.cpp b/kcms/hardware/joystick/joystick.cpp new file mode 100644 index 0000000000..c162211c09 --- /dev/null +++ b/kcms/hardware/joystick/joystick.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "joystick.h" +#include "joywidget.h" +#include "joydevice.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +//--------------------------------------------------------------------------------------------- + +K_PLUGIN_FACTORY(JoystickFactory, registerPlugin();) + +//--------------------------------------------------------------------------------------------- + +Joystick::Joystick(QWidget *parent, const QVariantList &) + : KCModule(parent) +{ + setButtons(Help); + setAboutData(new KAboutData("kcmjoystick", QString(), i18n("KDE Joystick Control Module"), "1.0", + i18n("KDE System Settings Module to test Joysticks"), + KAboutData::License_GPL, i18n("(c) 2004, Martin Koller"), + QString(), "kollix@aon.at")); + + setQuickHelp( i18n("

    Joystick

    " + "This module helps to check if your joystick is working correctly.
    " + "If it delivers wrong values for the axes, you can try to solve this with " + "the calibration.
    " + "This module tries to find all available joystick devices " + "by checking /dev/js[0-4] and /dev/input/js[0-4]
    " + "If you have another device file, enter it in the combobox.
    " + "The Buttons list shows the state of the buttons on your joystick, the Axes list " + "shows the current value for all axes.
    " + "NOTE: the current Linux device driver (Kernel 2.4, 2.6) can only autodetect" + "
      " + "
    • 2-axis, 4-button joystick
    • " + "
    • 3-axis, 4-button joystick
    • " + "
    • 4-axis, 4-button joystick
    • " + "
    • Saitek Cyborg 'digital' joysticks
    • " + "
    " + "(For details you can check your Linux source/Documentation/input/joystick.txt)" + )); + + joyWidget = new JoyWidget(this); + + QVBoxLayout *top = new QVBoxLayout(this); + top->setMargin(0); + top->setSpacing(KDialog::spacingHint()); + top->addWidget(joyWidget); +} + +//--------------------------------------------------------------------------------------------- + +void Joystick::load() +{ + joyWidget->init(); +} + +//--------------------------------------------------------------------------------------------- + +void Joystick::defaults() +{ + joyWidget->resetCalibration(); + + emit changed(true); +} + +//--------------------------------------------------------------------------------------------- + +#include "joystick.moc" diff --git a/kcms/hardware/joystick/joystick.desktop b/kcms/hardware/joystick/joystick.desktop new file mode 100644 index 0000000000..e5ff24a8b9 --- /dev/null +++ b/kcms/hardware/joystick/joystick.desktop @@ -0,0 +1,228 @@ +[Desktop Entry] +Exec=kcmshell5 joystick + +X-DocPath=kcontrol/joystick/index.html +Terminal=false +Type=Service +Icon=preferences-desktop-gaming +Categories=Qt;KDE;X-KDE-settings-hardware; + +X-KDE-ServiceTypes=KCModule +X-KDE-Library=kcm_joystick +X-KDE-Test-Module=true +X-KDE-System-Settings-Parent-Category=input-devices +X-KDE-ParentApp=kcontrol +X-KDE-Weight=70 + +Comment=Joystick settings +Comment[ar]=إعدادات عصى الألعاب +Comment[ast]=Preferencies del Joystick +Comment[be@latin]=Nałady džojstyka +Comment[bg]=Настройки на джойстик +Comment[bn]=জয়স্টিক সেটিংস +Comment[bn_IN]=জয়-স্টিক সংক্রান্ত বৈশিষ্ট্য +Comment[bs]=Postavke džojstika +Comment[ca]=Arranjament de la palanca de control +Comment[ca@valencia]=Arranjament de la palanca de control +Comment[cs]=Nastavení joysticku +Comment[csb]=Nastôw joysticka +Comment[da]=Joystick-indstillinger +Comment[de]=Joystick-Einstellungen +Comment[el]=Ρυθμίσεις χειριστηρίου +Comment[en_GB]=Joystick settings +Comment[eo]=Ludbastonaj agordoj +Comment[es]=Preferencias del Joystick +Comment[et]=Juhtpuldi seadistused +Comment[eu]=Kontrol-palankaren ezarpenak +Comment[fi]=Peliohjainten asetukset +Comment[fr]=Configuration du joystick +Comment[fy]=Joystick ynstellings +Comment[ga]=Socruithe an luamháin stiúrtha +Comment[gl]=Configuración do joystick +Comment[gu]=જોયસ્ટિક ગોઠવણીઓ +Comment[he]=הגדרות ג'ויסטיק +Comment[hi]=जॉयस्टिक विन्यास +Comment[hne]=जायस्टिक सेटिंग +Comment[hr]=Postavke igraće palice (joysticka) +Comment[hsb]=Nastajenja za joystick +Comment[hu]=Botkormány-beállítások +Comment[ia]=Preferentias de Joystick +Comment[id]=Pengaturan tongkat ria +Comment[is]=Stillingar stýripinna +Comment[it]=Impostazioni del joystick +Comment[ja]=ジョイスティックの設定 +Comment[kk]=Джойстик параметрлері +Comment[km]=ការ​កំណត់ Joystick +Comment[kn]=ಅಂಕೆಗೋಲು (ಜಾಯ್ ಸ್ಟಿಕ್) ಸಂಯೋಜನೆಗಳು +Comment[ko]=조이스틱 설정 +Comment[ku]=Mîhengên joystik +Comment[lt]=Valdymo svirties nustatymai +Comment[lv]=Kursorsviras iestatījumi +Comment[mai]=ज्वायस्टिक सेटिंग +Comment[mk]=Поставувања за палката за играње +Comment[ml]=ജോയ്സ്റ്റിക് സജ്ജീകരണങ്ങള്‍ +Comment[mr]=जॉयस्टीक् संयोजना +Comment[nb]=Styrespakinnstillinger +Comment[nds]=Joystick instellen +Comment[nl]=Joystick instellen +Comment[nn]=Innstillingar for styrespakar +Comment[or]=Joystick ସଂରଚନା +Comment[pa]=ਜਾਏਸਟਿੱਕ ਸੈਟਿੰਗ +Comment[pl]=Ustawienia joysticka +Comment[pt]=Configuração do 'joystick' +Comment[pt_BR]=Configurações do joystick +Comment[ro]=Configurări joystick +Comment[ru]=Настройка джойстика +Comment[si]=Joystick සැකසුම් +Comment[sk]=Nastavenie joysticku +Comment[sl]=Nastavitve igralne palice +Comment[sr]=Поставке џојстика +Comment[sr@ijekavian]=Поставке џојстика +Comment[sr@ijekavianlatin]=Postavke džojstika +Comment[sr@latin]=Postavke džojstika +Comment[sv]=Anpassa styrspak +Comment[ta]=ஜாய்ஸ்டிக் அமைப்புகள் +Comment[te]=Joystick అమరికలు +Comment[tg]=Танзимоти ҷойстик +Comment[th]=ตั้งค่าต่าง ๆ ของแท่งควบคุม +Comment[tr]=Oyun çubuğu ayarları +Comment[ug]=ئويۇن دەستە تەڭشەكلەر +Comment[uk]=Параметри джойстика +Comment[vi]=Thiết lập tay điều khiển trò chơi +Comment[wa]=Apontiaedje del djîsse di djeu +Comment[x-test]=xxJoystick settingsxx +Comment[zh_CN]=游戏杆设置 +Comment[zh_TW]=搖桿設定 +Name=Joystick +Name[af]=Joystick +Name[ar]=عصا الألعاب +Name[ast]=Joystick +Name[be]=Джойстык +Name[be@latin]=Džojstyk +Name[bg]=Джойстик +Name[bn]=জয়-স্টিক +Name[bn_IN]=জয়-স্টিক +Name[br]=Lanker-c'hoari +Name[bs]=Džojstik +Name[ca]=Palanca de control +Name[ca@valencia]=Palanca de control +Name[cs]=Joystick +Name[csb]=Joystick +Name[cy]=Ffôn reoli +Name[da]=Joystick +Name[de]=Joystick +Name[el]=Χειριστήριο +Name[en_GB]=Joystick +Name[eo]=Stirstango +Name[es]=Joystick +Name[et]=Juhtpult +Name[eu]=Kontrol-palanka +Name[fa]=اهرم کنترل +Name[fi]=Peliohjain +Name[fr]=Joystick +Name[fy]=Joystick +Name[ga]=Luamhán Stiúrtha +Name[gl]=Joystick +Name[gu]=જોયસ્ટિક +Name[he]=ג'ויסטיק +Name[hi]=जॉयस्टिक +Name[hne]=जायस्टिक +Name[hr]=Igraća palica +Name[hsb]=Joystick +Name[hu]=Botkormány +Name[ia]=Joystick +Name[id]=Tongkat Ria +Name[is]=Stýripinnar +Name[it]=Joystick +Name[ja]=ジョイスティック +Name[ka]=ჯოისტიკი +Name[kk]=Джойстик +Name[km]=យ៉យស្ទីក +Name[kn]=ಅಂಕೆಗೋಲು (ಜಾಯ್ ಸ್ಟಿಕ್) +Name[ko]=조이스틱 +Name[ku]=Joystîk +Name[lt]=Valdymo svirtis +Name[lv]=Kursorsvira +Name[mai]=जायस्टिक +Name[mk]=Џојстик +Name[ml]=ജോയ്സ്റ്റിക് +Name[mr]=जॉयस्टिक +Name[ms]=Kayu Bidik +Name[nb]=Styrespak +Name[nds]=Joystick +Name[ne]=जोयस्टिक +Name[nl]=Joystick +Name[nn]=Styrespak +Name[or]=Joystick +Name[pa]=ਜਾਏਸਟਿੱਕ +Name[pl]=Joystick +Name[pt]=Joystick +Name[pt_BR]=Joystick +Name[ro]=Joystick +Name[ru]=Джойстик +Name[se]=Stivrensággi +Name[si]=ජෝයිස්ටික් +Name[sk]=Joystick +Name[sl]=Igralna palica +Name[sr]=Џојстик +Name[sr@ijekavian]=Џојстик +Name[sr@ijekavianlatin]=Džojstik +Name[sr@latin]=Džojstik +Name[sv]=Styrspak +Name[ta]=இயக்கு கருவி +Name[te]=జాయ్ స్టిక్ +Name[tg]=Ҷойстик +Name[th]=แท่งควบคุม +Name[tr]=Oyun Çubuğu +Name[ug]=ئويۇن دەستىسى(رول) +Name[uk]=Джойстик +Name[uz]=Joystik +Name[uz@cyrillic]=Жойстик +Name[vi]=Tay điều khiển +Name[wa]=Djîsse di djeu +Name[xh]=Uvuyo +Name[x-test]=xxJoystickxx +Name[zh_CN]=游戏杆 +Name[zh_TW]=搖桿 + +X-KDE-Keywords=joystick,gamepad,controller +X-KDE-Keywords[bs]=dzojstik +X-KDE-Keywords[ca]=palanca de control,comandament de joc,controlador +X-KDE-Keywords[ca@valencia]=palanca de control,comandament de joc,controlador +X-KDE-Keywords[da]=joystick,gamepad,controller +X-KDE-Keywords[de]=Joystick,Gamepad,Spielsteuerung +X-KDE-Keywords[el]=χειριστήριο,πληκτρολόγιο παιχνιδιών,ελεγκτής +X-KDE-Keywords[es]=joystick,gamepad,controlador +X-KDE-Keywords[et]=juhtpult,juhtkang,kontroller +X-KDE-Keywords[eu]=kontrol-palanka,joko-teklatua,kontroladorea +X-KDE-Keywords[fi]=peliohjain,sauvaohjain,ohjain +X-KDE-Keywords[fr]=joystick, gamepad, contrôleur +X-KDE-Keywords[ga]=luamhán stiúrtha,ceap cluiche,rialaitheoir +X-KDE-Keywords[gl]=joystick, gamepad, controlador +X-KDE-Keywords[hu]=botkormány,játéktábla,vezérlő +X-KDE-Keywords[ia]=joystick,gamepad,controlator +X-KDE-Keywords[it]=joystick,gamepad,controller +X-KDE-Keywords[kk]=joystick,gamepad,controller +X-KDE-Keywords[km]=joystick,gamepad,controller +X-KDE-Keywords[ko]=joystick,gamepad,controller,조이스틱,컨트롤러 +X-KDE-Keywords[mr]=जॉयस्टिक, गेमपॅड, कन्ट्रोलर +X-KDE-Keywords[nb]=styrespak,spillepute,kontroller +X-KDE-Keywords[nds]=Stüerknüppel,Speelknüppel,Speelstüer-Reedschap,Speelstüern,Stüern,Kontroller,Speelkuntrull +X-KDE-Keywords[nl]=joystick,spelpad,besturing +X-KDE-Keywords[pa]=ਜਾਏਸਟਿੱਕ,ਗੇਮਪੈਡ,ਕੰਟਰੋਲਰ +X-KDE-Keywords[pl]=joystick,gamepad,kontroler +X-KDE-Keywords[pt]=joystick,comando,controlador +X-KDE-Keywords[pt_BR]=joystick,gamepad,controle +X-KDE-Keywords[ru]=joystick,gamepad,controller,джойстик,геймпад,контроллер +X-KDE-Keywords[sk]=joystick,gamepad,ovládač +X-KDE-Keywords[sl]=igralna palica,igralni plošček,igralne naprave,krmilnik +X-KDE-Keywords[sr]=joystick,gamepad,controller,џојстик,гејмпад,управљач +X-KDE-Keywords[sr@ijekavian]=joystick,gamepad,controller,џојстик,гејмпад,управљач +X-KDE-Keywords[sr@ijekavianlatin]=joystick,gamepad,controller,džojstik,gejmpad,upravljač +X-KDE-Keywords[sr@latin]=joystick,gamepad,controller,džojstik,gejmpad,upravljač +X-KDE-Keywords[sv]=styrspak,handkontroll,styrning +X-KDE-Keywords[tr]=oyun çubuğu, denetleyici,joystick, oyun oynama kolu +X-KDE-Keywords[uk]=joystick,gamepad,джойстик,геймпад,контролер +X-KDE-Keywords[x-test]=xxjoystick,gamepad,controllerxx +X-KDE-Keywords[zh_CN]=joystick,gamepad,controller,手柄,摇杆,控制器 +X-KDE-Keywords[zh_TW]=joystick,gamepad,controller diff --git a/kcms/hardware/joystick/joystick.h b/kcms/hardware/joystick/joystick.h new file mode 100644 index 0000000000..fedf3a4b75 --- /dev/null +++ b/kcms/hardware/joystick/joystick.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2003 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 _JOYSTICK_H_ +#define _JOYSTICK_H_ + +#define KDE3_SUPPORT +#include +#undef KDE3_SUPPORT + +class JoyWidget; + + +/* on FreeBSD the header already has a struct joystick, so we can't use the same name here, Alex */ +class Joystick: public KCModule +{ + Q_OBJECT + + public: + explicit Joystick(QWidget *parent = 0, const QVariantList &list = QVariantList()); + + virtual void load(); + virtual void defaults(); + + private: + JoyWidget *joyWidget; +}; + +#endif diff --git a/kcms/hardware/joystick/joywidget.cpp b/kcms/hardware/joystick/joywidget.cpp new file mode 100644 index 0000000000..9140213cd0 --- /dev/null +++ b/kcms/hardware/joystick/joywidget.cpp @@ -0,0 +1,418 @@ +/*************************************************************************** + * Copyright (C) 2003,2012 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "joywidget.h" +#include "joydevice.h" +#include "poswidget.h" +#include "caldialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//-------------------------------------------------------------- +static QString PRESSED = I18N_NOOP("PRESSED"); +//-------------------------------------------------------------- + +class TableWidget : public QTableWidget +{ + public: + TableWidget(int row, int col) : QTableWidget(row, col) {} + + virtual QSize sizeHint() const + { + return QSize(150, 100); // return a smaller size than the Qt default(256, 192) + } +}; + +//-------------------------------------------------------------- + +JoyWidget::JoyWidget(QWidget *parent) + : QWidget(parent), idle(0), joydev(0) +{ + QVBoxLayout *mainVbox = new QVBoxLayout(this); + mainVbox->setSpacing(KDialog::spacingHint()); + mainVbox->setMargin(0); + + // create area to show an icon + message if no joystick was detected + { + messageBox = new KMessageWidget(this); + messageBox->setMessageType(KMessageWidget::Error); + messageBox->setCloseButtonVisible(false); + messageBox->hide(); + + mainVbox->addWidget(messageBox); + } + + QHBoxLayout *devHbox = new QHBoxLayout; + devHbox->setSpacing(KDialog::spacingHint()); + devHbox->addWidget(new QLabel(i18n("Device:"))); + devHbox->addWidget(device = new KComboBox(true)); + + device->setInsertPolicy(QComboBox::NoInsert); + KUrlCompletion *kc = new KUrlCompletion(KUrlCompletion::FileCompletion); + device->setCompletionObject(kc); + device->setAutoDeleteCompletionObject(true); + connect(device, SIGNAL(activated(QString)), this, SLOT(deviceChanged(QString))); + connect(device, SIGNAL(returnPressed(QString)), this, SLOT(deviceChanged(QString))); + devHbox->setStretchFactor(device, 3); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setSpacing(KDialog::spacingHint()); + + mainVbox->addLayout(devHbox); + mainVbox->addLayout(hbox); + + QVBoxLayout *vboxLeft = new QVBoxLayout; + vboxLeft->setSpacing(KDialog::spacingHint()); + vboxLeft->addWidget(new QLabel(i18nc("Cue for deflection of the stick", "Position:"))); + vboxLeft->addWidget(xyPos = new PosWidget); + + vboxLeft->addWidget(trace = new QCheckBox(i18n("Show trace"))); + connect(trace, SIGNAL(toggled(bool)), this, SLOT(traceChanged(bool))); + + QVBoxLayout *vboxMid = new QVBoxLayout; + vboxMid->setSpacing(KDialog::spacingHint()); + + QVBoxLayout *vboxRight = new QVBoxLayout; + vboxRight->setSpacing(KDialog::spacingHint()); + + // calculate the column width we need + QFontMetrics fm(font()); + int colWidth = qMax(fm.width(PRESSED), fm.width("-32767")) + 10; // -32767 largest string + + vboxMid->addWidget(new QLabel(i18n("Buttons:"))); + buttonTbl = new TableWidget(0, 1); + buttonTbl->setSelectionMode(QAbstractItemView::NoSelection); + buttonTbl->setEditTriggers(QAbstractItemView::NoEditTriggers); + buttonTbl->setHorizontalHeaderLabels(QStringList(i18n("State"))); + buttonTbl->setSortingEnabled(false); + buttonTbl->horizontalHeader()->setClickable(false); + buttonTbl->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + buttonTbl->horizontalHeader()->resizeSection(0, colWidth); + buttonTbl->verticalHeader()->setClickable(false); + vboxMid->addWidget(buttonTbl); + + vboxRight->addWidget(new QLabel(i18n("Axes:"))); + axesTbl = new TableWidget(0, 1); + axesTbl->setSelectionMode(QAbstractItemView::NoSelection); + axesTbl->setEditTriggers(QAbstractItemView::NoEditTriggers); + axesTbl->setHorizontalHeaderLabels(QStringList(i18n("Value"))); + axesTbl->setSortingEnabled(false); + axesTbl->horizontalHeader()->setClickable(false); + axesTbl->horizontalHeader()->setResizeMode(QHeaderView::Stretch); + axesTbl->horizontalHeader()->resizeSection(0, colWidth); + axesTbl->verticalHeader()->setClickable(false); + vboxRight->addWidget(axesTbl); + + hbox->addLayout(vboxLeft); + hbox->addLayout(vboxMid); + hbox->addLayout(vboxRight); + + // calibrate button + calibrate = new QPushButton(i18n("Calibrate")); + connect(calibrate, SIGNAL(clicked()), this, SLOT(calibrateDevice())); + calibrate->setEnabled(false); + + vboxLeft->addStretch(); + vboxLeft->addWidget(calibrate); + + // set up a timer for idle processing of joystick events + idle = new QTimer(this); + connect(idle, SIGNAL(timeout()), this, SLOT(checkDevice())); + + // check which devicefiles we have + init(); +} + +//-------------------------------------------------------------- + +JoyWidget::~JoyWidget() +{ + delete joydev; +} + +//-------------------------------------------------------------- + +void JoyWidget::init() +{ + // check which devicefiles we have + int i; + bool first = true; + char dev[30]; + + device->clear(); + buttonTbl->setRowCount(0); + axesTbl->setRowCount(0); + + for (i = 0; i < 5; i++) // check the first 5 devices + { + sprintf(dev, "/dev/js%d", i); // first look in /dev + JoyDevice *joy = new JoyDevice(dev); + + if ( joy->open() != JoyDevice::SUCCESS ) + { + delete joy; + sprintf(dev, "/dev/input/js%d", i); // then look in /dev/input + joy = new JoyDevice(dev); + + if ( joy->open() != JoyDevice::SUCCESS ) + { + delete joy; + continue; // try next number + } + } + + // we found one + + device->addItem(QString("%1 (%2)").arg(joy->text()).arg(joy->device())); + + // display values for first device + if ( first ) + { + showDeviceProps(joy); // this sets the joy object into this->joydev + first = false; + } + else + delete joy; + } + + /* KDE 4: Remove this check(and i18n) when all KCM wrappers properly test modules */ + if ( device->count() == 0 ) + { + messageBox->show(); + messageBox->setText(QString("%1").arg( + i18n("No joystick device automatically found on this computer.
    " + "Checks were done in /dev/js[0-4] and /dev/input/js[0-4]
    " + "If you know that there is one attached, please enter the correct device file."))); + } +} + +//-------------------------------------------------------------- + +void JoyWidget::traceChanged(bool state) +{ + xyPos->showTrace(state); +} + +//-------------------------------------------------------------- + +void JoyWidget::restoreCurrDev() +{ + if ( !joydev ) // no device open + { + device->setEditText(""); + calibrate->setEnabled(false); + } + else + { + // try to find the current open device in the combobox list + int index = device->findText(joydev->device(), Qt::MatchContains); + + if ( index == -1 ) // the current open device is one the user entered (not in the list) + device->setEditText(joydev->device()); + else + device->setEditText(device->itemText(index)); + } +} + +//-------------------------------------------------------------- + +void JoyWidget::deviceChanged(const QString &dev) +{ + // find "/dev" in given string + int start, stop; + QString devName; + + if ( (start = dev.indexOf("/dev")) == -1 ) + { + KMessageBox::sorry(this, + i18n("The given device name is invalid (does not contain /dev).\n" + "Please select a device from the list or\n" + "enter a device file, like /dev/js0."), i18n("Unknown Device")); + + restoreCurrDev(); + return; + } + + if ( (stop = dev.indexOf(")", start)) != -1 ) // seems to be text selected from our list + devName = dev.mid(start, stop - start); + else + devName = dev.mid(start); + + if ( joydev && (devName == joydev->device()) ) return; // user selected the current device; ignore it + + JoyDevice *joy = new JoyDevice(devName); + JoyDevice::ErrorCode ret = joy->open(); + + if ( ret != JoyDevice::SUCCESS ) + { + KMessageBox::error(this, joy->errText(ret), i18n("Device Error")); + + delete joy; + restoreCurrDev(); + return; + } + + showDeviceProps(joy); +} + +//-------------------------------------------------------------- + +void JoyWidget::showDeviceProps(JoyDevice *joy) +{ + joydev = joy; + + buttonTbl->setRowCount(joydev->numButtons()); + + axesTbl->setRowCount(joydev->numAxes()); + if ( joydev->numAxes() >= 2 ) + { + axesTbl->setVerticalHeaderItem(0, new QTableWidgetItem(i18n("1(x)"))); + axesTbl->setVerticalHeaderItem(1, new QTableWidgetItem(i18n("2(y)"))); + } + + calibrate->setEnabled(true); + idle->start(0); + + // make both tables use the same space for header; this looks nicer + // TODO: Don't know how to do this in Qt4; the following does no longer work + // Probably by setting a sizeHint for every single header item ? + /* + buttonTbl->verticalHeader()->setFixedWidth(qMax(buttonTbl->verticalHeader()->width(), + axesTbl->verticalHeader()->width())); + axesTbl->verticalHeader()->setFixedWidth(buttonTbl->verticalHeader()->width()); + */ +} + +//-------------------------------------------------------------- + +void JoyWidget::checkDevice() +{ + if ( !joydev ) return; // no open device yet + + JoyDevice::EventType type; + int number, value; + + if ( !joydev->getEvent(type, number, value) ) + return; + + if ( type == JoyDevice::BUTTON ) + { + if ( ! buttonTbl->item(number, 0) ) + buttonTbl->setItem(number, 0, new QTableWidgetItem()); + + if ( value == 0 ) // button release + buttonTbl->item(number, 0)->setText("-"); + else + buttonTbl->item(number, 0)->setText(PRESSED); + } + + if ( type == JoyDevice::AXIS ) + { + if ( number == 0 ) // x-axis + xyPos->changeX(value); + + if ( number == 1 ) // y-axis + xyPos->changeY(value); + + if ( ! axesTbl->item(number, 0) ) + axesTbl->setItem(number, 0, new QTableWidgetItem()); + + axesTbl->item(number, 0)->setText(QString("%1").arg(int(value))); + } +} + +//-------------------------------------------------------------- + +void JoyWidget::calibrateDevice() +{ + if ( !joydev ) return; // just to be save + + JoyDevice::ErrorCode ret = joydev->initCalibration(); + + if ( ret != JoyDevice::SUCCESS ) + { + KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error")); + return; + } + + if ( KMessageBox::messageBox(this, KMessageBox::Information, + i18n("Calibration is about to check the precision.

    " + "Please move all axes to their center position and then " + "do not touch the joystick anymore.

    " + "Click OK to start the calibration.
    "), + i18n("Calibration"), + KStandardGuiItem::ok(), KStandardGuiItem::cancel()) != KMessageBox::Ok ) + return; + + idle->stop(); // stop the joystick event getting; this must be done inside the calibrate dialog + + CalDialog dlg(this, joydev); + dlg.calibrate(); + + // user canceled somewhere during calibration, therefore the device is in a bad state + if ( dlg.result() == QDialog::Rejected ) + joydev->restoreCorr(); + + idle->start(0); // continue with event getting +} + +//-------------------------------------------------------------- + +void JoyWidget::resetCalibration() +{ + if ( !joydev ) return; // just to be save + + JoyDevice::ErrorCode ret = joydev->restoreCorr(); + + if ( ret != JoyDevice::SUCCESS ) + { + KMessageBox::error(this, joydev->errText(ret), i18n("Communication Error")); + } + else + { + KMessageBox::information(this, + i18n("Restored all calibration values for joystick device %1.", joydev->device()), + i18n("Calibration Success")); + } +} + +//-------------------------------------------------------------- + +#include "joywidget.moc" diff --git a/kcms/hardware/joystick/joywidget.h b/kcms/hardware/joystick/joywidget.h new file mode 100644 index 0000000000..74e99d170a --- /dev/null +++ b/kcms/hardware/joystick/joywidget.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2003,2005,2006 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 _JOYWIDGET_H_ +#define _JOYWIDGET_H_ + +#include + +class JoyDevice; + +class PosWidget; +class QLabel; +class QTableWidget; +class QTimer; +class KComboBox; +class KMessageWidget; +class QPushButton; +class QCheckBox; +class QFrame; + +// the widget which displays all buttons, values, etc. +class JoyWidget : public QWidget +{ + Q_OBJECT + + public: + JoyWidget(QWidget *parent = 0); + + ~JoyWidget(); + + // initialize list of possible devices and open the first available + void init(); + + public Q_SLOTS: + // reset calibration values to their value when this KCM was started + void resetCalibration(); + + private Q_SLOTS: + void checkDevice(); + void deviceChanged(const QString &dev); + void traceChanged(bool); + void calibrateDevice(); + + private: + void showDeviceProps(JoyDevice *joy); // fill widgets with given device parameters + void restoreCurrDev(); // restores the content of the combobox to reflect the current open device + + private: + KMessageWidget *messageBox; // in case of no device, show here a message rather than in a dialog + KComboBox *device; + PosWidget *xyPos; + QTableWidget *buttonTbl; + QTableWidget *axesTbl; + QCheckBox *trace; + QPushButton *calibrate; + + QTimer *idle; + + JoyDevice *joydev; +}; + +#endif diff --git a/kcms/hardware/joystick/poswidget.cpp b/kcms/hardware/joystick/poswidget.cpp new file mode 100644 index 0000000000..50b3b0fbfb --- /dev/null +++ b/kcms/hardware/joystick/poswidget.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** + * Copyright (C) 2003,2005,2006 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 "poswidget.h" + +#include + +#define XY_WIDTH 220 +#define MARK_WIDTH 10 +#define MAX_POINTS 500 + +//----------------------------------------------------------------- + +PosWidget::PosWidget(QWidget *parent) + : QWidget(parent), x(0), y(0), trace(false) +{ + setMinimumSize(XY_WIDTH, XY_WIDTH); + setMaximumSize(XY_WIDTH, XY_WIDTH); + + QPalette palette; + palette.setColor(backgroundRole(), Qt::white); + setPalette(palette); +} + +//----------------------------------------------------------------- + +void PosWidget::paintEvent(QPaintEvent *) +{ + QPainter paint(this); + + // draw a frame + paint.drawRect(0, 0, width()-1, height()-1); + paint.setPen(Qt::gray); + + // draw a center grid + paint.drawLine(XY_WIDTH/2, 1, + XY_WIDTH/2, XY_WIDTH - 2); + + paint.drawLine(1, XY_WIDTH/2, + XY_WIDTH - 2, XY_WIDTH/2); + + // draw the trace of previous points + if ( trace ) + { + paint.setPen(Qt::black); + + for (int i = 0; i < tracePoints.count()-2; i++) + paint.drawLine(tracePoints[i], tracePoints[i+1]); + + if ( tracePoints.count() > 0 ) + paint.drawLine(tracePoints[tracePoints.count()-1], QPoint(x, y)); + } + + // draw the current position marker + paint.setPen(Qt::blue); + + paint.drawLine(x - MARK_WIDTH/2, y - MARK_WIDTH/2, + x + MARK_WIDTH/2, y + MARK_WIDTH/2); + + paint.drawLine(x - MARK_WIDTH/2, y + MARK_WIDTH/2, + x + MARK_WIDTH/2, y - MARK_WIDTH/2); +} + +//----------------------------------------------------------------- + +void PosWidget::changeX(int newX) +{ + // transform coordinates from joystick to widget coordinates + newX = int((newX/65535.0)*XY_WIDTH + XY_WIDTH/2); + + if ( x == newX ) return; // avoid unnecessary redraw + + if ( trace ) + { + tracePoints.append(QPoint(x, y)); + if ( tracePoints.count() == MAX_POINTS ) + tracePoints.removeFirst(); + } + + x = newX; + update(); +} + +//----------------------------------------------------------------- + +void PosWidget::changeY(int newY) +{ + // transform coordinates from joystick to widget coordinates + newY = int((newY/65535.0)*XY_WIDTH + XY_WIDTH/2); + + if ( y == newY ) return; // avoid unnecessary redraw + + if ( trace ) + { + tracePoints.append(QPoint(x, y)); + if ( tracePoints.count() == MAX_POINTS ) + tracePoints.removeFirst(); + } + + y = newY; + update(); +} + +//----------------------------------------------------------------- + +void PosWidget::showTrace(bool t) +{ + trace = t; + tracePoints.clear(); + + update(); +} + +//----------------------------------------------------------------- + +#include "poswidget.moc" diff --git a/kcms/hardware/joystick/poswidget.h b/kcms/hardware/joystick/poswidget.h new file mode 100644 index 0000000000..671cfedfdf --- /dev/null +++ b/kcms/hardware/joystick/poswidget.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2003,2005,2006 by Martin Koller * + * kollix@aon.at * + * This file is part of the KDE Control Center Module for Joysticks * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the 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 _POSWIDGET_H_ +#define _POSWIDGET_H_ + +#include +#include +class QPaintEvent; + +/** + Widget to display the joystick-selected (x,y) position +*/ +class PosWidget : public QWidget +{ + Q_OBJECT + + public: + PosWidget(QWidget *parent = 0); + + void changeX(int x); + void changeY(int y); + + // define if a trace of the moving joystick shall be displayed + // changing it will erase all previous marks from the widget + void showTrace(bool t); + + protected: + virtual void paintEvent(QPaintEvent *); + + private: + int x, y; + bool trace; + QList tracePoints; +}; + +#endif diff --git a/kcms/input/AUTHORS b/kcms/input/AUTHORS new file mode 100644 index 0000000000..2ab4353d7c --- /dev/null +++ b/kcms/input/AUTHORS @@ -0,0 +1,7 @@ +Mouse & Keyboard Configuration Modules: + + Pat Dowler (dowler@pt1B1106.FSH.UVic.CA) + +Conversion to kcontrol applet: + + Matthias Hoelzer (hoelzer@physik.uni-wuerzburg.de) diff --git a/kcms/input/CMakeLists.txt b/kcms/input/CMakeLists.txt new file mode 100644 index 0000000000..354f7acf32 --- /dev/null +++ b/kcms/input/CMakeLists.txt @@ -0,0 +1,115 @@ + +add_subdirectory( pics ) + +configure_file (config-kcontrol-input.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kcontrol-input.h ) + +include_directories( ${LIBUSB_INCLUDE_DIR} ) + +if(X11_Xcursor_FOUND) + set( libnoinst_SRCS + xcursor/themepage.cpp + xcursor/thememodel.cpp + xcursor/cursortheme.cpp + xcursor/xcursortheme.cpp + xcursor/previewwidget.cpp + xcursor/itemdelegate.cpp + xcursor/sortproxymodel.cpp + ../krdb/krdb.cpp ) + qt5_wrap_ui( libnoinst_SRCS xcursor/themepage.ui ) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/xcursor/ ) +else() + set( libnoinst_SRCS core/themepage.cpp ) + include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/core/ ) +endif() + +set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) +qt5_add_dbus_interface(libnoinst_SRCS ${klauncher_xml} klauncher_iface) + + +########### next target ############### + +set(kapplymousetheme_SRCS kapplymousetheme.cpp ) + + +add_executable(kapplymousetheme ${kapplymousetheme_SRCS}) + +target_link_libraries(kapplymousetheme ${X11_Xrender_LIB} ${X11_X11_LIB}) +if (X11_Xcursor_FOUND) + target_link_libraries(kapplymousetheme ${X11_Xcursor_LIB}) +endif () + +install(TARGETS kapplymousetheme ${INSTALL_TARGETS_DEFAULT_ARGS}) + + +########### next target ############### + +set(kcm_input_PART_SRCS mouse.cpp main.cpp logitechmouse.cpp) + + +qt5_wrap_ui(kcm_input_PART_SRCS kmousedlg.ui logitechmouse_base.ui ) +qt5_add_dbus_interface(kcm_input_PART_SRCS ${klauncher_xml} klauncher_iface) + +add_library(kcm_input MODULE ${kcm_input_PART_SRCS}) +set_target_properties(kcm_input PROPERTIES COMPILE_FLAGS -DHAVE_X11=1) + + +target_link_libraries(kcm_input + Qt5::DBus + Qt5::X11Extras + KF5::KCMUtils + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::KDE4Support + ${X11_LIBRARIES} + ${LIBUSB_LIBRARIES} + ) +if (X11_Xcursor_FOUND) + target_link_libraries(kcm_input ${X11_Xcursor_LIB}) +endif () +if (X11_Xfixes_FOUND) + target_link_libraries(kcm_input ${X11_Xfixes_LIB}) +endif () + +install(TARGETS kcm_input DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### next target ############### + +set(kcm_cursortheme_PART_SRCS kcmcursortheme.cpp ${libnoinst_SRCS}) + +add_library(kcm_cursortheme MODULE ${kcm_cursortheme_PART_SRCS}) +set_target_properties(kcm_cursortheme PROPERTIES COMPILE_FLAGS -DHAVE_X11=1) + + +target_link_libraries(kcm_cursortheme + Qt5::DBus + Qt5::X11Extras + KF5::Archive + KF5::KCMUtils + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::KDE4Support + KF5::NewStuff + ${X11_LIBRARIES} + ${XCB_XCB_LIBRARY} +) + +if (X11_Xcursor_FOUND) + target_link_libraries(kcm_cursortheme ${X11_Xcursor_LIB}) +endif () +if (X11_Xfixes_FOUND) + target_link_libraries(kcm_cursortheme ${X11_Xfixes_LIB}) +endif () + +install(TARGETS kcm_cursortheme DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES mouse.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES cursortheme.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES cursor_large_black.pcf.gz cursor_large_white.pcf.gz cursor_small_white.pcf.gz DESTINATION ${DATA_INSTALL_DIR}/kcminput ) +install( FILES xcursor/xcursor.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) + diff --git a/kcms/input/ChangeLog b/kcms/input/ChangeLog new file mode 100644 index 0000000000..2d9b8d545e --- /dev/null +++ b/kcms/input/ChangeLog @@ -0,0 +1,11 @@ +2002-07-01 Fabian Wolf + * added option to select a white cursor + +2000-03-14 David Faure + + * mouse.cpp: Added global settings for SC/DC/AutoSelect/ChangeCursor + * mousedefaults.h: New file, to store default values + +1998-11-30 Alex Zepeda + + * Makefile.am: Move all the icons into pics/ && pics/mini/ diff --git a/kcms/input/Messages.sh b/kcms/input/Messages.sh new file mode 100644 index 0000000000..b039def2e6 --- /dev/null +++ b/kcms/input/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find -name \*.ui` >> rc.cpp || exit 11 +$XGETTEXT *.cpp */*.cpp -o $podir/kcminput.pot +rm -f rc.cpp diff --git a/kcms/input/config-kcontrol-input.h.cmake b/kcms/input/config-kcontrol-input.h.cmake new file mode 100644 index 0000000000..ce817d8e5f --- /dev/null +++ b/kcms/input/config-kcontrol-input.h.cmake @@ -0,0 +1,3 @@ +/* Defined if you have libusb */ +#cmakedefine HAVE_LIBUSB 1 + diff --git a/kcms/input/consoleUserPerms b/kcms/input/consoleUserPerms new file mode 100755 index 0000000000..015df642f1 --- /dev/null +++ b/kcms/input/consoleUserPerms @@ -0,0 +1,42 @@ +#!/bin/bash +# +# /etc/hotplug/usb/consoleUserPerms +# +# Sets up newly plugged in USB device so that the user who owns +# the console according to pam_console can access it from user space +# +# Note that for this script to work, you'll need all of the following: +# a) a line in the file /etc/hotplug/usb.usermap or another usermap file +# in /etc/hotplug/usb/ that corresponds to the device you are using. +# b) a setup using pam_console creates the respective lock files +# containing the name of the respective user. You can check for that +# by executing "echo `cat /var/{run,lock}/console.lock`" and +# verifying the appropriate user is mentioned somewhere there. +# c) a Linux kernel supporting hotplug and usbdevfs +# d) the hotplug package (http://linux-hotplug.sourceforge.net/) +# +# In the usermap file, the first field "usb module" should be named +# "consoleUserPerms" to invoke this script. +# + +if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ] +then + # New code, using lock files instead of copying /dev/console permissions + # This also works with non-kdm logins (e.g. on a virtual terminal) + # Idea and code from Nalin Dahyabhai + if [ -f /var/run/console.lock ] + then + CONSOLEOWNER=`cat /var/run/console.lock` + elif [ -f /var/lock/console.lock ] + then + CONSOLEOWNER=`cat /var/lock/console.lock` + else + CONSOLEOWNER= + fi + if [ -n "$CONSOLEOWNER" ] + then + chmod 0000 "${DEVICE}" + chown "$CONSOLEOWNER" "${DEVICE}" + chmod 0600 "${DEVICE}" + fi +fi diff --git a/kcms/input/core/bitmaps.h b/kcms/input/core/bitmaps.h new file mode 100644 index 0000000000..1a8e272e68 --- /dev/null +++ b/kcms/input/core/bitmaps.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2003 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 __BITMAPS_H +#define __BITMAPS_H + + +static const char* const arrow_large_black_xpm[] = { +"24 24 3 1", +"# c None", +"a c #000000", +". c #ffffff", +"#####..#################", +"#####.a.################", +"#####.aa.###############", +"#####.aaa.##############", +"#####.aaaa.#############", +"#####.aaaaa.############", +"#####.aaaaaa.###########", +"#####.aaaaaaa.##########", +"#####.aaaaaaaa.#########", +"#####.aaaaaaaaa.########", +"#####.aaaaaaaaaa.#######", +"#####.aaaaaaaaaaa.######", +"#####.aaaaaaaaaaaa.#####", +"#####.aaaaaaaa....######", +"#####.aaaaaaa.##########", +"#####.aaa.aaaa.#########", +"#####.aa.#.aaa.#########", +"#####.a.##.aaaa.########", +"#####..####.aaa.########", +"###########.aaaa.#######", +"############.aaa.#######", +"############.aaa.#######", +"#############...########", +"########################"}; + + +static const char* const arrow_small_black_xpm[]={ +"24 24 3 1", +"# c None", +"a c #000000", +". c #ffffff", +"########################", +"########################", +"########################", +"########################", +"#######..###############", +"#######.a.##############", +"#######.aa.#############", +"#######.aaa.############", +"#######.aaaa.###########", +"#######.aaaaa.##########", +"#######.aaaaaa.#########", +"#######.aaaaaaa.########", +"#######.aaaaaaaa.#######", +"#######.aaaaa....#######", +"#######.aa.aa.##########", +"#######.a.#.aa.#########", +"#######..##.aa.#########", +"############.aa.########", +"############.aa.########", +"#############..#########", +"########################", +"########################", +"########################", +"########################"}; + + +static const char* const arrow_large_white_xpm[] = { +"24 24 3 1", +"# c None", +"a c #ffffff", +". c #000000", +"#####..#################", +"#####.a.################", +"#####.aa.###############", +"#####.aaa.##############", +"#####.aaaa.#############", +"#####.aaaaa.############", +"#####.aaaaaa.###########", +"#####.aaaaaaa.##########", +"#####.aaaaaaaa.#########", +"#####.aaaaaaaaa.########", +"#####.aaaaaaaaaa.#######", +"#####.aaaaaaaaaaa.######", +"#####.aaaaaaaaaaaa.#####", +"#####.aaaaaaaa....######", +"#####.aaaaaaa.##########", +"#####.aaa.aaaa.#########", +"#####.aa.#.aaa.#########", +"#####.a.##.aaaa.########", +"#####..####.aaa.########", +"###########.aaaa.#######", +"############.aaa.#######", +"############.aaa.#######", +"#############...########", +"########################"}; + + +static const char* const arrow_small_white_xpm[]={ +"24 24 3 1", +"# c None", +"a c #ffffff", +". c #000000", +"########################", +"########################", +"########################", +"########################", +"#######..###############", +"#######.a.##############", +"#######.aa.#############", +"#######.aaa.############", +"#######.aaaa.###########", +"#######.aaaaa.##########", +"#######.aaaaaa.#########", +"#######.aaaaaaa.########", +"#######.aaaaaaaa.#######", +"#######.aaaaa....#######", +"#######.aa.aa.##########", +"#######.a.#.aa.#########", +"#######..##.aa.#########", +"############.aa.########", +"############.aa.########", +"#############..#########", +"########################", +"########################", +"########################", +"########################"}; + +#endif diff --git a/kcms/input/core/themepage.cpp b/kcms/input/core/themepage.cpp new file mode 100644 index 0000000000..5e8ffc42d3 --- /dev/null +++ b/kcms/input/core/themepage.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2003 Fredrik Höglund + * + * Based on the large cursor code written by Rik Hemsley, + * Copyright (c) 2000 Rik Hemsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "themepage.h" +#include +#include "themepage.moc" + +#include "bitmaps.h" + + + +ThemePage::ThemePage( QWidget* parent, const char* name ) + : QWidget( parent ) +{ + setObjectName(name); + QBoxLayout *layout = new QVBoxLayout( this ); + layout->setMargin( KDialog::marginHint() ); + layout->setSpacing( KDialog::spacingHint() ); + + layout->addWidget(new QLabel( i18n("Select the cursor theme you want to use:"), this )); + + // Create the theme list view + listview = new QTreeWidget( this ); + QStringList lstHeader; + lstHeader<setHeaderLabels( lstHeader ); + listview->setSelectionMode( QAbstractItemView::SingleSelection ); + listview->setRootIsDecorated( false ); + connect( listview, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)) + , this, SLOT(selectionChanged(QTreeWidgetItem*,QTreeWidgetItem*)) ); + layout->addWidget( listview ); + insertThemes(); +} + + +ThemePage::~ThemePage() +{ +} + + +void ThemePage::selectionChanged( QTreeWidgetItem*current,QTreeWidgetItem*previous ) +{ + Q_UNUSED( previous ); + selectedTheme = current->data( 0, Qt::UserRole + 1 ).toString(); + emit changed( selectedTheme != currentTheme ); +} + + +void ThemePage::save() +{ + if ( currentTheme == selectedTheme ) + return; + + bool whiteCursor = selectedTheme.right( 5 ) == "White"; + bool largeCursor = selectedTheme.left( 5 ) == "Large"; + + KConfig config( "kcminputrc" ); + KConfigGroup c( &config, "Mouse" ); + c.writeEntry( "LargeCursor", largeCursor ); + c.writeEntry( "WhiteCursor", whiteCursor ); + + currentTheme = selectedTheme; + + fixCursorFile(); + + KMessageBox::information( this, i18n("You have to restart KDE for these " + "changes to take effect."), i18n("Cursor Settings Changed"), + "CursorSettingsChanged" ); +} + + +void ThemePage::load() +{ + bool largeCursor, whiteCursor; + + KConfig config( "kcminputrc" ); + KConfigGroup c( &config, "Mouse" ); + largeCursor = c.readEntry( "LargeCursor", false); + whiteCursor = c.readEntry( "WhiteCursor", false); + + if ( largeCursor ) + currentTheme = whiteCursor ? "LargeWhite" : "LargeBlack"; + else + currentTheme = whiteCursor ? "SmallWhite" : "SmallBlack"; + + selectedTheme = currentTheme; + for ( int i = 0;i topLevelItemCount();++i ) + { + QTreeWidgetItem *item = listview->topLevelItem( i ); + if ( item && item->data(0, Qt::UserRole + 1 ) == currentTheme ) + { + listview->setCurrentItem( item ); + } + } +} + + +void ThemePage::defaults() +{ + currentTheme = selectedTheme = "SmallBlack"; + for ( int i = 0;i topLevelItemCount();++i ) + { + QTreeWidgetItem *item = listview->topLevelItem( i ); + if ( item && item->data(0, Qt::UserRole + 1 ) == currentTheme ) + { + listview->setCurrentItem( item ); + } + } +} + + +void ThemePage::insertThemes() +{ + QList lstChildren; + QTreeWidgetItem *item = new QTreeWidgetItem(listview ); + + item->setData( 0, Qt::DisplayRole,i18n("Small black") ); + item->setData( 1, Qt::DisplayRole, i18n("Small black cursors") ); + item->setData( 0, Qt::DecorationRole, QPixmap( arrow_small_black_xpm ) ); + item->setData( 0, Qt::UserRole + 1,"SmallBlack" ); + lstChildren<setData( 0, Qt::DisplayRole, i18n("Large black") ); + item->setData( 1, Qt::DisplayRole, i18n("Large black cursors") ); + item->setData( 0, Qt::DecorationRole, QPixmap( arrow_large_black_xpm ) ); + item->setData( 0, Qt::UserRole + 1,"LargeBlack" ); + lstChildren<setData( 0, Qt::DisplayRole, i18n("Small white") ); + item->setData( 1, Qt::DisplayRole, i18n("Small white cursors") ); + item->setData( 0, Qt::DecorationRole, QPixmap(arrow_small_white_xpm ) ); + item->setData( 0, Qt::UserRole + 1,"SmallWhite" ); + lstChildren<setData( 0, Qt::DisplayRole, i18n("Large white") ); + item->setData( 1, Qt::DisplayRole, i18n("Large white cursors") ); + item->setData( 0, Qt::DecorationRole, QPixmap( arrow_large_white_xpm ) ); + item->setData( 0, Qt::UserRole + 1, "LargeWhite" ); + lstChildren<addTopLevelItems( lstChildren ); +} + + +void ThemePage::fixCursorFile() +{ + // Make sure we have the 'font' resource dir registered and can find the + // override dir. + // + // Next, if the user wants large cursors, copy the font + // cursor_large.pcf.gz to (localkdedir)/share/fonts/override/cursor.pcf.gz. + // Else remove the font cursor.pcf.gz from (localkdedir)/share/fonts/override. + // + // Run mkfontdir to update fonts.dir in that dir. + + KGlobal::dirs()->addResourceType( "font", 0, "share/fonts/" ); + KIO::mkdir( QDir::homePath() + "/.fonts/kde-override" ); + QString overrideDir = QDir::homePath() + "/.fonts/kde-override/"; + + KUrl installedFont; + installedFont.setPath( overrideDir + "cursor.pcf.gz" ); + + if ( currentTheme == "SmallBlack" ) + KIO::NetAccess::del( installedFont, this ); + else { + KUrl source; + + if ( currentTheme == "LargeBlack" ) + source.setPath( KStandardDirs::locate("data", "kcminput/cursor_large_black.pcf.gz") ); + else if ( currentTheme == "LargeWhite" ) + source.setPath( KStandardDirs::locate("data", "kcminput/cursor_large_white.pcf.gz") ); + else if ( currentTheme == "SmallWhite" ) + source.setPath( KStandardDirs::locate("data", "kcminput/cursor_small_white.pcf.gz") ); + + KIO::Job* job = KIO::file_copy( source, installedFont, -1, KIO::Overwrite ); + job->exec(); + } + + QString cmd = KGlobal::dirs()->findExe( "mkfontdir" ); + if ( !cmd.isEmpty() ) + { + KProcess p; + p << cmd << overrideDir; + p.execute(); + } +} + +// vim: set noet ts=4 sw=4: diff --git a/kcms/input/core/themepage.h b/kcms/input/core/themepage.h new file mode 100644 index 0000000000..b264422add --- /dev/null +++ b/kcms/input/core/themepage.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2003 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 __THEMEPAGE_H +#define __THEMEPAGE_H + +class QTreeWidget; +class QTreeWidgetItem; + +class ThemePage : public QWidget +{ + Q_OBJECT + + public: + explicit ThemePage( QWidget* parent = 0, const char* name = 0 ); + ~ThemePage(); + + // Called by the KCM + void save(); + void load(); + void defaults(); + + Q_SIGNALS: + void changed( bool ); + + private Q_SLOTS: + void selectionChanged( QTreeWidgetItem *,QTreeWidgetItem* ); + + private: + void insertThemes(); + void fixCursorFile(); + + QTreeWidget *listview; + QString currentTheme, selectedTheme; +}; + +#endif // __THEMEPAGE_H + +// vim: set noet ts=4 sw=4: diff --git a/kcms/input/cursor_large.bdf b/kcms/input/cursor_large.bdf new file mode 100644 index 0000000000..241189286e --- /dev/null +++ b/kcms/input/cursor_large.bdf @@ -0,0 +1,4447 @@ +STARTFONT 2.1 +FONT cursor +SIZE 47 78 78 +FONTBOUNDINGBOX 45 42 -21 -23 +STARTPROPERTIES 13 +COPYRIGHT "(C) 2000 Rik Hemsley " +POINT_SIZE 470 +FONT "cursor" +WEIGHT 10 +RESOLUTION 107 +RESOLUTION_X 78 +RESOLUTION_Y 78 +X_HEIGHT -1 +QUAD_WIDTH 20 +DEFAULT_CHAR 0 +FONT_ASCENT 23 +FONT_DESCENT 24 +_XMBDFED_INFO "Edited with xmbdfed 4.3." +ENDPROPERTIES +CHARS 154 +STARTCHAR D +ENCODING 0 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 1 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C002 +ENCODING 2 +SWIDTH 1139 0 +DWIDTH 58 0 +BBX 12 21 -10 -22 +BITMAP +0010 +0030 +0070 +00F0 +01F0 +03F0 +07F0 +0FF0 +1FF0 +3FF0 +7FF0 +FFF0 +0FF0 +07F0 +0F70 +0E30 +1E10 +1C00 +3C00 +3800 +3800 +ENDCHAR +STARTCHAR C003 +ENCODING 3 +SWIDTH 1414 0 +DWIDTH 72 0 +BBX 14 23 -11 -23 +BITMAP +000C +001C +003C +007C +00FC +01FC +03FC +07FC +0FFC +1FFC +3FFC +7FFC +FFFC +7FFC +07FC +0FFC +0FBC +1F9C +1F0C +3F00 +3E00 +3E00 +1C00 +ENDCHAR +STARTCHAR C004 +ENCODING 4 +SWIDTH 137 0 +DWIDTH 7 0 +BBX 11 15 -4 -2 +BITMAP +FFE0 +FFE0 +FFE0 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +FFE0 +7FC0 +3F80 +1F00 +0E00 +0400 +ENDCHAR +STARTCHAR C004 +ENCODING 5 +SWIDTH 176 0 +DWIDTH 9 0 +BBX 15 17 -6 -3 +BITMAP +3FF8 +7FFC +7FFC +7FFC +3FF8 +07C0 +07C0 +07C0 +07C0 +FFFE +7FFC +3FF8 +1FF0 +0FE0 +07C0 +0380 +0100 +ENDCHAR +STARTCHAR C004 +ENCODING 6 +SWIDTH 137 0 +DWIDTH 7 0 +BBX 11 15 -4 -16 +BITMAP +0400 +0E00 +1F00 +3F80 +7FC0 +FFE0 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +FFE0 +FFE0 +FFE0 +ENDCHAR +STARTCHAR C004 +ENCODING 7 +SWIDTH 176 0 +DWIDTH 9 0 +BBX 15 17 -6 -17 +BITMAP +0100 +0380 +07C0 +0FE0 +1FF0 +3FF8 +7FFC +FFFE +07C0 +07C0 +07C0 +07C0 +3FF8 +7FFC +7FFC +7FFC +3FF8 +ENDCHAR +STARTCHAR D +ENCODING 8 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 9 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 10 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 11 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C014 +ENCODING 12 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 21 0 -3 +BITMAP +E00000 +E00000 +E00000 +E00100 +E00380 +E087C0 +E0CF80 +E0FF00 +E0FE00 +E0FC00 +E0FC00 +E0FE00 +E0FF00 +E00000 +E00000 +E00000 +E00000 +E00000 +FFFFF8 +FFFFF8 +FFFFF8 +ENDCHAR +STARTCHAR C014 +ENCODING 13 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 23 23 -1 -4 +BITMAP +700000 +F80000 +F80000 +F80080 +F881C0 +F8C3E0 +F8E7F0 +F8FFE0 +F8FFC0 +F8FF80 +F8FF00 +F8FF00 +F8FF80 +F8FFC0 +F8FFE0 +F80000 +F80000 +F80000 +FFFFFC +FFFFFE +FFFFFE +FFFFFE +FFFFFC +ENDCHAR +STARTCHAR C014 +ENCODING 14 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 21 -18 -3 +BITMAP +000038 +000038 +000038 +040038 +0E0038 +1F0838 +0F9838 +07F838 +03F838 +01F838 +01F838 +03F838 +07F838 +000038 +000038 +000038 +000038 +000038 +FFFFF8 +FFFFF8 +FFFFF8 +ENDCHAR +STARTCHAR C014 +ENCODING 15 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 23 23 -19 -4 +BITMAP +00001C +00003E +00003E +02003E +07023E +0F863E +1FCE3E +0FFE3E +07FE3E +03FE3E +01FE3E +01FE3E +03FE3E +07FE3E +0FFE3E +00003E +00003E +00003E +7FFFFE +FFFFFE +FFFFFE +FFFFFE +7FFFFE +ENDCHAR +STARTCHAR C020 +ENCODING 16 +SWIDTH 216 0 +DWIDTH 11 0 +BBX 19 20 -8 -3 +BITMAP +00E000 +00E000 +00E000 +00E000 +00E000 +00E000 +00E000 +0FFE00 +07FC00 +03F800 +01F000 +00E000 +004000 +000000 +000000 +000000 +000000 +FFFFE0 +FFFFE0 +FFFFE0 +ENDCHAR +STARTCHAR C020 +ENCODING 17 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 21 22 -9 -4 +BITMAP +007000 +00F800 +00F800 +00F800 +00F800 +00F800 +00F800 +1FFFC0 +0FFF80 +07FF00 +03FE00 +01FC00 +00F800 +007000 +002000 +000000 +000000 +7FFFF0 +FFFFF8 +FFFFF8 +FFFFF8 +7FFFF0 +ENDCHAR +STARTCHAR D +ENCODING 18 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 19 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 20 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 21 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C026 +ENCODING 22 +SWIDTH 137 0 +DWIDTH 7 0 +BBX 11 20 -4 -21 +BITMAP +0400 +0400 +0E00 +0E00 +1F00 +1F00 +3F80 +3F80 +7FC0 +7FC0 +FFE0 +CE60 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0400 +ENDCHAR +STARTCHAR C026 +ENCODING 23 +SWIDTH 157 0 +DWIDTH 8 0 +BBX 13 22 -5 -22 +BITMAP +0200 +0700 +0700 +0F80 +0F80 +1FC0 +1FC0 +3FE0 +3FE0 +7FF0 +7FF0 +FFF8 +FFF8 +6FB0 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0700 +0200 +ENDCHAR +STARTCHAR D +ENCODING 24 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 25 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 26 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 27 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 28 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 29 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 30 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 24 23 -10 -13 +BITMAP +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +002800 +FFC7FF +FF83FF +FFC7FF +002800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +ENDCHAR +STARTCHAR numbersign +ENCODING 31 +SWIDTH 294 0 +DWIDTH 15 0 +BBX 26 25 -11 -14 +BITMAP +001C0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +7FF7FF80 +FFE3FFC0 +FFC1FFC0 +FFE3FFC0 +7FF7FF80 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +001C0000 +ENDCHAR +STARTCHAR D +ENCODING 32 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 33 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 24 23 -10 -13 +BITMAP +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +002800 +FFC7FF +FF83FF +FFC7FF +002800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 294 0 +DWIDTH 15 0 +BBX 26 25 -11 -14 +BITMAP +001C0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +7FF7FF80 +FFE3FFC0 +FFC1FFC0 +FFE3FFC0 +7FF7FF80 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +001C0000 +ENDCHAR +STARTCHAR D +ENCODING 36 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 37 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 38 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 39 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 40 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 41 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 15 23 -6 -13 +BITMAP +0100 +0380 +07C0 +0FE0 +1FF0 +3FF8 +7BBC +F39E +638C +0380 +0380 +0380 +0380 +0380 +E38C +F39E +7BBC +3FF8 +1FF0 +0FE0 +07C0 +0380 +0100 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 196 0 +DWIDTH 10 0 +BBX 17 25 -7 -14 +BITMAP +008000 +01C000 +03E000 +07F000 +0FF800 +1FFC00 +3FFE00 +7FFF00 +FFFF80 +7BEF00 +33E600 +03E000 +03E000 +03E000 +33E600 +7BEF00 +FFFF80 +7FFF00 +3FFE00 +1FFC00 +0FF800 +07F000 +03E000 +01C000 +008000 +ENDCHAR +STARTCHAR C002 +ENCODING 44 +SWIDTH 1139 0 +DWIDTH 58 0 +BBX 12 21 -10 -22 +BITMAP +0010 +0030 +0070 +00F0 +01F0 +03F0 +07F0 +0FF0 +1FF0 +3FF0 +7FF0 +FFF0 +0FF0 +07F0 +0F70 +0E30 +1E10 +1C00 +3C00 +3800 +3800 +ENDCHAR +STARTCHAR C003 +ENCODING 45 +SWIDTH 1414 0 +DWIDTH 72 0 +BBX 14 23 -11 -23 +BITMAP +000C +001C +003C +007C +00FC +01FC +03FC +07FC +0FFC +1FFC +3FFC +7FFC +FFFC +7FFC +07FC +0FFC +0FBC +1F9C +1F0C +3F00 +3E00 +3E00 +1C00 +ENDCHAR +STARTCHAR C002 +ENCODING 46 +SWIDTH 1139 0 +DWIDTH 58 0 +BBX 12 21 -10 -22 +BITMAP +0010 +0030 +0070 +00F0 +01F0 +03F0 +07F0 +0FF0 +1FF0 +3FF0 +7FF0 +FFF0 +0FF0 +07F0 +0F70 +0E30 +1E10 +1C00 +3C00 +3800 +3800 +ENDCHAR +STARTCHAR C003 +ENCODING 47 +SWIDTH 1414 0 +DWIDTH 72 0 +BBX 14 23 -11 -23 +BITMAP +000C +001C +003C +007C +00FC +01FC +03FC +07FC +0FFC +1FFC +3FFC +7FFC +FFFC +7FFC +07FC +0FFC +0FBC +1F9C +1F0C +3F00 +3E00 +3E00 +1C00 +ENDCHAR +STARTCHAR D +ENCODING 48 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 49 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR 2 +ENCODING 50 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 23 -9 -13 +BITMAP +00F800 +C3FE00 +E7FF80 +FFC3C0 +DF00E0 +CE0060 +C60020 +C30000 +FF8000 +FF8000 +000000 +000000 +000000 +000FF8 +000FF8 +000618 +200318 +300398 +3C07D8 +1E1FF8 +0FFF38 +03FE18 +00F800 +ENDCHAR +STARTCHAR 2 +ENCODING 51 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 23 -9 -13 +BITMAP +00F800 +C3FE00 +E7FF80 +FFC3C0 +FF00E0 +FE0060 +FE0020 +FF0000 +FF8000 +FF8000 +000000 +000000 +000000 +000FF8 +000FF8 +0007F8 +2003F8 +3003F8 +3C07F8 +1E1FF8 +0FFF38 +03FE18 +00F800 +ENDCHAR +STARTCHAR 4 +ENCODING 52 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 27 27 -12 -15 +BITMAP +00040000 +000E0000 +001F0000 +003F8000 +007FC000 +007FC000 +000E0000 +000E0000 +000E0000 +0C0E0600 +1C0E0700 +3C0E0780 +7FFFFFC0 +FFFFFFE0 +7FFFFFC0 +3C0E0780 +1C0E0700 +0C0E0600 +000E0000 +000E0000 +000E0000 +007FC000 +007FC000 +003F8000 +001F0000 +000E0000 +00040000 +ENDCHAR +STARTCHAR 4 +ENCODING 53 +SWIDTH 314 0 +DWIDTH 16 0 +BBX 29 29 -13 -16 +BITMAP +00020000 +00070000 +000F8000 +001FC000 +003FE000 +007FF000 +007FF000 +003FE000 +000F8000 +060F8300 +0F0F8780 +1F0F87C0 +3FFFFFE0 +7FFFFFF0 +FFFFFFF8 +7FFFFFF0 +3FFFFFE0 +1F0F87C0 +0F0F8780 +060F8300 +000F8000 +003FE000 +007FF000 +007FF000 +003FE000 +001FC000 +000F8000 +00070000 +00020000 +ENDCHAR +STARTCHAR D +ENCODING 54 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 55 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 56 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 57 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR less +ENCODING 58 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 23 21 -21 -21 +BITMAP +001FFC +00FFFE +01E006 +0307FC +060FF8 +0C0060 +0C07C0 +0C0FC0 +0C0060 +1E07C0 +330FC0 +6180C0 +C0C780 +C06F00 +603C00 +318C00 +199800 +0C3000 +066000 +03C000 +018000 +ENDCHAR +STARTCHAR equal +ENCODING 59 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 23 21 -21 -21 +BITMAP +001FFC +00FFFE +01FFFE +03FFFC +07FFF8 +0FFFE0 +0FFFC0 +0FFFC0 +0FFFE0 +1FFFC0 +3FFFC0 +7FFFC0 +FFFF80 +FFFF00 +7FFC00 +3FFC00 +1FF800 +0FF000 +07E000 +03C000 +018000 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 962 0 +DWIDTH 49 0 +BBX 23 21 1 -21 +BITMAP +7FF000 +FFFE00 +C00F00 +7FC180 +3FE0C0 +0C0060 +07C060 +07E060 +0C0060 +07C0F0 +07E198 +06030C +03C606 +01EC06 +00780C +006318 +003330 +001860 +000CC0 +000780 +000300 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 923 0 +DWIDTH 47 0 +BBX 23 21 1 -21 +BITMAP +7FF000 +FFFE00 +FFFF00 +7FFF80 +3FFFC0 +0FFFE0 +07FFE0 +07FFE0 +0FFFE0 +07FFF0 +07FFF8 +07FFFC +03FFFE +01FFFE +007FFC +007FF8 +003FF0 +001FE0 +000FC0 +000780 +000300 +ENDCHAR +STARTCHAR D +ENCODING 62 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 63 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 64 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 65 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 66 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 67 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C020 +ENCODING 70 +SWIDTH 216 0 +DWIDTH 11 0 +BBX 20 19 0 -11 +BITMAP +E00000 +E00000 +E00000 +E00000 +E00800 +E01800 +E03800 +E07800 +E0FFF0 +E1FFF0 +E0FFF0 +E07800 +E03800 +E01800 +E00800 +E00000 +E00000 +E00000 +E00000 +ENDCHAR +STARTCHAR C020 +ENCODING 71 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 22 21 -1 -12 +BITMAP +700000 +F80000 +F80000 +F80200 +F80600 +F80E00 +F81E00 +F83E00 +F87FF8 +F8FFFC +F9FFFC +F8FFFC +F87FF8 +F83E00 +F81E00 +F80E00 +F80600 +F80200 +F80000 +F80000 +700000 +ENDCHAR +STARTCHAR D +ENCODING 72 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 73 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 74 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 75 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 76 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 77 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 78 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 79 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 80 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 81 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 82 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 83 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 84 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 85 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +D800 +CC00 +CC00 +6600 +6600 +3300 +3300 +1980 +1980 +0CC0 +0CC0 +0660 +0660 +03F0 +0330 +01F0 +00E0 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FC00 +7E00 +7E00 +3F00 +3F00 +1F80 +1F80 +0FC0 +0FC0 +07E0 +07E0 +03F0 +03F0 +01F0 +00E0 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 353 0 +DWIDTH 18 0 +BBX 17 17 1 -2 +BITMAP +003F80 +007F00 +00FC00 +01F000 +03C000 +07FE00 +01FC00 +03F000 +07C000 +0F0000 +1FF000 +07E000 +0F8000 +1E0000 +380000 +600000 +800000 +ENDCHAR +STARTCHAR X +ENCODING 89 +SWIDTH 392 0 +DWIDTH 20 0 +BBX 20 19 0 -3 +BITMAP +001FF0 +003FE0 +007FC0 +00FF80 +01FE00 +03FFC0 +07FF80 +0FFF00 +03FE00 +07F800 +0FFE00 +1FFC00 +3FF800 +0FF000 +0FC000 +3F0000 +7C0000 +F00000 +C00000 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 15 15 -6 -9 +BITMAP +0380 +0380 +0380 +0380 +0380 +0380 +FFFE +FFFE +FFFE +0380 +0380 +0380 +0380 +0380 +0380 +ENDCHAR +STARTCHAR Z +ENCODING 91 +SWIDTH 196 0 +DWIDTH 10 0 +BBX 17 17 -7 -10 +BITMAP +01C000 +03E000 +03E000 +03E000 +03E000 +03E000 +7FFF00 +FFFF80 +FFFF80 +FFFF80 +7FFF00 +03E000 +03E000 +03E000 +03E000 +03E000 +01C000 +ENDCHAR +STARTCHAR D +ENCODING 92 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 93 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C002 +ENCODING 94 +SWIDTH 1139 0 +DWIDTH 58 0 +BBX 12 21 -10 -22 +BITMAP +0010 +0030 +0070 +00F0 +01F0 +03F0 +07F0 +0FF0 +1FF0 +3FF0 +7FF0 +FFF0 +0FF0 +07F0 +0F70 +0E30 +1E10 +1C00 +3C00 +3800 +3800 +ENDCHAR +STARTCHAR C003 +ENCODING 95 +SWIDTH 1414 0 +DWIDTH 72 0 +BBX 14 23 -11 -23 +BITMAP +000C +001C +003C +007C +00FC +01FC +03FC +07FC +0FFC +1FFC +3FFC +7FFC +FFFC +7FFC +07FC +0FFC +0FBC +1F9C +1F0C +3F00 +3E00 +3E00 +1C00 +ENDCHAR +STARTCHAR C020 +ENCODING 96 +SWIDTH 216 0 +DWIDTH 11 0 +BBX 20 19 -17 -11 +BITMAP +000070 +000070 +000070 +000070 +010070 +018070 +01C070 +01E070 +FFF070 +FFF870 +FFF070 +01E070 +01C070 +018070 +010070 +000070 +000070 +000070 +000070 +ENDCHAR +STARTCHAR C020 +ENCODING 97 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 22 21 -18 -12 +BITMAP +000038 +00007C +00007C +01007C +01807C +01C07C +01E07C +01F07C +7FF87C +FFFC7C +FFFE7C +FFFC7C +7FF87C +01F07C +01E07C +01C07C +01807C +01007C +00007C +00007C +000038 +ENDCHAR +STARTCHAR D +ENCODING 98 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 99 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 100 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 101 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 102 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 103 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 104 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 105 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 157 0 +DWIDTH 8 0 +BBX 13 20 -5 -2 +BITMAP +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +FFF8 +7FF0 +3FE0 +1FC0 +0F80 +0700 +0200 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 176 0 +DWIDTH 9 0 +BBX 15 22 -6 -3 +BITMAP +06C0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +7FFC +FFFE +7FFC +3FF8 +1FF0 +0FE0 +07C0 +0380 +0100 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 25 13 -12 -7 +BITMAP +02002000 +06003000 +0E003800 +1E003C00 +3FFFFE00 +7FFFFF00 +FE003F80 +7FFFFF00 +3FFFFE00 +1E003C00 +0E003800 +06003000 +02002000 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 274 0 +DWIDTH 14 0 +BBX 27 15 -13 -8 +BITMAP +01001000 +03803800 +07803C00 +0F803E00 +1FFFFF00 +3FFFFF80 +7FFFFFC0 +FFFFFFE0 +7FFFFFC0 +3FFFFF80 +1FFFFF00 +0F803E00 +07803C00 +03803800 +01001000 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 412 0 +DWIDTH 21 0 +BBX 20 13 1 -8 +BITMAP +020000 +060000 +0E0000 +1E0000 +3FFFF0 +7FFFF0 +FE0000 +7FFFF0 +3FFFF0 +1E0000 +0E0000 +060000 +020000 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 22 15 0 -9 +BITMAP +010000 +038000 +078000 +0F8000 +1FFFF8 +3FFFFC +7FFFFC +FFFFF8 +7FFFFC +3FFFFC +1FFFF8 +0F8000 +078000 +038000 +010000 +ENDCHAR +STARTCHAR n +ENCODING 112 +SWIDTH 412 0 +DWIDTH 21 0 +BBX 20 13 -18 -8 +BITMAP +000400 +000600 +000700 +000780 +FFFFC0 +FFFFE0 +0007F0 +FFFFE0 +FFFFC0 +000780 +000700 +000600 +000400 +ENDCHAR +STARTCHAR o +ENCODING 113 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 22 15 -19 -9 +BITMAP +000200 +000700 +000780 +0007C0 +7FFFE0 +FFFFF0 +FFFFF8 +7FFFFC +FFFFF8 +FFFFF0 +7FFFE0 +0007C0 +000780 +000700 +000200 +ENDCHAR +STARTCHAR j +ENCODING 114 +SWIDTH 157 0 +DWIDTH 8 0 +BBX 13 20 -5 -21 +BITMAP +0200 +0700 +0F80 +1FC0 +3FE0 +7FF0 +FFF8 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +ENDCHAR +STARTCHAR k +ENCODING 115 +SWIDTH 176 0 +DWIDTH 9 0 +BBX 15 22 -6 -22 +BITMAP +0100 +0380 +07C0 +0FE0 +1FF0 +3FF8 +7FFC +FFFE +7FFC +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +06C0 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 137 0 +DWIDTH 7 0 +BBX 13 25 -5 -14 +BITMAP +0200 +0700 +0F80 +1FC0 +3FE0 +7FF0 +FFF8 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +0D80 +FFF8 +7FF0 +3FE0 +1FC0 +0F80 +0700 +0200 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 157 0 +DWIDTH 8 0 +BBX 15 27 -6 -15 +BITMAP +0100 +0380 +07C0 +0FE0 +1FF0 +3FF8 +7FFC +FFFE +7FFC +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +0FE0 +7FFC +FFFE +7FFC +3FF8 +1FF0 +0FE0 +07C0 +0380 +0100 +ENDCHAR +STARTCHAR D +ENCODING 118 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 119 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 120 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 121 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 122 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 123 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 39 0 +DWIDTH 2 0 +BBX 15 26 -13 -22 +BITMAP +000A +0054 +00A0 +0000 +1CAA +1D54 +1C00 +1C20 +3E14 +7F0A +FF80 +C180 +C180 +C180 +C180 +C180 +C180 +C180 +FF80 +FF80 +FF80 +FF80 +C180 +FF80 +FF80 +FF80 +ENDCHAR +STARTCHAR bar +ENCODING 125 +SWIDTH 39 0 +DWIDTH 2 0 +BBX 15 26 -13 -22 +BITMAP +000E +007C +00E0 +0000 +1CFE +1DFE +1C00 +1C60 +3E3C +7F0E +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +FF80 +ENDCHAR +STARTCHAR D +ENCODING 126 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 127 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 128 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 129 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 130 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 24 23 -10 -13 +BITMAP +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +002800 +FFC7FF +FF83FF +FFC7FF +002800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +003800 +ENDCHAR +STARTCHAR numbersign +ENCODING 131 +SWIDTH 294 0 +DWIDTH 15 0 +BBX 26 25 -11 -14 +BITMAP +001C0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +7FF7FF80 +FFE3FFC0 +FFC1FFC0 +FFE3FFC0 +7FF7FF80 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +003E0000 +001C0000 +ENDCHAR +STARTCHAR D +ENCODING 132 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 133 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C014 +ENCODING 134 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 21 0 -21 +BITMAP +FFFFF8 +FFFFF8 +FFFFF8 +E00000 +E00000 +E00000 +E00000 +E00000 +E0FF00 +E0FE00 +E0FC00 +E0FC00 +E0FE00 +E0FF00 +E0CF80 +E087C0 +E00380 +E00100 +E00000 +E00000 +E00000 +ENDCHAR +STARTCHAR C014 +ENCODING 135 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 23 23 -1 -22 +BITMAP +FFFFFC +FFFFFE +FFFFFE +FFFFFE +FFFFFC +F80000 +F80000 +F80000 +F8FFE0 +F8FFC0 +F8FF80 +F8FF00 +F8FF00 +F8FF80 +F8FFC0 +F8FFE0 +F8E7F0 +F8C3E0 +F881C0 +F80080 +F80000 +F80000 +700000 +ENDCHAR +STARTCHAR C014 +ENCODING 136 +SWIDTH 510 0 +DWIDTH 26 0 +BBX 21 21 -18 -21 +BITMAP +FFFFF8 +FFFFF8 +FFFFF8 +000038 +000038 +000038 +000038 +000038 +07F838 +03F838 +01F838 +01F838 +03F838 +07F838 +0F9838 +1F0838 +0E0038 +040038 +000038 +000038 +000038 +ENDCHAR +STARTCHAR C014 +ENCODING 137 +SWIDTH 432 0 +DWIDTH 22 0 +BBX 23 23 -19 -22 +BITMAP +7FFFFE +FFFFFE +FFFFFE +FFFFFE +7FFFFE +00003E +00003E +00003E +0FFE3E +07FE3E +03FE3E +01FE3E +01FE3E +03FE3E +07FE3E +0FFE3E +1FCE3E +0F863E +07023E +02003E +00003E +00003E +00001C +ENDCHAR +STARTCHAR C020 +ENCODING 138 +SWIDTH 216 0 +DWIDTH 11 0 +BBX 19 20 -8 -20 +BITMAP +FFFFE0 +FFFFE0 +FFFFE0 +000000 +000000 +000000 +000000 +004000 +00E000 +01F000 +03F800 +07FC00 +0FFE00 +00E000 +00E000 +00E000 +00E000 +00E000 +00E000 +00E000 +ENDCHAR +STARTCHAR C020 +ENCODING 139 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 21 22 -9 -21 +BITMAP +7FFFF0 +FFFFF8 +FFFFF8 +FFFFF8 +7FFFF0 +000000 +000000 +002000 +007000 +00F800 +01FC00 +03FE00 +07FF00 +0FFF80 +1FFFC0 +00F800 +00F800 +00F800 +00F800 +00F800 +00F800 +007000 +ENDCHAR +STARTCHAR D +ENCODING 140 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 141 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 142 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 143 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 144 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 145 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 146 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 147 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR D +ENCODING 148 +SWIDTH 255 0 +DWIDTH 13 0 +BBX 12 21 1 -22 +BITMAP +8000 +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FF00 +FE00 +EF00 +C700 +8780 +0380 +03C0 +01C0 +01C0 +ENDCHAR +STARTCHAR E +ENCODING 149 +SWIDTH 530 0 +DWIDTH 27 0 +BBX 14 23 0 -23 +BITMAP +C000 +E000 +F000 +F800 +FC00 +FE00 +FF00 +FF80 +FFC0 +FFE0 +FFF0 +FFF8 +FFFC +FFF8 +FF80 +FFC0 +F7C0 +E7E0 +C3E0 +03F0 +01F0 +01F0 +00E0 +ENDCHAR +STARTCHAR C226 +ENCODING 150 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 23 37 -10 -20 +BITMAP +007C00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +03FF80 +0FFFE0 +1F01F0 +3C0078 +383838 +70381C +70381C +60380C +E0380E +E0380E +E0380E +E03C0E +E01E0E +600F0C +70079C +70031C +380038 +3C0078 +1F01F0 +0FFFE0 +03FF80 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +007C00 +ENDCHAR +STARTCHAR C226 +ENCODING 151 +SWIDTH 235 0 +DWIDTH 12 0 +BBX 23 37 -10 -20 +BITMAP +007C00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +03FF80 +0FFFE0 +1FFFF0 +3FFFF8 +3FFFF8 +7FFFFC +7FFFFC +7FFFFC +FFFFFE +FFFFFE +FFFFFE +FFFFFE +FFFFFE +7FFFFC +7FFFFC +7FFFFC +3FFFF8 +3FFFF8 +1FFFF0 +0FFFE0 +03FF80 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +00FE00 +007C00 +ENDCHAR +STARTCHAR C230 +ENCODING 152 +SWIDTH 373 0 +DWIDTH 19 0 +BBX 11 21 -4 -12 +BITMAP +FBE0 +FFE0 +1F00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +0E00 +1F00 +FFE0 +FBE0 +ENDCHAR +STARTCHAR C231 +ENCODING 153 +SWIDTH 157 0 +DWIDTH 8 0 +BBX 13 23 -5 -13 +BITMAP +7DF0 +FFF8 +FFF8 +7FF0 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +0F80 +7FF0 +FFF8 +FFF8 +7DF0 +ENDCHAR +ENDFONT diff --git a/kcms/input/cursor_large_black.pcf.gz b/kcms/input/cursor_large_black.pcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..c9b458390cf7326545ccb6b8cdf25c5c4de45f03 GIT binary patch literal 3339 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 literal 0 HcmV?d00001 diff --git a/kcms/input/cursor_small_white.pcf.gz b/kcms/input/cursor_small_white.pcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..618905ea70bbcb363d84aad2597357aa2da802c4 GIT binary patch literal 3524 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 literal 0 HcmV?d00001 diff --git a/kcms/input/cursortheme.desktop b/kcms/input/cursortheme.desktop new file mode 100644 index 0000000000..4a5feed001 --- /dev/null +++ b/kcms/input/cursortheme.desktop @@ -0,0 +1,169 @@ +[Desktop Entry] +Exec=kcmshell5 cursortheme +Icon=edit-select +Type=Service + +X-KDE-ServiceTypes=KCModule +X-KDE-Library=kcm_cursortheme +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=desktop-appearance +X-DocPath=kcontrol/cursortheme/index.html + +Name=Cursor Theme +Name[ar]=سِمة المؤشر +Name[ast]=Tema de cursores +Name[bg]=Тема за курсора +Name[bn]=কার্সর থীম +Name[bs]=Tema pokazivača +Name[ca]=Tema de cursor +Name[ca@valencia]=Tema de cursor +Name[cs]=Motiv kurzorů +Name[da]=Markørtema +Name[de]=Zeigerdesigns +Name[el]=Θέμα δρομέα +Name[en_GB]=Cursor Theme +Name[es]=Tema de cursores +Name[et]=Kursoriteema +Name[eu]=Kurtsorearen gaia +Name[fi]=Osoitinteema +Name[fr]=Thème de curseur +Name[ga]=Téama Cúrsóra +Name[gl]=Tema do cursor +Name[he]=ערכת־נושא למצביע העכבר +Name[hi]=संकेतक प्रसंग +Name[hr]=Tema pokazivača +Name[hu]=Kurzortéma +Name[ia]=Thema de cursor +Name[is]=Bendilþema +Name[it]=Tema dei cursori +Name[ja]=カーソルテーマ +Name[kk]=Меңзер нақышы +Name[km]=ស្បែក​ទស្សន៍ទ្រនិច +Name[kn]=ಸ್ಥಳಸೂಚಕ (ಕರ್ಸರ್) ಪರಿಸರವಿನ್ಯಾಸ +Name[ko]=커서 테마 +Name[lt]=Žymeklių tema +Name[lv]=Kursora tēma +Name[mr]=कर्सर शैली +Name[nb]=Pekertema +Name[nds]=Wieserutsehn +Name[nl]=Cursorthema +Name[pa]=ਕਰਸਰ ਥੀਮ +Name[pl]=Zestawy kursorów +Name[pt]=Tema de Cursores +Name[pt_BR]=Tema de cursores +Name[ro]=Tematica de cursor +Name[ru]=Тема курсоров +Name[sk]=Téma kurzora +Name[sl]=Tema kazalke +Name[sr]=Тема показивача +Name[sr@ijekavian]=Тема показивача +Name[sr@ijekavianlatin]=Tema pokazivača +Name[sr@latin]=Tema pokazivača +Name[sv]=Muspekartema +Name[th]=ชุดเคอร์เซอร์ +Name[tr]=İmleç Teması +Name[ug]=نۇربەلگە ئۆرنىكى +Name[uk]=Тема вказівника +Name[vi]=Sắc thái con trỏ +Name[wa]=Tinme do cursoe +Name[x-test]=xxCursor Themexx +Name[zh_CN]=光标主题 +Name[zh_TW]=游標主題 + +Comment=Customize the mouse cursor appearance +Comment[ar]=خصص مظهر سِمة مؤشر الفأرة +Comment[ast]=Personalizar l'apariencia del cursor del mur +Comment[bg]=Настройки на изгледа на курсора на мишката +Comment[bn]=মাউস কার্সর-এর চেহারা পছন্দমত বদলান +Comment[bs]=Prilagodite izgled pokazivača miša +Comment[ca]=Personalitza l'aparença del cursor del ratolí +Comment[ca@valencia]=Personalitza l'aparença del cursor del ratolí +Comment[cs]=Upravit vzhled kurzoru myši +Comment[da]=Tilpas musemarkørens udseende +Comment[de]=Das Erscheinungsbild des Mauszeigers anpassen +Comment[el]=Προσαρμογή εμφάνισης του δείκτη ποντικιού +Comment[en_GB]=Customise the mouse cursor appearance +Comment[es]=Personalizar la apariencia del cursor del ratón +Comment[et]=Hiirekursori välimuse kohandamine +Comment[eu]=Pertsonalizatu saguaren kurtsorearen itxura +Comment[fi]=Hiiren osoittimen ulkoasuasetukset +Comment[fr]=Personnaliser l'apparence du curseur de la souris +Comment[gl]=Personaliza o tema do cursor +Comment[he]=התאמה אישית של מראה מצביע העכבר +Comment[hr]=Podesi izgled pokazivača miša +Comment[hu]=Az egérmutató megjelenésének testreszabása +Comment[ia]=Personalisa le apparentia de cursor de mus +Comment[is]=Sérsníða útlit músarbendilsins +Comment[it]=Personalizza l'aspetto del cursore del mouse +Comment[ja]=マウスカーソル表示のカスタマイズ +Comment[kk]=Меңзер нақышын өзінше баптап алу +Comment[km]=ប្ដូរ​រូបរាង​ទស្សន៍ទ្រនិច​កណ្ដុរ​តាម​បំណង +Comment[ko]=마우스 커서 모양 사용자 정의 +Comment[lt]=Derinti pelės žymeklio išvaizdą +Comment[lv]=Pielāgot peles kursora izskatu +Comment[mr]=कर्सर शैलीत ऐच्छिक बदल करा +Comment[nb]=Sett opp utseende for musepekeren +Comment[nds]=Dat Muuswieser-Utsehn topassen +Comment[nl]=Het uiterlijk van de muiscursor aanpassen +Comment[pa]=ਮਾਊਸ ਕਰਸਰ ਦਿੱਖ ਆਪਣੀ ਪਸੰਦ ਦੀ ਬਣਾਉ +Comment[pl]=Dostosowywanie wyglądu kursora myszy +Comment[pt]=Personalizar a aparência do cursor do rato +Comment[pt_BR]=Personaliza a aparência do cursor do mouse +Comment[ro]=Particularizează tematica de cursor +Comment[ru]=Настройка внешнего вида курсора мыши +Comment[sk]=Prispôsobenie vzhľadu kurzora myši +Comment[sl]=Prilagodite videz kazalke miške +Comment[sr]=Прилагодите изглед показивача миша +Comment[sr@ijekavian]=Прилагодите изглед показивача миша +Comment[sr@ijekavianlatin]=Prilagodite izgled pokazivača miša +Comment[sr@latin]=Prilagodite izgled pokazivača miša +Comment[sv]=Anpassa muspekarens utseende +Comment[th]=ปรับแต่งชุดเคอร์เซอร์ของเมาส์เอง +Comment[tr]=Fare işaretçisi görünümünü özelleştir +Comment[ug]=چاشقىنەك نۇربەلگە قىياپىتىنى ئۆزلەشتۈر +Comment[uk]=Налаштування вигляду вказівника миші на екрані +Comment[vi]=Tuỳ chỉnh diện mạo con trỏ chuột +Comment[wa]=Mete a vosse môde li rivnance do cursoe del sori +Comment[x-test]=xxCustomize the mouse cursor appearancexx +Comment[zh_CN]=定制鼠标指针外观 +Comment[zh_TW]=自訂滑鼠游標外觀 + +X-KDE-Keywords=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance +X-KDE-Keywords[bs]=miš,kursor,tema,pojavljivanje kurosra,boja kursora,tema kursora,tema miša,pojavljivanje miša,površina miša,pokazatelj boja,pojava boja +X-KDE-Keywords[ca]=Ratolí,Cursor,Tema,Aparença de cursor,Color de cursor,Tema de cursor,Tema de ratolí,Aparença de ratolí,Pells de ratolí,Colors d'apuntador,Aparença d'apuntador +X-KDE-Keywords[ca@valencia]=Ratolí,Cursor,Tema,Aparença de cursor,Color de cursor,Tema de cursor,Tema de ratolí,Aparença de ratolí,Pells de ratolí,Colors d'apuntador,Aparença d'apuntador +X-KDE-Keywords[da]=Mus,markør,cursor,tema,markørens udseende,markørfarve,markørtema,musetema,musens udseende,museskin +X-KDE-Keywords[de]=Maus,Zeiger,Mauszeiger,Zeigerfarbe,Zeigerdesign +X-KDE-Keywords[el]=ποντίκι,δρομέας,θέμα,εμφάνιση δρομέα,χρώμα δρομέα,θέμα δρομέα,θέμα ποντικιού,εμφάνιση ποντικιού,θέματα ποντικιού,χρώματα δείκτη,εμφάνιση δείκτη +X-KDE-Keywords[es]=Ratón,Cursor,Tema,Apariencia del cursor,Color del cursor,Tema del cursor,Tema del ratón,Apariencia del ratón,Pieles del ratón,Colores del puntero,Apariencia del puntero +X-KDE-Keywords[et]=Hiir,Kursor,Teema,Kursori välimus,Kursori värv,Kursori teema,Hiireteema,Hiire välimus,Hiire nahad,Osutusseadme värvid,Osutusseadme välimus +X-KDE-Keywords[eu]=sagu,kurtsore,gai,kurtsorearen itsura,kurtsorearen kolorea,saguaren gaia,saguaren itxura,saguaren azalak,erakuslearen koloreak,erakuslearen itxura +X-KDE-Keywords[fi]=hiiri,osoitin,teema,osoittimen ulkoasu,osoittimen väri,osoitinteema,hiiren teema,hiiriteema,hiiren ulkoasu,hiiriteemat,osoitinvärit +X-KDE-Keywords[fr]=Souris, Curseur, Thème, Apparence du curseur, Couleur du curseur, Thème de curseurs, Thème de la souris, Apparence de la souris, Revêtement de la souris, Couleur du pointeur, Apparence du pointeur +X-KDE-Keywords[gl]=rato, cursor, tema, aparencia do cursor, cor do cursor, tema do cursor, tema do rato, aparencia do rato, cor do rato, punteiro, cor do punteiro, aparencia do punteiro, tema do punteiro +X-KDE-Keywords[hu]=Egér,Kurzor,Téma,Kurzormegjelenés,Kurzorszín,Kurzortéma,Egértéma,Egérmegjelenés,Egérfelületek,Mutató színek,Mutató megjelenés +X-KDE-Keywords[ia]=Mus,Cursor,Thema,Apparentia,Cursor,Color,Thema de Cursor,Thema de Mus, Apparentia de Mus,Pelles de Mus,Colores de punctator,Apparentia de punctator +X-KDE-Keywords[it]=Mouse,Cursore,Aspetto cursore,Colore cursore,Tema cursore,Tema mouse,Aspetto mouse,Skin mouse,Colore puntatore,Aspetto puntatore +X-KDE-Keywords[kk]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance +X-KDE-Keywords[km]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance +X-KDE-Keywords[ko]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,마우스,커서,커서 테마,포인터 +X-KDE-Keywords[mr]=माऊस, कर्सर, थीम, कर्सर, अपिरिअन्स, कर्सर, कलर, कर्सर थीम, माऊस थीम, माऊस अपिरिअन्स, माऊस स्कीन्स, पॉईटर अपिरिअन्स +X-KDE-Keywords[nb]=Mus.peker,tema,pekerutseende,pekerfarge,pekertem,musetema,musutseende,museskins,pekerfarger,pekeerutseende +X-KDE-Keywords[nds]=Muus,Wieser,Muster, Wieserutsehn,Klöör,Utsehn +X-KDE-Keywords[nl]=Muis,Cursor,Thema,Uiterlijk van cursor,kleur van cursor,Thema van cursor,Thema van muis,uiterlijk van muis,Muisoppervlak,Kleuren van aanwijzer,Uiterlijk van aanwijzer +X-KDE-Keywords[pl]=Mysz,Kursor,Motyw,Wygląd kursora,Kolor kursora,Motyw kursora,Motyw myszy,Wygląd myszy,Skórki myszy,Kolory wskaźnika,Wygląd wskaźnika +X-KDE-Keywords[pt]=Rato,Cursor,Tema,Aparência do Cursor,Cor do Cursor,Tema do Cursor,Tema do Rato,Aparência do Rato,Visuais do Rato,Cores do Cursor +X-KDE-Keywords[pt_BR]=Mouse,Cursor,Tema,Aparência do cursor,Cor do cursor,Tema do cursor,Tema do mouse,Aparência do mouse,Visuais do mouse,Cores do ponteiro,Aparência do ponteiro +X-KDE-Keywords[ru]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,мышь,курсор,тема,внешний вид курсора мыши,цвет указателя,внешний вид указателя +X-KDE-Keywords[sk]=Myš, kurzor,téma,vzhľad kurzora,farba kurzora,téma kurzora,téma myši,vzhľad myši,skiny myši,farby ukazovateľa,vzhľad ukazovateľa +X-KDE-Keywords[sl]=miška,kazalec,kurzor,kazalka,tema,videz kazalca,videz kazalke,barva kazalca,barva kazalke,tema kazalcev,tema kazalk,tema miške,videz miške,preobleke miške,teme miške +X-KDE-Keywords[sr]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,миш,показивач,курсор,тема,изглед показивача,боја показивача,тема показивача,тема миша,изглед миша,пресвлаке миша,боје показивача +X-KDE-Keywords[sr@ijekavian]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,миш,показивач,курсор,тема,изглед показивача,боја показивача,тема показивача,тема миша,изглед миша,пресвлаке миша,боје показивача +X-KDE-Keywords[sr@ijekavianlatin]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,miš,pokazivač,kursor,tema,izgled pokazivača,boja pokazivača,tema pokazivača,tema miša,izgled miša,presvlake miša,boje pokazivača +X-KDE-Keywords[sr@latin]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,miš,pokazivač,kursor,tema,izgled pokazivača,boja pokazivača,tema pokazivača,tema miša,izgled miša,presvlake miša,boje pokazivača +X-KDE-Keywords[sv]=Mus,Pekare,Tema,Utseende,Färg,Pekartema,Mustema,Musutseende,Musskal,Pekarfärger,Pekarutseende +X-KDE-Keywords[tr]=Fare,İşaretçi,Tema,İşaretçi Görünümü,İşaretçi Rengi,İşaretçi Teması,Fare Teması,Fare Görünümü,Fare Kabuğu,İşaretçi Renkleri,İşaretçi Görünümü +X-KDE-Keywords[uk]=миша,вказівник,тема,вигляд вказівника,колір вказівника,тема вказівника,тема миші,вигляд миші,Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance +X-KDE-Keywords[x-test]=xxMouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearancexx +X-KDE-Keywords[zh_CN]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance,鼠标,指针,主题,指针外观,指针颜色,指针主题,鼠标主题,鼠标外观,鼠标皮肤,指针外观 +X-KDE-Keywords[zh_TW]=Mouse,Cursor,Theme,Cursor Appearance,Cursor Color,Cursor Theme,Mouse Theme,Mouse Appearance,Mouse Skins,Pointer Colors,Pointer Appearance diff --git a/kcms/input/kapplymousetheme.cpp b/kcms/input/kapplymousetheme.cpp new file mode 100644 index 0000000000..67b5138058 --- /dev/null +++ b/kcms/input/kapplymousetheme.cpp @@ -0,0 +1,88 @@ +/* + * main.cpp + * + * Copyright (c) 1999 Matthias Hoelzer-Kluepfel + * Copyright (c) 2005 Lubos Lunak + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 + +#include +#include +#include + +#ifdef HAVE_XCURSOR +# include +#endif + +static Display* dpy; +Display* display() { return dpy; } +Window appRootWindow() { return DefaultRootWindow( dpy ); } + +static bool isEmpty( const char* str ) + { + if( str == NULL ) + return true; + while( isspace( *str )) + ++str; + return *str == '\0'; + } + +int main( int argc, char* argv[] ) + { + if( argc != 3 ) + return 1; + dpy = XOpenDisplay( NULL ); + if( dpy == NULL ) + return 2; + int ret = 0; +#ifdef HAVE_XCURSOR + const char* theme = argv[ 1 ]; + const char* size = argv[ 2 ]; + + // Note: If you update this code, update kapplymousetheme as well. + + // use a default value for theme only if it's not configured at all, not even in X resources + if( isEmpty( theme ) + && isEmpty( XGetDefault( display(), "Xcursor", "theme" )) + && isEmpty( XcursorGetTheme( display()))) + { + theme = "default"; + ret = 10; // means to switch to default + } + + // Apply the KDE cursor theme to ourselves + if( !isEmpty( theme )) + XcursorSetTheme(display(), theme ); + + if (!isEmpty( size )) + XcursorSetDefaultSize(display(), atoi( size )); + + // Load the default cursor from the theme and apply it to the root window. + Cursor handle = XcursorLibraryLoadCursor(display(), "left_ptr"); + XDefineCursor(display(), appRootWindow(), handle); + XFreeCursor(display(), handle); // Don't leak the cursor + +#else + ( void ) argv; +#endif + XCloseDisplay( dpy ); + return ret; + } diff --git a/kcms/input/kcmcursortheme.cpp b/kcms/input/kcmcursortheme.cpp new file mode 100644 index 0000000000..68f44bb287 --- /dev/null +++ b/kcms/input/kcmcursortheme.cpp @@ -0,0 +1,70 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "kcmcursortheme.h" + +#include +#include +#include + +K_PLUGIN_FACTORY(CursorThemeConfigFactory, + registerPlugin(); +) +K_EXPORT_PLUGIN(CursorThemeConfigFactory("kcm_cursortheme", "kcminput")) + + +CursorThemeConfig::CursorThemeConfig(QWidget *parent, const QVariantList &args) + : KCModule(parent, args) +{ + QLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + + themepage = new ThemePage(this); + connect(themepage, SIGNAL(changed(bool)), SLOT(changed())); + layout->addWidget(themepage); + + KAboutData* aboutData = new KAboutData(QStringLiteral("kcm_cursortheme"), QString(), i18n("Cursor Theme"), + QString(), QString(), KAboutData::License_GPL, i18n("(c) 2003-2007 Fredrik Höglund")); + aboutData->addAuthor(i18n("Fredrik Höglund")); + setAboutData(aboutData); +} + +CursorThemeConfig::~CursorThemeConfig() +{ + /* */ +} + +void CursorThemeConfig::load() +{ + themepage->load(); + emit changed(false); +} + +void CursorThemeConfig::save() +{ + themepage->save(); + emit changed(false); +} + +void CursorThemeConfig::defaults() +{ + themepage->defaults(); + changed(); +} + +#include "kcmcursortheme.moc" diff --git a/kcms/input/kcmcursortheme.h b/kcms/input/kcmcursortheme.h new file mode 100644 index 0000000000..d9e32b2359 --- /dev/null +++ b/kcms/input/kcmcursortheme.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 KCMCURSORTHEME_H +#define KCMCURSORTHEME_H + +#include +#include "themepage.h" + +class CursorThemeConfig : public KCModule +{ + Q_OBJECT + +public: + CursorThemeConfig(QWidget *parent, const QVariantList &); + ~CursorThemeConfig(); + +public: + void load(); + void save(); + void defaults(); + +private: + ThemePage *themepage; +}; + +#endif diff --git a/kcms/input/kmousedlg.ui b/kcms/input/kmousedlg.ui new file mode 100644 index 0000000000..b48a6065fa --- /dev/null +++ b/kcms/input/kmousedlg.ui @@ -0,0 +1,295 @@ + + + KMouseDlg + + + + 0 + 0 + 416 + 329 + + + + + + + + + + + + 0 + 0 + + + + Button Order + + + true + + + + + + Righ&t handed + + + true + + + + + + + Le&ft handed + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 1 + 1 + + + + + + + + + + + Change the direction of scrolling for the mouse wheel or the 4th and 5th mouse buttons. + + + Re&verse scroll direction + + + + + + + + + + 0 + 0 + + + + + 96 + 80 + + + + true + + + + + + + + + Icons + + + + + + Dou&ble-click to open files and folders (select icons on first click) + + + false + + + + + + + &Single-click to open files and folders + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + Cha&nge pointer shape over icons + + + true + + + + + + + A&utomatically select icons + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + false + + + + 0 + 0 + + + + Delay + + + 0 + + + 2000 + + + 125 + + + ms + + + true + + + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 1 + + + + + + + + + KIntNumInput + QWidget +
    knuminput.h
    +
    +
    + + rightHanded + leftHanded + cbScrollPolarity + doubleClick + singleClick + cb_pointershape + cbAutoSelect + + + kdialog.h + + + + + singleClick + toggled(bool) + cb_pointershape + setEnabled(bool) + + + 40 + 209 + + + 69 + 240 + + + + + singleClick + toggled(bool) + cbAutoSelect + setEnabled(bool) + + + 40 + 209 + + + 69 + 264 + + + + +
    diff --git a/kcms/input/logitechmouse.cpp b/kcms/input/logitechmouse.cpp new file mode 100644 index 0000000000..2b856c3c6c --- /dev/null +++ b/kcms/input/logitechmouse.cpp @@ -0,0 +1,421 @@ +/* + * logitechmouse.cpp + * + * Copyright (C) 2004 Brad Hards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_LIBUSB +#include + +#include "logitechmouse.h" + +LogitechMouse::LogitechMouse( struct usb_device *usbDev, int mouseCapabilityFlags, QWidget* parent, const char* name ) + : LogitechMouseBase( parent ) + , m_resolution( 0 ) +{ + if ( !name ) + setObjectName( "LogitechMouse" ); + + cordlessNameLabel->setText( i18n("Mouse type: %1", objectName() ) ); + + m_mouseCapabilityFlags = mouseCapabilityFlags; + + m_usbDeviceHandle = usb_open( usbDev ); + + if ( !m_usbDeviceHandle ) { + kWarning() << "Error opening usbfs file: " << usb_strerror() ; + return; + } + + if ( mouseCapabilityFlags & USE_CH2 ) { + m_useSecondChannel = 0x0100; + } else { + m_useSecondChannel = 0x0000; + } + + permissionProblemText->hide(); + + if ( mouseCapabilityFlags & HAS_RES ) { + updateResolution(); + resolutionSelector->setEnabled( true ); + + connect( button400cpi, SIGNAL(clicked()), parent, SLOT(changed()) ); + connect( button800cpi, SIGNAL(clicked()), parent, SLOT(changed()) ); + + if ( 4 == resolution() ) { + button800cpi->setChecked( true ); + } else if ( 3 == resolution() ) { + button400cpi->setChecked( true ); + } else { + // it must have failed, try to help out + resolutionSelector->setEnabled(false); + permissionProblemText->show(); + } + } + + if ( mouseCapabilityFlags & HAS_CSR ) { + + initCordlessStatusReporting(); + + // Do a name + cordlessNameLabel->setText( i18n("Mouse type: %1", cordlessName() ) ); + cordlessNameLabel->setEnabled( true ); + + // Display the battery power level - the level gets updated in updateGUI() + batteryBox->setEnabled( true ); + + // Channel + channelSelector->setEnabled( true ); + // if the channel is changed, we need to turn off the timer, otherwise it + // just resets the button to reflect the current status. The timer is + // started again when we applyChanges() + connect( channel1, SIGNAL(clicked()), this, SLOT(stopTimerForNow()) ); + connect( channel1, SIGNAL(clicked()), parent, SLOT(changed()) ); + if ( isDualChannelCapable() ) { + channel2->setEnabled( true ); + connect( channel2, SIGNAL(clicked()), this, SLOT(stopTimerForNow()) ); + connect( channel2, SIGNAL(clicked()), parent, SLOT(changed()) ); + } + + updateGUI(); + } + +} + +LogitechMouse::~LogitechMouse() +{ + if ( m_usbDeviceHandle ) + usb_close( m_usbDeviceHandle ); +} + +void LogitechMouse::initCordlessStatusReporting() +{ + updateCordlessStatus(); + doUpdate = new QTimer( this ); // will be automatically deleted + connect( doUpdate, SIGNAL(timeout()), this, SLOT(updateGUI()) ); + doUpdate->start( 20000 ); +} + +void LogitechMouse::updateCordlessStatus() +{ + QByteArray status(8, '\0'); + + int result = -1; + + if ( m_usbDeviceHandle ) + result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR | USB_ENDPOINT_IN,0x09, + (0x0003 | m_useSecondChannel), + (0x0000 | m_useSecondChannel), + status.data(), + 0x0008, + 1000); + + if (0 > result) { + // We probably have a permission problem + m_channel = 0; + channelSelector->setEnabled( false ); + batteryBox->setEnabled( false ); + cordlessNameLabel->hide(); + permissionProblemText->show(); + } else { + // kDebug() << "P6 (connect status): " << (status[0] & 0xFF); + if ( status[0] & 0x20 ) { // mouse is talking + m_connectStatus = ( status[0] & 0x80 ); + m_mousePowerup = ( status[0] & 0x40 ); + m_receiverUnlock = ( status[0] & 0x10 ); + m_waitLock = ( status[0] & 0x08 ); + } + + // kDebug() << "P0 (receiver type): " << (status[1] & 0xFF); + /* + 0x38 = pid C501 + 0x39 = pid C502 + 0x3B = pid C504 + 0x3C = pid C508 + 0x3D = pid C506 + 0x3E = pid C505 + */ + + m_cordlessNameIndex = (status[2] & 0xFF); + + m_batteryLevel = (status[3] & 0x07 ); + if ( status[3] & 0x08 ) { + m_channel = 2; + } else { + m_channel = 1; + } + + m_cordlessSecurity = ( ( status[4] ) & ( status[5] << 8 ) ); + + m_caseShape = ( status[6] & 0x7F ); + + // kDebug() << "PB1 (device Capabilities): " << (status[7] & 0xFF); + m_numberOfButtons = 2 + ( status[7] & 0x07 ); // 9 means something more than 8 + m_twoChannelCapable = ( status[7] & 0x40 ); + m_verticalRoller = ( status[7] & 0x08 ); + m_horizontalRoller = ( status[7] & 0x10 ); + m_has800cpi = ( status[7] & 0x20 ); + } + +} + +void LogitechMouse::updateGUI() +{ + updateCordlessStatus(); + + batteryBar->setValue( batteryLevel() ); + + if ( isDualChannelCapable() ) { + if ( 2 == channel() ) { + channel2->setChecked( true ); + } else if ( 1 == channel() ) { + channel1->setChecked( true ); + } // else it might have failed - we don't do anything + } +} + +void LogitechMouse::stopTimerForNow() +{ + doUpdate->stop(); +} + +void LogitechMouse::applyChanges() +{ + if ( m_mouseCapabilityFlags & HAS_RES ) { + if ( ( resolution() == 4 ) && ( button400cpi->isChecked() ) ) { + // then we are in 800cpi mode, but want 400cpi + setLogitechTo400(); + } else if ( ( resolution() == 3 ) && (button800cpi->isChecked() ) ) { + // then we are in 400 cpi mode, but want 800 cpi + setLogitechTo800(); + } + } + + if ( isDualChannelCapable() ) { + if ( ( channel() == 2 ) && ( channel1->isChecked() ) ) { + // we are on channel 2, but want channel 1 + setChannel1(); + KMessageBox::information(this, i18n("RF channel 1 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") ); + } else if ( ( channel() == 1 ) && ( channel2->isChecked() ) ) { + // we are on channel 1, but want channel 2 + setChannel2(); + KMessageBox::information(this, i18n("RF channel 2 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") ); + } + + initCordlessStatusReporting(); + } +} + +void LogitechMouse::save(KConfig * /*config*/) +{ + kDebug() << "Logitech mouse settings not saved - not implemented yet"; +} + +quint8 LogitechMouse::resolution() +{ + // kDebug() << "resolution: " << m_resolution; + if ( 0 == m_resolution ) { + updateResolution(); + } + return m_resolution; +} + +void LogitechMouse::updateResolution() +{ + char resolution; + + int result = -1; + + if ( m_usbDeviceHandle ) + result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR | USB_ENDPOINT_IN, + 0x01, + 0x000E, + 0x0000, + &resolution, + 0x0001, + 100); + + // kDebug() << "resolution is: " << resolution; + if (0 > result) { + kWarning() << "Error getting resolution from device : " << usb_strerror() ; + m_resolution = 0; + } else { + m_resolution = resolution; + } +} + +void LogitechMouse::setLogitechTo800() +{ + int result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR, + 0x02, + 0x000E, + 4, + NULL, + 0x0000, + 100); + if (0 > result) { + kWarning() << "Error setting resolution on device: " << usb_strerror() ; + } +} + +void LogitechMouse::setLogitechTo400() +{ + int result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR, + 0x02, + 0x000E, + 3, + NULL, + 0x0000, + 100); + if (0 > result) { + kWarning() << "Error setting resolution on device: " << usb_strerror() ; + } +} + +quint8 LogitechMouse::batteryLevel() const +{ + return m_batteryLevel; +} + + +quint8 LogitechMouse::channel() const +{ + return m_channel; +} + +bool LogitechMouse::isDualChannelCapable() const +{ + return m_twoChannelCapable; +} + +void LogitechMouse::setChannel1() +{ + int result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR, + 0x02, + (0x0008 | m_useSecondChannel), + (0x0000 | m_useSecondChannel), + NULL, + 0x0000, + 1000); + + if (0 > result) { + kWarning() << "Error setting mouse to channel 1 : " << usb_strerror() ; + } + +} + +void LogitechMouse::setChannel2() +{ + int result = usb_control_msg( m_usbDeviceHandle, + USB_TYPE_VENDOR, + 0x02, + (0x0008 | m_useSecondChannel), + (0x0001 | m_useSecondChannel), + NULL, + 0x0000, + 1000); + + if (0 > result) { + kWarning() << "Error setting mouse to channel 2 : " << usb_strerror() ; + } + +} + +QString LogitechMouse::cordlessName() const +{ + switch ( m_cordlessNameIndex ) { + case 0x00: + return i18nc( "no cordless mouse", "none" ); + break; + case 0x04: + return i18n( "Cordless Mouse" ); + break; + case 0x05: + return i18n( "Cordless Wheel Mouse" ); + break; + case 0x06: + return i18n( "Cordless MouseMan Wheel" ); + break; + case 0x07: + return i18n( "Cordless Wheel Mouse" ); + break; + case 0x08: + return i18n( "Cordless Wheel Mouse" ); + break; + case 0x09: + return i18n( "Cordless TrackMan Wheel" ); + break; + case 0x0A: + return i18n( "TrackMan Live" ); + break; + case 0x0C: + return i18n( "Cordless TrackMan FX" ); + break; + case 0x0D: + return i18n( "Cordless MouseMan Optical" ); + break; + case 0x0E: + return i18n( "Cordless Optical Mouse" ); + break; + case 0x0F: + return i18n( "Cordless Mouse" ); + break; + case 0x12: + return i18n( "Cordless MouseMan Optical (2ch)" ); + break; + case 0x13: + return i18n( "Cordless Optical Mouse (2ch)" ); + break; + case 0x14: + return i18n( "Cordless Mouse (2ch)" ); + break; + case 0x82: + return i18n( "Cordless Optical TrackMan" ); + break; + case 0x8A: + return i18n( "MX700 Cordless Optical Mouse" ); + break; + case 0x8B: + return i18n( "MX700 Cordless Optical Mouse (2ch)" ); + break; + default: + return i18n( "Unknown mouse"); + } +} + +#include "logitechmouse.moc" + +#endif + diff --git a/kcms/input/logitechmouse.h b/kcms/input/logitechmouse.h new file mode 100644 index 0000000000..cc4f5f6210 --- /dev/null +++ b/kcms/input/logitechmouse.h @@ -0,0 +1,107 @@ +/* + * logitechmouse.h + * + * Copyright (C) 2004 Brad Hards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __LOGITECHMOUSE_H__ +#define __LOGITECHMOUSE_H__ + +#include + +#include + +#include + +#include "ui_logitechmouse_base.h" + +#include + +#define VENDOR_LOGITECH 0x046D +#define HAS_RES 0x01 /* mouse supports variable resolution */ +#define HAS_SS 0x02 /* mouse supports smart scroll control */ +#define HAS_CSR 0x04 /* mouse supports cordless status reporting and control */ +#define HAS_SSR 0x08 /* mouse supports smart scroll reporting */ +#define USE_CH2 0x10 /* mouse needs to use the second channel */ + +class LogitechMouseBase : public QWidget, public Ui::LogitechMouseBase +{ +public: + LogitechMouseBase( QWidget *parent ) : QWidget( parent ) { + setupUi( this ); + } +}; + + + +class LogitechMouse : public LogitechMouseBase +{ + Q_OBJECT + +public: + LogitechMouse( struct usb_device *usbDev, int mouseCapabilityFlags, QWidget* parent = 0, const char* name=0); + ~LogitechMouse(); + void applyChanges(); + void save(KConfig *config); + +protected Q_SLOTS: + void setChannel1(); + void setChannel2(); + void updateGUI(); + void stopTimerForNow(); + +private: + void initCordlessStatusReporting(); + void updateCordlessStatus(); + + void setLogitechTo400(); + void setLogitechTo800(); + + QString cordlessName() const ; + quint8 resolution(); + void updateResolution(); + quint8 batteryLevel() const; + quint8 channel() const; + bool isDualChannelCapable() const; + + QTimer *doUpdate; + + struct usb_dev_handle *m_usbDeviceHandle; + bool m_connectStatus; // true if the CONNECT button on the mouse is pressed + bool m_mousePowerup; // true if we are doing "just out of the box" auto-locking + bool m_receiverUnlock; // true if mouse has been disconnected by a long press + // of the receiver's CONNECT button + bool m_waitLock; // true if receiver searching for new mouse because the + // CONNECT button on the receiver was pressed + quint8 m_batteryLevel; + quint8 m_channel; + quint8 m_cordlessNameIndex; // this gets convered into a QString in cordlessName() + quint16 m_cordlessSecurity; + quint16 m_useSecondChannel; + quint8 m_caseShape; + quint8 m_numberOfButtons; + quint8 m_resolution; + bool m_twoChannelCapable; // true if the mouse supports dual channels + bool m_verticalRoller; // true if the mouse has a vertical roller (wheel) + bool m_horizontalRoller; // true if the mouse has a horizontal roller (wheel) + bool m_has800cpi; // true if the mouse does 800cpi resolution + int m_mouseCapabilityFlags; +}; + +#endif + diff --git a/kcms/input/logitechmouse.usermap b/kcms/input/logitechmouse.usermap new file mode 100644 index 0000000000..65da520c53 --- /dev/null +++ b/kcms/input/logitechmouse.usermap @@ -0,0 +1,35 @@ +# script match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info +# Wheel Mouse Optical +consoleUserPerms 0x0003 0x046d 0xc00e 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MouseMan Traveler +consoleUserPerms 0x0003 0x046d 0xc00f 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MouseMan Dual Optical +consoleUserPerms 0x0003 0x046d 0xc012 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX310 Optical Mouse +consoleUserPerms 0x0003 0x046d 0xc01b 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX510 Optical Mouse +consoleUserPerms 0x0003 0x046d 0xc01d 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX300 Optical Mouse +consoleUserPerms 0x0003 0x046d 0xc024 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX500 Optical Mouse +consoleUserPerms 0x0003 0x046d 0xc025 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# iFeel Mouse +consoleUserPerms 0x0003 0x046d 0xc031 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Mouse Receiver +consoleUserPerms 0x0003 0x046d 0xc501 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Dual Receiver +consoleUserPerms 0x0003 0x046d 0xc502 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Cordless Freedom Optical +consoleUserPerms 0x0003 0x046d 0xc504 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Cordless Elite Duo +consoleUserPerms 0x0003 0x046d 0xc505 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX700 Optical Mouse +consoleUserPerms 0x0003 0x046d 0xc506 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Cordless Optical Trackman +consoleUserPerms 0x0003 0x046d 0xc508 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Cordless MX Duo Receiver +consoleUserPerms 0x0003 0x046d 0xc50b 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# MX100 Laser Mouse +consoleUserPerms 0x0003 0x046d 0xc50e 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 +# Receiver for Cordless Presenter +consoleUserPerms 0x0003 0x046d 0xc702 0x0000 0xffff 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 diff --git a/kcms/input/logitechmouse_base.ui b/kcms/input/logitechmouse_base.ui new file mode 100644 index 0000000000..13ac59e511 --- /dev/null +++ b/kcms/input/logitechmouse_base.ui @@ -0,0 +1,134 @@ + + LogitechMouseBase + + + + + + Cordless Name + + + false + + + + + + + false + + + Sensor Resolution + + + + + + 400 counts per inch + + + 1 + + + + + + + 800 counts per inch + + + 1 + + + + + + + + + + false + + + Battery Level + + + + + + 7 + + + + + + + + + + false + + + RF Channel + + + + + + Channel 1 + + + true + + + 3 + + + + + + + false + + + Channel 2 + + + 3 + + + + + + + + + + You have a Logitech Mouse connected, and libusb was found at compile time, but it was not possible to access this mouse. This is probably caused by a permissions problem - you should consult the manual on how to fix this. + + + Qt::AlignVCenter + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/kcms/input/main.cpp b/kcms/input/main.cpp new file mode 100644 index 0000000000..e68044c1ec --- /dev/null +++ b/kcms/input/main.cpp @@ -0,0 +1,94 @@ +/* + * main.cpp + * + * Copyright (c) 1999 Matthias Hoelzer-Kluepfel + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 + +#include +#include +#include +#include +#include + +#include "mouse.h" +#include + +#include + +#include +#ifdef HAVE_XCURSOR +# include +#endif + +extern "C" +{ + Q_DECL_EXPORT void kcminit_mouse() + { + KConfig *config = new KConfig("kcminputrc", KConfig::NoGlobals ); + MouseSettings settings; + settings.load(config); + settings.apply(true); // force + +#ifdef HAVE_XCURSOR + KConfigGroup group = config->group("Mouse"); + QString theme = group.readEntry("cursorTheme", QString()); + QString size = group.readEntry("cursorSize", QString()); + + // Note: If you update this code, update kapplymousetheme as well. + + // use a default value for theme only if it's not configured at all, not even in X resources + if( theme.isEmpty() + && QByteArray( XGetDefault( QX11Info::display(), "Xcursor", "theme" )).isEmpty() + && QByteArray( XcursorGetTheme( QX11Info::display())).isEmpty()) + { + theme = "default"; + } + + // Apply the KDE cursor theme to ourselves + if( !theme.isEmpty()) + XcursorSetTheme(QX11Info::display(), QFile::encodeName(theme)); + + if (!size.isEmpty()) + XcursorSetDefaultSize(QX11Info::display(), size.toUInt()); + + // Load the default cursor from the theme and apply it to the root window. + Cursor handle = XcursorLibraryLoadCursor(QX11Info::display(), "left_ptr"); + XDefineCursor(QX11Info::display(), QX11Info::appRootWindow(), handle); + XFreeCursor(QX11Info::display(), handle); // Don't leak the cursor + + // Tell klauncher to set the XCURSOR_THEME and XCURSOR_SIZE environment + // variables when launching applications. + OrgKdeKLauncherInterface klauncher(QStringLiteral("org.kde.klauncher5"), + QStringLiteral("/KLauncher"), + QDBusConnection::sessionBus()); + if(!theme.isEmpty()) + klauncher.setLaunchEnv(QStringLiteral("XCURSOR_THEME"), theme); + if( !size.isEmpty()) + klauncher.setLaunchEnv(QStringLiteral("XCURSOR_SIZE"), size); + +#endif + + delete config; + } +} + + diff --git a/kcms/input/mouse.cpp b/kcms/input/mouse.cpp new file mode 100644 index 0000000000..a3847ba66e --- /dev/null +++ b/kcms/input/mouse.cpp @@ -0,0 +1,821 @@ +/* + * mouse.cpp + * + * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca + * + * Layout management, enhancements: + * Copyright (c) 1999 Dirk A. Mueller + * + * SC/DC/AutoSelect/ChangeCursor: + * Copyright (c) 2000 David Faure + * + * Double click interval, drag time & dist + * Copyright (c) 2000 Bernd Gehrmann + * + * Large cursor support + * Visual activation TODO: speed + * Copyright (c) 2000 Rik Hemsley + * + * White cursor support + * TODO: give user the option to choose a certain cursor font + * -> Theming + * + * General/Advanced tabs + * Copyright (c) 2000 Brad Hughes + * + * redesign for KDE 2.2 + * Copyright (c) 2001 Ralf Nolden + * + * Logitech mouse support + * Copyright (C) 2004 Brad Hards + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#undef Below +#undef Above +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mouse.h" + +#include +#include +#include +#include +#include + +#undef Below + + +K_PLUGIN_FACTORY(MouseConfigFactory, + registerPlugin(); // mouse + ) +K_EXPORT_PLUGIN(MouseConfigFactory("kcminput")) + +MouseConfig::MouseConfig(QWidget *parent, const QVariantList &args) + : KCModule(parent, args) +{ + + + setQuickHelp( i18n("

    Mouse

    This module allows you to choose various" + " options for the way in which your pointing device works. Your" + " pointing device may be a mouse, trackball, or some other hardware" + " that performs a similar function.")); + + QString wtstr; + + QBoxLayout *top = new QVBoxLayout(this); + top->setMargin(0); + + tabwidget = new QTabWidget(this); + top->addWidget(tabwidget); + + generalTab = new KMouseDlg(this); + QButtonGroup *group = new QButtonGroup( generalTab ); + group->setExclusive( true ); + group->addButton( generalTab->singleClick ); + group->addButton( generalTab->doubleClick ); + + tabwidget->addTab(generalTab, i18n("&General")); + + group = new QButtonGroup( generalTab ); + group->setExclusive( true ); + group->addButton( generalTab->rightHanded,RIGHT_HANDED ); + group->addButton( generalTab->leftHanded,LEFT_HANDED ); + + connect(group, SIGNAL(buttonClicked(int)), this, SLOT(changed())); + connect(group, SIGNAL(buttonClicked(int)), this, SLOT(slotHandedChanged(int))); + + wtstr = i18n("If you are left-handed, you may prefer to swap the" + " functions of the left and right buttons on your pointing device" + " by choosing the 'left-handed' option. If your pointing device" + " has more than two buttons, only those that function as the" + " left and right buttons are affected. For example, if you have" + " a three-button mouse, the middle button is unaffected."); + generalTab->handedBox->setWhatsThis( wtstr ); + + connect(generalTab->doubleClick, SIGNAL(clicked()), SLOT(changed())); + + wtstr = i18n("The default behavior in KDE is to select and activate" + " icons with a single click of the left button on your pointing" + " device. This behavior is consistent with what you would expect" + " when you click links in most web browsers. If you would prefer" + " to select with a single click, and activate with a double click," + " check this option."); + generalTab->doubleClick->setWhatsThis( wtstr ); + + wtstr = i18n("Activates and opens a file or folder with a single click."); + generalTab->singleClick->setWhatsThis( wtstr ); + + + connect(generalTab->cbAutoSelect, SIGNAL(clicked()), this, SLOT(changed())); + + wtstr = i18n("If you check this option, pausing the mouse pointer" + " over an icon on the screen will automatically select that icon." + " This may be useful when single clicks activate icons, and you" + " want only to select the icon without activating it."); + generalTab->cbAutoSelect->setWhatsThis( wtstr ); + + wtstr = i18n("If you have checked the option to automatically select" + " icons, this slider allows you to select how long the mouse pointer" + " must be paused over the icon before it is selected."); + generalTab->slAutoSelect->setWhatsThis( wtstr ); + + connect(generalTab->slAutoSelect, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + connect(generalTab->cb_pointershape, SIGNAL(clicked()), this, SLOT(changed())); + + connect(generalTab->singleClick, SIGNAL(clicked()), this, SLOT(changed())); + connect(generalTab->singleClick, SIGNAL(clicked()), this, SLOT(slotClick())); + connect(generalTab->singleClick, SIGNAL(clicked()), this, SLOT(slotSmartSliderEnabling())); + + connect( generalTab->doubleClick, SIGNAL(clicked()), this, SLOT(slotClick()) ); + connect( generalTab->cbAutoSelect, SIGNAL(clicked()), this, SLOT(slotClick()) ); + connect(generalTab->cbAutoSelect, SIGNAL(clicked()), this, SLOT(slotSmartSliderEnabling())); + + + // Only allow setting reversing scroll polarity if we have scroll buttons + unsigned char map[20]; + if ( XGetPointerMapping(QX11Info::display(), map, 20) >= 5 ) + { + generalTab->cbScrollPolarity->setEnabled( true ); + generalTab->cbScrollPolarity->show(); + } + else + { + generalTab->cbScrollPolarity->setEnabled( false ); + generalTab->cbScrollPolarity->hide(); + } + connect(generalTab->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(changed())); + connect(generalTab->cbScrollPolarity, SIGNAL(clicked()), this, SLOT(slotScrollPolarityChanged())); + + // Advanced tab + advancedTab = new QWidget(0); + advancedTab->setObjectName("Advanced Tab"); + tabwidget->addTab(advancedTab, i18n("Advanced")); + + QFormLayout *lay = new QFormLayout(advancedTab); + + accel = new KDoubleNumInput(0.1, 20, 2, advancedTab, 0.1, 1); + accel->setSuffix(i18n(" x")); + lay->addRow(i18n("Pointer acceleration:"), accel); + connect(accel, SIGNAL(valueChanged(double)), this, SLOT(changed())); + + wtstr = i18n("

    This option allows you to change the relationship" + " between the distance that the mouse pointer moves on the" + " screen and the relative movement of the physical device" + " itself (which may be a mouse, trackball, or some other" + " pointing device.)

    " + " A high value for the acceleration will lead to large" + " movements of the mouse pointer on the screen even when" + " you only make a small movement with the physical device." + " Selecting very high values may result in the mouse pointer" + " flying across the screen, making it hard to control.

    "); + accel->setWhatsThis( wtstr ); + + thresh = new KIntNumInput(20, advancedTab); + thresh->setRange(0,20,1); + thresh->setSteps(1,1); + lay->addRow(i18n("Pointer threshold:"), thresh); + connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(thresh, SIGNAL(valueChanged(int)), this, SLOT(slotThreshChanged(int))); + slotThreshChanged(thresh->value()); + + wtstr = i18n("

    The threshold is the smallest distance that the" + " mouse pointer must move on the screen before acceleration" + " has any effect. If the movement is smaller than the threshold," + " the mouse pointer moves as if the acceleration was set to 1X;

    " + " thus, when you make small movements with the physical device," + " there is no acceleration at all, giving you a greater degree" + " of control over the mouse pointer. With larger movements of" + " the physical device, you can move the mouse pointer" + " rapidly to different areas on the screen.

    "); + thresh->setWhatsThis( wtstr ); + + // It would be nice if the user had a test field. + // Selecting such values in milliseconds is not intuitive + doubleClickInterval = new KIntNumInput(2000, advancedTab); + doubleClickInterval->setRange(0, 2000, 100); + doubleClickInterval->setSuffix(i18n(" msec")); + doubleClickInterval->setSteps(100, 100); + lay->addRow(i18n("Double click interval:"), doubleClickInterval); + connect(doubleClickInterval, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + wtstr = i18n("The double click interval is the maximal time" + " (in milliseconds) between two mouse clicks which" + " turns them into a double click. If the second" + " click happens later than this time interval after" + " the first click, they are recognized as two" + " separate clicks."); + doubleClickInterval->setWhatsThis( wtstr ); + + dragStartTime = new KIntNumInput(2000, advancedTab); + dragStartTime->setRange(0, 2000, 100); + dragStartTime->setSuffix(i18n(" msec")); + dragStartTime->setSteps(100, 100); + lay->addRow(i18n("Drag start time:"), dragStartTime); + connect(dragStartTime, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + wtstr = i18n("If you click with the mouse (e.g. in a multi-line" + " editor) and begin to move the mouse within the" + " drag start time, a drag operation will be initiated."); + dragStartTime->setWhatsThis( wtstr ); + + dragStartDist = new KIntNumInput(20, advancedTab); + dragStartDist->setRange(1, 20, 1); + dragStartDist->setSteps(1,1); + lay->addRow(i18n("Drag start distance:"), dragStartDist); + connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(dragStartDist, SIGNAL(valueChanged(int)), this, SLOT(slotDragStartDistChanged(int))); + slotDragStartDistChanged(dragStartDist->value()); + + wtstr = i18n("If you click with the mouse and begin to move the" + " mouse at least the drag start distance, a drag" + " operation will be initiated."); + dragStartDist->setWhatsThis( wtstr ); + + wheelScrollLines = new KIntNumInput(3, advancedTab); + wheelScrollLines->setRange(1, 12, 1); + wheelScrollLines->setSteps(1,1); + lay->addRow(i18n("Mouse wheel scrolls by:"), wheelScrollLines); + connect(wheelScrollLines, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(wheelScrollLines, SIGNAL(valueChanged(int)), SLOT(slotWheelScrollLinesChanged(int))); + slotWheelScrollLinesChanged(wheelScrollLines->value()); + + wtstr = i18n("If you use the wheel of a mouse, this value determines the number of lines to scroll for each wheel movement. Note that if this number exceeds the number of visible lines, it will be ignored and the wheel movement will be handled as a page up/down movement."); + wheelScrollLines->setWhatsThis(wtstr); + +{ + QWidget *mouse = new QWidget(this); + mouse->setObjectName("Mouse Navigation"); + tabwidget->addTab(mouse, i18n("Mouse Navigation")); + + QFormLayout *form = new QFormLayout(mouse); + + mouseKeys = new QCheckBox(i18n("&Move pointer with keyboard (using the num pad)"), mouse); + form->addRow(mouseKeys); + + mk_delay = new KIntNumInput(mouse); + mk_delay->setRange(1, 1000, 50); + mk_delay->setSuffix(i18n(" msec")); + form->addRow(i18n("&Acceleration delay:"), mk_delay); + + mk_interval = new KIntNumInput(0, mouse); + mk_interval->setRange(1, 1000, 10); + mk_interval->setSuffix(i18n(" msec")); + form->addRow(i18n("R&epeat interval:"), mk_interval); + + mk_time_to_max = new KIntNumInput(0, mouse); + mk_time_to_max->setRange(100, 10000, 200); + mk_time_to_max->setSuffix(i18n(" msec")); + form->addRow(i18n("Acceleration &time:"), mk_time_to_max); + + mk_max_speed = new KIntNumInput(0, mouse); + mk_max_speed->setRange(1, 2000, 20); + mk_max_speed->setSuffix(i18n(" pixel/sec")); + form->addRow(i18n("Ma&ximum speed:"), mk_max_speed); + + mk_curve = new KIntNumInput(0, mouse); + mk_curve->setRange(-1000, 1000, 100); + form->addRow(i18n("Acceleration &profile:"), mk_curve); + + connect(mouseKeys, SIGNAL(clicked()), this, SLOT(checkAccess())); + connect(mouseKeys, SIGNAL(clicked()), this, SLOT(changed())); + connect(mk_delay, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(mk_interval, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(mk_time_to_max, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(mk_max_speed, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(mk_curve, SIGNAL(valueChanged(int)), this, SLOT(changed())); +} + + settings = new MouseSettings; + + // This part is for handling features on Logitech USB mice. + // It only works if libusb is available. +#ifdef HAVE_LIBUSB + + static const + struct device_table { + int idVendor; + int idProduct; + const char* Model; + const char* Name; + int flags; + } device_table[] = { + { VENDOR_LOGITECH, 0xC00E, "M-BJ58", "Wheel Mouse Optical", HAS_RES }, + { VENDOR_LOGITECH, 0xC00F, "M-BJ79", "MouseMan Traveler", HAS_RES }, + { VENDOR_LOGITECH, 0xC012, "M-BL63B", "MouseMan Dual Optical", HAS_RES }, + { VENDOR_LOGITECH, 0xC01B, "M-BP86", "MX310 Optical Mouse", HAS_RES }, + { VENDOR_LOGITECH, 0xC01D, "M-BS81A", "MX510 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR }, + { VENDOR_LOGITECH, 0xC024, "M-BP82", "MX300 Optical Mouse", HAS_RES }, + { VENDOR_LOGITECH, 0xC025, "M-BP81A", "MX500 Optical Mouse", HAS_RES | HAS_SS | HAS_SSR }, + { VENDOR_LOGITECH, 0xC031, "M-UT58A", "iFeel Mouse (silver)", HAS_RES }, + { VENDOR_LOGITECH, 0xC501, "C-BA4-MSE", "Mouse Receiver", HAS_CSR }, + { VENDOR_LOGITECH, 0xC502, "C-UA3-DUAL", "Dual Receiver", HAS_CSR | USE_CH2}, + { VENDOR_LOGITECH, 0xC504, "C-BD9-DUAL", "Cordless Freedom Optical", HAS_CSR | USE_CH2 }, + { VENDOR_LOGITECH, 0xC505, "C-BG17-DUAL", "Cordless Elite Duo", HAS_SS | HAS_SSR | HAS_CSR | USE_CH2}, + { VENDOR_LOGITECH, 0xC506, "C-BF16-MSE", "MX700 Optical Mouse", HAS_SS | HAS_CSR }, + { VENDOR_LOGITECH, 0xC508, "C-BA4-MSE", "Cordless Optical TrackMan", HAS_SS | HAS_CSR }, + { VENDOR_LOGITECH, 0xC50B, "967300-0403", "Cordless MX Duo Receiver", HAS_SS|HAS_CSR }, + { VENDOR_LOGITECH, 0xC50E, "M-RAG97", "MX1000 Laser Mouse", HAS_SS | HAS_CSR }, + { VENDOR_LOGITECH, 0xC702, "C-UF15", "Receiver for Cordless Presenter", HAS_CSR }, + { 0, 0, 0, 0, 0 } + }; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + struct usb_bus *bus; + struct usb_device *dev; + + for (bus = usb_busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + for (int n = 0; device_table[n].idVendor; n++) + if ( (device_table[n].idVendor == dev->descriptor.idVendor) && + (device_table[n].idProduct == dev->descriptor.idProduct) ) { + // OK, we have a device that appears to be one of the ones we support + LogitechMouse *mouse = new LogitechMouse( dev, device_table[n].flags, this, device_table[n].Name ); + settings->logitechMouseList.append(mouse); + tabwidget->addTab( (QWidget*)mouse, device_table[n].Name ); + } + } + } + +#endif + + KAboutData* about = new KAboutData(QStringLiteral("kcmmouse"), QString(), i18n("Mouse"), QString(), QString(), + KAboutData::License_GPL, i18n("(c) 1997 - 2005 Mouse developers")); + about->addAuthor(i18n("Patrick Dowler")); + about->addAuthor(i18n("Dirk A. Mueller")); + about->addAuthor(i18n("David Faure")); + about->addAuthor(i18n("Bernd Gehrmann")); + about->addAuthor(i18n("Rik Hemsley")); + about->addAuthor(i18n("Brad Hughes")); + about->addAuthor(i18n("Ralf Nolden")); + about->addAuthor(i18n("Brad Hards")); + setAboutData( about ); +} + +void MouseConfig::checkAccess() +{ + mk_delay->setEnabled(mouseKeys->isChecked()); + mk_interval->setEnabled(mouseKeys->isChecked()); + mk_time_to_max->setEnabled(mouseKeys->isChecked()); + mk_max_speed->setEnabled(mouseKeys->isChecked()); + mk_curve->setEnabled(mouseKeys->isChecked()); +} + + +MouseConfig::~MouseConfig() +{ + delete settings; +} + +double MouseConfig::getAccel() +{ + return accel->value(); +} + +void MouseConfig::setAccel(double val) +{ + accel->setValue(val); +} + +int MouseConfig::getThreshold() +{ + return thresh->value(); +} + +void MouseConfig::setThreshold(int val) +{ + thresh->setValue(val); +} + + +int MouseConfig::getHandedness() +{ + if (generalTab->rightHanded->isChecked()) + return RIGHT_HANDED; + else + return LEFT_HANDED; +} + +void MouseConfig::setHandedness(int val) +{ + generalTab->rightHanded->setChecked(false); + generalTab->leftHanded->setChecked(false); + if (val == RIGHT_HANDED){ + generalTab->rightHanded->setChecked(true); + generalTab->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_rh.png")); + } + else{ + generalTab->leftHanded->setChecked(true); + generalTab->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png")); + } + settings->m_handedNeedsApply = true; +} + +void MouseConfig::load() +{ + KConfig config( "kcminputrc" ); + settings->load(&config); + + generalTab->rightHanded->setEnabled(settings->handedEnabled); + generalTab->leftHanded->setEnabled(settings->handedEnabled); + if ( generalTab->cbScrollPolarity->isEnabled() ) + generalTab->cbScrollPolarity->setEnabled(settings->handedEnabled); + generalTab->cbScrollPolarity->setChecked( settings->reverseScrollPolarity ); + + setAccel(settings->accelRate); + setThreshold(settings->thresholdMove); + setHandedness(settings->handed); + + doubleClickInterval->setValue(settings->doubleClickInterval); + dragStartTime->setValue(settings->dragStartTime); + dragStartDist->setValue(settings->dragStartDist); + wheelScrollLines->setValue(settings->wheelScrollLines); + + generalTab->singleClick->setChecked( settings->singleClick ); + generalTab->doubleClick->setChecked(!settings->singleClick); + generalTab->cb_pointershape->setChecked(settings->changeCursor); + generalTab->cbAutoSelect->setChecked( settings->autoSelectDelay >= 0 ); + if ( settings->autoSelectDelay < 0 ) + generalTab->slAutoSelect->setValue( 0 ); + else + generalTab->slAutoSelect->setValue( settings->autoSelectDelay ); + slotClick(); + + + KConfig ac("kaccessrc"); + + KConfigGroup group = ac.group("Mouse"); + mouseKeys->setChecked(group.readEntry("MouseKeys", false)); + mk_delay->setValue(group.readEntry("MKDelay", 160)); + + int interval = group.readEntry("MKInterval", 5); + mk_interval->setValue(interval); + + // Default time to reach maximum speed: 5000 msec + int time_to_max = group.readEntry("MKTimeToMax", (5000+interval/2)/interval); + time_to_max = group.readEntry("MK-TimeToMax", time_to_max*interval); + mk_time_to_max->setValue(time_to_max); + + // Default maximum speed: 1000 pixels/sec + // (The old default maximum speed from KDE <= 3.4 + // (100000 pixels/sec) was way too fast) + long max_speed = group.readEntry("MKMaxSpeed", interval); + max_speed = max_speed * 1000 / interval; + if (max_speed > 2000) + max_speed = 2000; + max_speed = group.readEntry("MK-MaxSpeed", int(max_speed)); + mk_max_speed->setValue(max_speed); + + mk_curve->setValue(group.readEntry("MKCurve", 0)); + + checkAccess(); + + emit changed(false); +} + +void MouseConfig::save() +{ + settings->accelRate = getAccel(); + settings->thresholdMove = getThreshold(); + settings->handed = getHandedness(); + + settings->doubleClickInterval = doubleClickInterval->value(); + settings->dragStartTime = dragStartTime->value(); + settings->dragStartDist = dragStartDist->value(); + settings->wheelScrollLines = wheelScrollLines->value(); + settings->singleClick = !generalTab->doubleClick->isChecked(); + settings->autoSelectDelay = generalTab->cbAutoSelect->isChecked()? generalTab->slAutoSelect->value():-1; +// settings->changeCursor = generalTab->singleClick->isChecked(); + settings->changeCursor = generalTab->cb_pointershape->isChecked(); + settings->reverseScrollPolarity = generalTab->cbScrollPolarity->isChecked(); + + settings->apply(); + KConfig config( "kcminputrc" ); + settings->save(&config); + + KConfig ac("kaccessrc"); + + KConfigGroup group = ac.group("Mouse"); + + int interval = mk_interval->value(); + group.writeEntry("MouseKeys", mouseKeys->isChecked()); + group.writeEntry("MKDelay", mk_delay->value()); + group.writeEntry("MKInterval", interval); + group.writeEntry("MK-TimeToMax", mk_time_to_max->value()); + group.writeEntry("MKTimeToMax", + (mk_time_to_max->value() + interval/2)/interval); + group.writeEntry("MK-MaxSpeed", mk_max_speed->value()); + group.writeEntry("MKMaxSpeed", + (mk_max_speed->value()*interval + 500)/1000); + group.writeEntry("MKCurve", mk_curve->value()); + group.sync(); + group.writeEntry("MKCurve", mk_curve->value()); + + // restart kaccess + KToolInvocation::startServiceByDesktopName("kaccess"); + + emit changed(false); +} + +void MouseConfig::defaults() +{ + setThreshold(2); + setAccel(2); + setHandedness(RIGHT_HANDED); + generalTab->cbScrollPolarity->setChecked( false ); + doubleClickInterval->setValue(400); + dragStartTime->setValue(500); + dragStartDist->setValue(4); + wheelScrollLines->setValue(3); + generalTab->doubleClick->setChecked( !KDE_DEFAULT_SINGLECLICK ); + generalTab->cbAutoSelect->setChecked( KDE_DEFAULT_AUTOSELECTDELAY != -1 ); + generalTab->slAutoSelect->setValue( KDE_DEFAULT_AUTOSELECTDELAY == -1 ? 50 : KDE_DEFAULT_AUTOSELECTDELAY ); + generalTab->singleClick->setChecked( KDE_DEFAULT_SINGLECLICK ); + generalTab->cb_pointershape->setChecked(KDE_DEFAULT_CHANGECURSOR); + slotClick(); + + mouseKeys->setChecked(false); + mk_delay->setValue(160); + mk_interval->setValue(5); + mk_time_to_max->setValue(5000); + mk_max_speed->setValue(1000); + mk_curve->setValue(0); + + checkAccess(); + + changed(); +} + +void MouseConfig::slotClick() +{ + // Autoselect has a meaning only in single-click mode + generalTab->cbAutoSelect->setEnabled(!generalTab->doubleClick->isChecked() || generalTab->singleClick->isChecked()); + // Delay has a meaning only for autoselect + bool bDelay = generalTab->cbAutoSelect->isChecked() && ! generalTab->doubleClick->isChecked(); + generalTab->slAutoSelect->setEnabled( bDelay ); +} + +/** No descriptions */ +void MouseConfig::slotHandedChanged(int val){ + if(val==RIGHT_HANDED) + generalTab->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_rh.png")); + else + generalTab->mousePix->setPixmap(KStandardDirs::locate("data", "kcminput/pics/mouse_lh.png")); + settings->m_handedNeedsApply = true; +} + +void MouseSettings::load(KConfig *config) +{ + int accel_num, accel_den, threshold; + double accel; + XGetPointerControl( QX11Info::display(), + &accel_num, &accel_den, &threshold ); + accel = float(accel_num) / float(accel_den); + + // get settings from X server + int h = RIGHT_HANDED; + unsigned char map[20]; + num_buttons = XGetPointerMapping(QX11Info::display(), map, 20); + + handedEnabled = true; + + // ## keep this in sync with KGlobalSettings::mouseSettings + if( num_buttons == 1 ) + { + /* disable button remapping */ + handedEnabled = false; + } + else if( num_buttons == 2 ) + { + if ( (int)map[0] == 1 && (int)map[1] == 2 ) + h = RIGHT_HANDED; + else if ( (int)map[0] == 2 && (int)map[1] == 1 ) + h = LEFT_HANDED; + else + /* custom button setup: disable button remapping */ + handedEnabled = false; + } + else + { + middle_button = (int)map[1]; + if ( (int)map[0] == 1 && (int)map[2] == 3 ) + h = RIGHT_HANDED; + else if ( (int)map[0] == 3 && (int)map[2] == 1 ) + h = LEFT_HANDED; + else + { + /* custom button setup: disable button remapping */ + handedEnabled = false; + } + } + + KConfigGroup group = config->group("Mouse"); + double a = group.readEntry("Acceleration",-1.0); + if (a == -1) + accelRate = accel; + else + accelRate = a; + + int t = group.readEntry("Threshold",-1); + if (t == -1) + thresholdMove = threshold; + else + thresholdMove = t; + + QString key = group.readEntry("MouseButtonMapping"); + if (key == "RightHanded") + handed = RIGHT_HANDED; + else if (key == "LeftHanded") + handed = LEFT_HANDED; +#ifdef __GNUC__ +#warning was key == NULL how was this working? is key.isNull() what the coder meant? +#endif + else if (key.isNull()) + handed = h; + reverseScrollPolarity = group.readEntry( "ReverseScrollPolarity", false); + m_handedNeedsApply = false; + + // SC/DC/AutoSelect/ChangeCursor + group = config->group("KDE"); + doubleClickInterval = group.readEntry("DoubleClickInterval", 400); + dragStartTime = group.readEntry("StartDragTime", 500); + dragStartDist = group.readEntry("StartDragDist", 4); + wheelScrollLines = group.readEntry("WheelScrollLines", 3); + + singleClick = group.readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK); + autoSelectDelay = group.readEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY); + changeCursor = group.readEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR); +} + +void MouseConfig::slotThreshChanged(int value) +{ + thresh->setSuffix(i18np(" pixel", " pixels", value)); +} + +void MouseConfig::slotDragStartDistChanged(int value) +{ + dragStartDist->setSuffix(i18np(" pixel", " pixels", value)); +} + +void MouseConfig::slotWheelScrollLinesChanged(int value) +{ + wheelScrollLines->setSuffix(i18np(" line", " lines", value)); +} + +void MouseSettings::apply(bool force) +{ + XChangePointerControl( QX11Info::display(), + true, true, int(qRound(accelRate*10)), 10, thresholdMove); + + // 256 might seems extreme, but X has already been known to return 32, + // and we don't want to truncate things. Xlib limits the table to 256 bytes, + // so it's a good uper bound.. + unsigned char map[256]; + num_buttons = XGetPointerMapping(QX11Info::display(), map, 256); + + int remap=(num_buttons>=1); + if (handedEnabled && (m_handedNeedsApply || force)) { + if( num_buttons == 1 ) + { + map[0] = (unsigned char) 1; + } + else if( num_buttons == 2 ) + { + if (handed == RIGHT_HANDED) + { + map[0] = (unsigned char) 1; + map[1] = (unsigned char) 3; + } + else + { + map[0] = (unsigned char) 3; + map[1] = (unsigned char) 1; + } + } + else // 3 buttons and more + { + if (handed == RIGHT_HANDED) + { + map[0] = (unsigned char) 1; + map[1] = (unsigned char) middle_button; + map[2] = (unsigned char) 3; + } + else + { + map[0] = (unsigned char) 3; + map[1] = (unsigned char) middle_button; + map[2] = (unsigned char) 1; + } + if( num_buttons >= 5 ) + { + // Apps seem to expect logical buttons 4,5 are the vertical wheel. + // With mice with more than 3 buttons (not including wheel) the physical + // buttons mapped to logical 4,5 may not be physical 4,5 , so keep + // this mapping, only possibly reversing them. + int pos; + for( pos = 0; pos < num_buttons; ++pos ) + if( map[pos] == 4 || map[pos] == 5 ) + break; + if( pos < num_buttons - 1 ) + { + map[pos] = reverseScrollPolarity ? (unsigned char) 5 : (unsigned char) 4; + map[pos+1] = reverseScrollPolarity ? (unsigned char) 4 : (unsigned char) 5; + } + } + } + int retval; + if (remap) + while ((retval=XSetPointerMapping(QX11Info::display(), map, + num_buttons)) == MappingBusy) + /* keep trying until the pointer is free */ + { }; + m_handedNeedsApply = false; + } + + // This iterates through the various Logitech mice, if we have support. + #ifdef HAVE_LIBUSB + LogitechMouse *logitechMouse; + Q_FOREACH( logitechMouse, logitechMouseList ) { + logitechMouse->applyChanges(); + } + #endif +} + +void MouseSettings::save(KConfig *config) +{ + KConfigGroup group = config->group("Mouse"); + group.writeEntry("Acceleration",accelRate); + group.writeEntry("Threshold",thresholdMove); + if (handed == RIGHT_HANDED) + group.writeEntry("MouseButtonMapping",QString("RightHanded")); + else + group.writeEntry("MouseButtonMapping",QString("LeftHanded")); + group.writeEntry( "ReverseScrollPolarity", reverseScrollPolarity ); + + group = config->group("KDE"); + group.writeEntry("DoubleClickInterval", doubleClickInterval, KConfig::Persistent|KConfig::Global); + group.writeEntry("StartDragTime", dragStartTime, KConfig::Persistent|KConfig::Global); + group.writeEntry("StartDragDist", dragStartDist, KConfig::Persistent|KConfig::Global); + group.writeEntry("WheelScrollLines", wheelScrollLines, KConfig::Persistent|KConfig::Global); + group.writeEntry("SingleClick", singleClick, KConfig::Persistent|KConfig::Global); + group.writeEntry("AutoSelectDelay", autoSelectDelay, KConfig::Persistent|KConfig::Global); + group.writeEntry("ChangeCursor", changeCursor,KConfig::Persistent|KConfig::Global); + // This iterates through the various Logitech mice, if we have support. +#ifdef HAVE_LIBUSB + LogitechMouse *logitechMouse; + Q_FOREACH( logitechMouse, logitechMouseList ) { + logitechMouse->save(config); + } +#endif + config->sync(); + KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_MOUSE); +} + +void MouseConfig::slotScrollPolarityChanged() +{ + settings->m_handedNeedsApply = true; +} + +void MouseConfig::slotSmartSliderEnabling() +{ + bool enabled = generalTab->singleClick->isChecked() ? generalTab->cbAutoSelect->isChecked() : false; + generalTab->slAutoSelect->setEnabled(enabled); +} + +#include "mouse.moc" diff --git a/kcms/input/mouse.desktop b/kcms/input/mouse.desktop new file mode 100644 index 0000000000..a3ca207411 --- /dev/null +++ b/kcms/input/mouse.desktop @@ -0,0 +1,240 @@ +[Desktop Entry] +Exec=kcmshell5 mouse +Icon=preferences-desktop-mouse +Type=Service +X-KDE-ServiceTypes=KCModule,KCModuleInit +X-DocPath=kcontrol/mouse/index.html + +X-KDE-Library=kcm_input +X-KDE-Init-Symbol=mouse +X-KDE-ParentApp=kcontrol +X-KDE-OnlyShowOnQtPlatforms=xcb; + +X-KDE-System-Settings-Parent-Category=input-devices +X-KDE-Weight=60 + +Name=Mouse +Name[af]=Muis +Name[ar]=الفأرة +Name[ast]=Mur +Name[be]=Мыш +Name[be@latin]=Myš +Name[bg]=Мишка +Name[bn]=মাউস +Name[bn_IN]=মাউস +Name[br]=Logodenn +Name[bs]=Miš +Name[ca]=Ratolí +Name[ca@valencia]=Ratolí +Name[cs]=Myš +Name[csb]=Mësz +Name[cy]=Llygoden +Name[da]=Mus +Name[de]=Maus +Name[el]=Ποντίκι +Name[en_GB]=Mouse +Name[eo]=Muso +Name[es]=Ratón +Name[et]=Hiir +Name[eu]=Sagua +Name[fa]=موشی +Name[fi]=Hiiri +Name[fr]=Souris +Name[fy]=Mûs +Name[ga]=Luch +Name[gl]=Rato +Name[gu]=માઉસ +Name[he]=עכבר +Name[hi]=माउस +Name[hne]=मुसुवा +Name[hr]=Miš +Name[hsb]=Myš +Name[hu]=Egér +Name[ia]=Mus +Name[id]=Tetikus +Name[is]=Mús +Name[it]=Mouse +Name[ja]=マウス +Name[ka]=თაგვი +Name[kk]=Тышқан +Name[km]=កណ្ដុរ +Name[kn]=ಮೂಷಕ (ಮೌಸ್) +Name[ko]=마우스 +Name[ku]=Mişk +Name[lt]=Pelė +Name[lv]=Pele +Name[mai]=माउस +Name[mk]=Глушец +Name[ml]=മൌസ് +Name[mr]=माऊस +Name[ms]=Tetikus +Name[nb]=Mus +Name[nds]=Muus +Name[ne]=माउस +Name[nl]=Muis +Name[nn]=Mus +Name[oc]=Mirga +Name[or]=ମାଉସ +Name[pa]=ਮਾਊਸ +Name[pl]=Mysz +Name[pt]=Rato +Name[pt_BR]=Mouse +Name[ro]=Maus +Name[ru]=Мышь +Name[se]=Sáhpán +Name[si]=මවුසය +Name[sk]=Myš +Name[sl]=Miška +Name[sr]=Миш +Name[sr@ijekavian]=Миш +Name[sr@ijekavianlatin]=Miš +Name[sr@latin]=Miš +Name[sv]=Mus +Name[ta]=சுட்டி +Name[te]=మౌస్ +Name[tg]=Муш +Name[th]=เมาส์ +Name[tr]=Fare +Name[ug]=چاشقىنەك +Name[uk]=Мишка +Name[uz]=Sichqoncha +Name[uz@cyrillic]=Сичқонча +Name[vi]=Chuột +Name[wa]=Sori +Name[xh]=Mouse +Name[x-test]=xxMousexx +Name[zh_CN]=鼠标 +Name[zh_TW]=滑鼠 + +Comment=Mouse settings +Comment[af]=Muis instellings +Comment[ar]=إعدادات الفأرة +Comment[ast]=Preferencies sobre'l mur +Comment[be]=Настаўленні мышы +Comment[be@latin]=Nałady myšy +Comment[bg]=Настройки на мишка +Comment[bn]=মাউস সেটিংস +Comment[bn_IN]=মাউস সংক্রান্ত বৈশিষ্ট্য +Comment[br]=Kefluniañ al logodenn +Comment[bs]=Postavke miša +Comment[ca]=Arranjament del ratolí +Comment[ca@valencia]=Arranjament del ratolí +Comment[cs]=Nastavení myši +Comment[csb]=Nastôw mëszë +Comment[cy]=Gosodiadau Llygoden +Comment[da]=Indstilling af mus +Comment[de]=Einstellung der Maus +Comment[el]=Ρυθμίσεις Ποντικιού +Comment[en_GB]=Mouse settings +Comment[eo]=Agordo de la muso +Comment[es]=Preferencias sobre el ratón +Comment[et]=Hiire seadistused +Comment[eu]=Saguaren ezarpenak +Comment[fa]=تنظیمات موشی +Comment[fi]=Hiiren asetukset +Comment[fr]=Configuration de la souris +Comment[fy]=Mûsynstellings +Comment[ga]=Socruithe luiche +Comment[gl]=Configuración do rato +Comment[gu]=માઉસ ગોઠવણીઓ +Comment[he]=הגדרות העכבר +Comment[hi]=माउस विन्यास +Comment[hne]=मुसुवा सेटिंग +Comment[hr]=Postavke miša +Comment[hsb]=Nastajenja za myš +Comment[hu]=Az egér beállításai +Comment[ia]=Preferentias de mus +Comment[id]=Pengaturan tetikus +Comment[is]=Stillingar músar +Comment[it]=Impostazione del mouse +Comment[ja]=マウスの設定 +Comment[ka]=თაგვის კონფიგურაცია +Comment[kk]=Тышқан параметрлері +Comment[km]=ការ​កំណត់​កណ្ដុរ +Comment[kn]=ಮೂಷಕದ (ಮೌಸ್) ಸಂಯೋಜನೆಗಳು +Comment[ko]=마우스 설정 +Comment[ku]=Mîhengên Mişkî +Comment[lt]=Pelės parametrai +Comment[lv]=Peles parametri +Comment[mai]=माउस बिन्यास +Comment[mk]=Поставувања на глушецот +Comment[ml]=മൌസിന്റെ സജ്ജീകരണങ്ങള്‍ +Comment[mr]=माऊस संयोजना +Comment[ms]=Seting tetikus +Comment[nb]=Musinnstillinger +Comment[nds]=Muus instellen +Comment[ne]=माउस सेटिङ +Comment[nl]=Muisinstellingen +Comment[nn]=Musinnstillingar +Comment[or]=ମାଉସ ବିନ୍ୟାସ +Comment[pa]=ਮਾਊਸ ਸੈਟਿੰਗ +Comment[pl]=Ustawienia myszy +Comment[pt]=Configuração do rato +Comment[pt_BR]=Configurações do mouse +Comment[ro]=Configurări maus +Comment[ru]=Настройка мыши +Comment[se]=Sáhpánheivehusat +Comment[si]=මවුසයේ සැකසුම් +Comment[sk]=Nastavenie myši +Comment[sl]=Nastavitve miške +Comment[sr]=Поставке миша +Comment[sr@ijekavian]=Поставке миша +Comment[sr@ijekavianlatin]=Postavke miša +Comment[sr@latin]=Postavke miša +Comment[sv]=Anpassa mus +Comment[ta]=சுட்டி அமைப்புகள் +Comment[te]=మౌస్ అమరికలు +Comment[tg]=Танзимоти муш +Comment[th]=ตั้งค่าต่างๆ ของเมาส์ +Comment[tr]=Fare ayarları +Comment[ug]=چاشقىنەك تەڭشەك +Comment[uk]=Налаштування миші +Comment[uz]=Sichqonchaning moslamalari +Comment[uz@cyrillic]=Сичқончанинг мосламалари +Comment[vi]=Thiết lập con chuột +Comment[wa]=Apontiaedjes del sori +Comment[xh]=Izicwangciso ze mouse +Comment[x-test]=xxMouse settingsxx +Comment[zh_CN]=鼠标设置 +Comment[zh_TW]=滑鼠設定 + +X-KDE-Keywords=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation +X-KDE-Keywords[bs]=Miš, Brzina kretanja miša, Prag osjetljivosti miša, Tasteri miša, Oblik kursora, Ulazni Uređaji, Mapiranje tastera, Klik, Ikone, feedback (povratna veza), Pokazivači, Vuči (drag), Dupli klik, Jedan Klik, Mapiranje, Dešnjak, Ljevak, Uređaj koji je Pokazivač (miš, Trackball, Joystick), Točkić za pomicanje (gore ili dolje), Emulatija Miša, Navigacija Miša, Miš Povucite i ispustite(drag and drop), Skrolanje Mišem, Osjetljivost Miša, Pomjeranje miša pomoću brojevne tastature, Emulacija miša pomoću brojevne tastature +X-KDE-Keywords[ca]=Ratolí,Acceleració de ratolí,Llindar de ratolí,Botons de ratolí,Selecció,Ombra de cursor,Dispositius d'entrada,Mapatge de boton,Clic,icones,reacció,Apuntadors,Arrossegar,Clic doble,Clic normal,mapatge,dretà,esquerrà,Dispositiu apuntador,Roda de ratolí,Emulació de ratolí,Navegació amb ratolí,Arrossegar i deixar anar de ratolí,Desplaçament amb ratolí,Sensitivitat de ratolí,Moure el ratolí amb teclat numèric,Emulació de ratolí amb teclat numèric +X-KDE-Keywords[ca@valencia]=Ratolí,Acceleració de ratolí,Llindar de ratolí,Botons de ratolí,Selecció,Ombra de cursor,Dispositius d'entrada,Mapatge de boton,Clic,icones,reacció,Apuntadors,Arrossegar,Clic doble,Clic normal,mapatge,dretà,esquerrà,Dispositiu apuntador,Roda de ratolí,Emulació de ratolí,Navegació amb ratolí,Arrossegar i deixar anar de ratolí,Desplaçament amb ratolí,Sensitivitat de ratolí,Moure el ratolí amb teclat numèric,Emulació de ratolí amb teclat numèric +X-KDE-Keywords[da]=Mus,Museacceleration,musetærskel,museknapper,markering,markørform,Input-enheder,knapkobling,klik,ikoner,feedback,Pointers,træk,dobbeltklik,enkeltklik,kobling,højrehåndet,venstrehåndet,pegeenhed,musehjul,museemulering,musenavigation,træk og slip,muserulning,scrolling,musefølsomhed,bevæg mus med numerisk tastatur,markører,cursor,rulning +X-KDE-Keywords[de]=Maus,Mausbeschleunigung,Mausschwellwert,Maustasten,Auswahl,Cursor,Cursor-Form,Eingabegeräte,Knöpfe,Buttons,Zuordnungen,Klicks,Zeigegeräte,Doppelklick,Rechtshänder,Linkshänder,Ziehen,Mausrad,Maus-Emulation,Maus-Navigation,Ziehen und Ablegen mit der Maus,Blättern mit der Maus,Maus-Empfindlichkeit,Mauszeiger mit der Zahlentastatur verschieben,Maus-Emulation mit der Zahlentastatur +X-KDE-Keywords[el]=ποντίκι,επιτάχυνση ποντικιού,κατώφλι ποντικιού,κουμπιά ποντικιού,επιλογή,σχήμα δρομέα,συσκευές εισόδου,χαρτογράφηση κουμπιών,κλικ,εικονίδια,ανάδραση,δείκτες,έλξη,διπλό κλικ,μονό κλικ,χαρτογράφηση,δεξιόχειρας,αριστερόχειρας,συσκευή δείκτη,τροχός ποντικιού,εξομοίωση ποντικιού,πλοήγηση ποντικιού,έλξη και απόθεση ποντικιού,κύλιση ποντικιού,ευαισθησία ποντικιού,κίνηση ποντικιού με το αριθμητικό πληκτρολόγιο,εξομοίωση ποντικιού αριθμητικού πληκτρολογίου +X-KDE-Keywords[es]=Ratón,Aceleración de ratón,Umbral del ratón,Botones del ratón,Selección,Forma del cursor,Dispositivos de entrada,Mapeo de botones,Clic,iconos,reacción,Punteros,Arrastrar,Doble clic,clic sencillo,mapeo,diestro,zurdo,Dispositivo apuntador,Rueda del ratón,Emulación del ratón,Navegación con el ratón,Arrastrar y soltar con el ratón,Desplazamiento con el ratón,Sensibilidad del ratón,Mover el ratón con el teclado numérico,Emulación del ratón con el teclado numérico +X-KDE-Keywords[et]=hiir,hiire kiirendamine,hiire lävi,hiirenupud,valik,kursori kuju,sisendseadmed,nuppude seostamine,klõps,klõpsamine,ikoonid,tagasiside,lohistamine,topeltklõps,ühekordne klõps,seostamine,paremakäelised,vasakukäelised,osutusseade,hiireratas,hiire emuleerimine,hiirega liikumine,hiirega lohistamine,hiirega kerimine,hiire tundlikkus,hiire liigutamine numbriklahvistikuga,hiire numbriklahvistiku emuleerimine +X-KDE-Keywords[eu]=sagu,saguaren azelerazio,saguaren atalase,saguaren botoiak,hautapena,kurtsorearen forma,sarrerako gailuak,botoiak mapatzea,klik,ikonoak,oharrak,erakusle,arrastatu,klik bikoitza,klik bakarra,mapatze,eskuina,ezkerra,erakuslearen gailu,saguaren gurpil,saguaren emulazio,sagu bidezko nabigazio,saguaren bidez arrastatu eta jaregin,saguaren bidez korritu,saguaren sentikortasuna,sagua zenbakizko teklatuarekin mugitzea,sagua emulatzea zenbakizko teklatuarekin +X-KDE-Keywords[fi]=Hiiri,Osoittimen kiihdytys,Osoittimen raja-arvo,Hiiripainikkeet,Valinta,Osoittimen muoto,Syöttölaitteet,Syötelaitteet,Painikkeiden kuvaus,Napsauta,Napsautus,kuvakkeet,tuntuma,Osoittimet,Raahaus,Kaksoisnapsautus,kuvaus,oikeakätinen,oikeakätisyys,vasenkätinen,vasenkätisyys,osoitinlaite,hiiren rulla,hiiren emulointi,hiirinavigointi,hiiren vedä ja pudota,hiiren vieritys,hiiren herkkyys,hiiren liikuttaminen numeronäppäimistöltä +X-KDE-Keywords[fr]=Souris, Accélération de la souris, Seuil de la souris, Boutons de la souris, Sélection, Forme du curseur, Périphériques d'entrée, affectation des boutons, Clic, icônes, réaction, Pointeurs, Glisser, Double clic, Simple clic, affectation, droitier, gaucher, Périphérique de pointage, Roulette de la souris, Émulation de la souris, Navigation de la souris, Glisser-déposer, Défilement de la souris, Sensibilité de la souris, Déplacement de la souris avec le pavé numérique, Émulation de la souris du pavé numérique +X-KDE-Keywords[gl]=rato, aceleración do rato, limiar do rato, botóns do rato, selección, escolla, forma do rato, dispositivos de entrada, mapas de botóns, premer, clic, iconas, punteiro, arrastrar, duplo clic, dobre clic, dereito, zurdo, dispositivo do punteiro, roda do rato, emulación do rato, navegación co rato, arrastrar e soltar co rato, sensibilidade do rato, mover o rato co teclado numérico, teclado numérico +X-KDE-Keywords[hu]=Egér,Egérgyorsítás,Egérküszöb,Egérgombok,Kijelölés,Kurzorforma,Beviteli eszközök,Gombhozzárendelés,Kattintás,ikonok,visszajelzés,Mutatók,Fogás,Dupla kattintás,Egyszeres kattintás,leképezés,jobb kezes,bal kezes,Mutató eszköz,Egérgörgő,Egéremuláció,Egérnavigáció,Egér fogd és vidd,Egérgörgetés,Egér érzékenység,Egér mozgatása numerikus billentyűkkel,Egér numerikus billentyűzet emuláció +X-KDE-Keywords[ia]=Mus,Acceleration de mus,Limine de mus,Buttones de mus,Selection,Forma de cursor, Dispositivos de ingresso,Mappatura de button,Click,icones,retro-information,Punctatores,Trahe,DupleClick,Singule click,mappar,con mano dextere, con mano sinistre,Dispositivo punctator,Rota de Mus,Emulation de mus,Navigation de mus,Traher e Poner con Mus, Rolar con Mus,Sensibilitate de mus, Move Mus con NumPad,Emulation Mus con NumPad +X-KDE-Keywords[it]=mouse,accelerazione del mouse,soglia del mouse,pulsanti del mouse,selezione,forma del cursore,dispositivi di ingresso,mappatura dei pulsanti,clic,icone,segnale di avvio,puntatori,trascinamento,doppio clic,singolo clic,mappatura,destrorso,mancino,dispositivo di puntamento,rotellina del mouse,emulazione del mouse,navigazione con il mouse, trascinamento con il mouse, scorrimento con il mouse, sensibilità del mouse,muovi il mouse con il tastierino numerico,emulazione mouse con il tastierino numerico +X-KDE-Keywords[kk]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation +X-KDE-Keywords[km]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation +X-KDE-Keywords[ko]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,마우스,마우스 가속,시간,커서 모양,입력 장치,클릭,드래그,왼손잡이,오른손잡이,마우스 휠,마우스 탐색, 마우스 스크롤,감도,스크롤,휠 +X-KDE-Keywords[mr]=माऊस, माऊस एक्सलरेशन, माऊस थ्रेशहोल्ड, माऊस बटन्स, सिलेक्शन, कर्सर शेप, इनपुट डिव्हाईस, बटन मेपिंग, क्लिक, आयकॉनस, फीडबेक, पॉईटर, ड्रग डबल, क्लिक, सिंगल क्लिक, मेपिंग, राईट हेन्डेड ,पॉईटर डिव्हाईस,माऊस, व्हील, माऊस इम्यूलेशन, माऊस,नेव्हीगेशन, माऊस ड्रेग व ड्रोप,न्यूम पॅड, माऊस न्यूम पॅड इम्यूलेशन +X-KDE-Keywords[nb]=Mus,Pekerakselerasjon,Pekerterskel,knapper,valg,pekerform,Inndataenheter,knappeavbildning,Klikk, ikoner,oppstartsmelding,Pekere,Dra,Dobbeltklikk,Enkeltklikk,Knapperekkefølge,høyrehendt,venstrehendt,Pekerenhet,Musehjul,Musemulering,Musenavigasjon,Dra og slipp med Mus, Muserulling,Flytt mus med talltastatur,Museemulering med talltastatur +X-KDE-Keywords[nds]=Muus,Muusbeslünigen,Wieser-Süll,Muusgauheit,Muusknööp,Köör,Blinkerform,Ingaavreedschappen,Knoop-Toornen,Klick,Lüttbiller,Rückmellen,Wiesers,Dregen,Dubbelklick,Towiesen,Rechtepoot,Linkepoot,Wiesreedschap,Muusrad,Muusemuleren,Muusstüern,Dregen un Droppen,Trecken,Afsetten,Fallenlaten,Rullen,Föhlsamkeit,Tallenblock +X-KDE-Keywords[nl]=muis,muisversnelling,muisdrempel,muisknoppen,selectie,cursorvorm,invoerapparaten,knoppenmapping,klik,pictogrammen,terugkoppeling,aanwijzer,slepen,dubbelklik,klik,mapping,rechtshandig,linkshandig,aanwijsapparaat,muiswiel,muisemulatie,muisnavigatie,slepen en laten vallen met muis,schuiven met de muis,muisgevoeligheid,muis bewegen met num-pad,emulatie van num-pad met muis +X-KDE-Keywords[pl]=Mysz,Przyspieszenie myszy,Próg myszy,Przyciski myszy,Zaznaczenie, Kształt kursora,Urządzenia wejścia,Mapowanie przycisków,Kliknięcie,ikony,odczucie,Wskaźniki,Przeciągnięcie,Podwójne kliknięcie,mapowanie,praworęczny,leworęczny, Urządzenie wskazujące,Rolka myszy,Emulacja myszy,Nawigacja myszą,Przeciąganie i upuszczanie myszą,Przewijanie myszą,Czułość myszy,Przemieszczaj myszą przy użyciu klawiatury numerycznej,Emulacja myszy klawiaturą numeryczną +X-KDE-Keywords[pt]=Rato,aceleração do rato,limiar do rato,botões do rato,selecção,forma do cursor,dispositivos de entrada,associação de botões,click,ícones,reacção,cursores,arrastar,duplo-click,associação,destro,esquerdino,ponteiro,roda do rato,emulação do rato,navegação do rato,arrastamento com o rato,deslocamento do rato,sensibilidade do rato,mover o rato com cursores,emulação do rato com teclado numérico +X-KDE-Keywords[pt_BR]=Mouse,aceleração do mouse,limiar do mouse,botões do mouse,seleção,forma do cursor,dispositivos de entrada,associação de botões,clique,ícones,feedback,ponteiros,arrastar,clique duplo,clique simples,associação,destro,canhoto, ponteiro,roda do mouse,emulação do mouse,navegação do mouse,arrastar e soltar com o mouse,deslocamento do mouse,sensibilidade do mouse,mover o mouse com o teclado numérico,emulação do mouse com o teclado numérico +X-KDE-Keywords[ru]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,мышь,ускорение мыши,границы мыши,кнопки мыши,выбор,форма курсора,устройство ввода,назначение клавиш,клик,значки,обратная связь,указатели,перемещение,двойной клик,двойной щелчок,одиночный клик,одиночный щелчок,правая рука,левая рука,праворукая,леворукая,колесо мыши,эмуляция мыши,управление мышью, навигация мыши,прокрутка,чувствительность,управление мышью через цифровую клавиатуру +X-KDE-Keywords[sk]=Myš,Zrýchlenie myši,Prah myši,Tlačidlá myši,Výber,Tvar kurzora,Vstupné zariadenia,Mapovanie tlačidiel,Klik,ikony,odozva,Ukazovatele,Drag,Dvojklik,Jednoduchý klik,mapovanie,pre pravákov,pre ľavákov,ukazovacie zariadenie,koliesko myši,emulácia myši,navigácia myši,drag and drop myši,rolovanie myši,citlivosť myši,pohyb myši numerickou klávesnicou,emulácia myši numerickou klávesnicou +X-KDE-Keywords[sl]=miška,pospešek miške,prag miške,gumbi miške,miškini gumbi,izbor,oblika kazalca,oblika kazalke,vhodne naprave,preslikava gumbov,klik,ikone,povratne informacije,odziv,kazalci,kazalke,vleka,dvojni klik,dvoklik,enojni klik,preslikava,desničar,levičar,kazalna naprava,kolešček miške,miškin kolešček,posnemanje miške,krmarjenje z miško,vleka in spuščanje z miško,pomikanje z miško,občutljivost miške,miškina občutljivost,premikanje miške s številčnico,posnemanje s številčnico +X-KDE-Keywords[sr]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,миш,убрзање миша,праг миша,дугмад миша,избор,облик показивача,облик курсора,улазни уређаји,мапирање дугмади,клик,иконе,одзив,превлачење,двоклик,десноруки,леворуки,показивачки уређај,точкић миша,осетљивост миша,кретање мишем,емулација миша,емулација миша преко нумеричке тастатуре +X-KDE-Keywords[sr@ijekavian]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,миш,убрзање миша,праг миша,дугмад миша,избор,облик показивача,облик курсора,улазни уређаји,мапирање дугмади,клик,иконе,одзив,превлачење,двоклик,десноруки,леворуки,показивачки уређај,точкић миша,осетљивост миша,кретање мишем,емулација миша,емулација миша преко нумеричке тастатуре +X-KDE-Keywords[sr@ijekavianlatin]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,miš,ubrzanje miša,prag miša,dugmad miša,izbor,oblik pokazivača,oblik kursora,ulazni uređaji,mapiranje dugmadi,klik,ikone,odziv,prevlačenje,dvoklik,desnoruki,levoruki,pokazivački uređaj,točkić miša,osetljivost miša,kretanje mišem,emulacija miša,emulacija miša preko numeričke tastature +X-KDE-Keywords[sr@latin]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,miš,ubrzanje miša,prag miša,dugmad miša,izbor,oblik pokazivača,oblik kursora,ulazni uređaji,mapiranje dugmadi,klik,ikone,odziv,prevlačenje,dvoklik,desnoruki,levoruki,pokazivački uređaj,točkić miša,osetljivost miša,kretanje mišem,emulacija miša,emulacija miša preko numeričke tastature +X-KDE-Keywords[sv]=Mus,Musacceleration,Muströskel,Musknappar,Val,Pekarform,Indataenheter,Knappavbildning,Klick,ikoner,återmatning,Pekare,Dra,Dubbelklick,avbildning,högerhänt,vänsterhänt,pekarenhet,mushjul,musemulering,musnavigering,mus drag och släpp,musrullning,muskänslighet,flytta musen med numeriskt tangentbord,emulering av mus med numeriskt tangentbord +X-KDE-Keywords[tr]=Fare,Fare Hızlandırma,Fare Eşiği,Fare Düğmeleri,Seçim,İşaretçi Şekli,Girdi Aygıtları,Düğme Haritalama,Tıklama,simgeler,geri bildirim,İşaretçiler,Sürükle,Çift Tıklama,Tek Tıklama,haritalama,sağlak,solak,İşaretçi Aygıtı,Fare Tekeri,Fare Benzetimi,Fare Gezinmesi,Fare Sürükle Bırak,Fare Kaydırması,Fare Hassasiyeti,Fareyi Sayısal Tuşlarla Hareket Ettir,Fare Sayısal Tuş Benzetimi +X-KDE-Keywords[uk]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,DoubleClick,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,миша,прискорення,поріг,порогове значення,кнопка,вибір,вказівник,форма,введення,кнопки,клацання,піктограми,значки,іконки,супровід,вказівники,перетягування,подвійне клацання,відповідність,праворукий,шульга,лівша,пристрій вказівника,коліщатко миші,емуляція миші,імітація миші,навігація за допомогою миші,перетягування зі скиданням мишею,гортання мишею,чутливість миші,миша з цифровою панеллю,емуляція цифрової панелі миші +X-KDE-Keywords[x-test]=xxMouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulationxx +X-KDE-Keywords[zh_CN]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation,鼠标,鼠标加速,鼠标阀值,鼠标按键,选择,光标形状,输入设备,按键映射,点击,图标,反馈,指针,拖拽,双击,映射,右手习惯,左手习惯,光标设备,指针设备,鼠标滚轮,鼠标模拟,鼠标导航,鼠标拖拽,鼠标滚动,鼠标灵敏度,小键盘移动鼠标,小键盘鼠标模拟 +X-KDE-Keywords[zh_TW]=Mouse,Mouse acceleration,Mouse threshold,Mouse buttons,Selection,Cursor Shape,Input Devices,Button Mapping,Click,icons,feedback,Pointers,Drag,Double Click,Single Click,mapping,right handed,left handed,Pointer Device,Mouse Wheel,Mouse Emulation,Mouse Navigation,Mouse Drag and Drop,Mouse Scrolling,Mouse Sensitivity,Move Mouse with Num Pad,Mouse Num Pad Emulation +Categories=Qt;KDE;X-KDE-settings-hardware; diff --git a/kcms/input/mouse.h b/kcms/input/mouse.h new file mode 100644 index 0000000000..58d92012e2 --- /dev/null +++ b/kcms/input/mouse.h @@ -0,0 +1,160 @@ +/* + * mouse.h + * + * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca + * + * Layout management, enhancements: + * Copyright (c) 1999 Dirk A. Mueller + * + * SC/DC/AutoSelect/ChangeCursor: + * Copyright (c) 2000 David Faure + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __MOUSECONFIG_H__ +#define __MOUSECONFIG_H__ + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#ifdef HAVE_LIBUSB +#include "logitechmouse.h" +#endif + +#include +#include "ui_kmousedlg.h" + +#define RIGHT_HANDED 0 +#define LEFT_HANDED 1 + +class QCheckBox; +class QSlider; +class QTabWidget; + +class KMouseDlg : public QWidget, public Ui::KMouseDlg +{ +public: + KMouseDlg( QWidget *parent ) : QWidget( parent ) { + setupUi( this ); + } +}; + + +class MouseSettings +{ +public: + void save(KConfig *); + void load(KConfig *); + void apply(bool force=false); +public: + int num_buttons; + int middle_button; + bool handedEnabled; + bool m_handedNeedsApply; + int handed; + double accelRate; + int thresholdMove; + int doubleClickInterval; + int dragStartTime; + int dragStartDist; + bool singleClick; + int autoSelectDelay; + bool changeCursor; + int wheelScrollLines; + bool reverseScrollPolarity; + + #ifdef HAVE_LIBUSB + // TODO: In Qt4, replace with a better container. + QList logitechMouseList; + #endif +}; + +class MouseConfig : public KCModule +{ + Q_OBJECT +public: + MouseConfig(QWidget *parent, const QVariantList &args); + ~MouseConfig(); + + void save(); + void load(); + void defaults(); + +private Q_SLOTS: + + void slotClick(); + /** No descriptions */ + void slotHandedChanged(int val); + void slotScrollPolarityChanged(); + void checkAccess(); + void slotThreshChanged(int value); + void slotDragStartDistChanged(int value); + void slotWheelScrollLinesChanged(int value); + void slotSmartSliderEnabling(); + +private: + + double getAccel(); + int getThreshold(); + int getHandedness(); + + void setAccel(double); + void setThreshold(int); + void setHandedness(int); + + KDoubleNumInput *accel; + KIntNumInput *thresh; + KIntNumInput *doubleClickInterval; + KIntNumInput *dragStartTime; + KIntNumInput *dragStartDist; + KIntNumInput *wheelScrollLines; + +// QRadioButton *leftHanded, *rightHanded; +// QCheckBox *doubleClick; +// QCheckBox *cbAutoSelect; + QLabel *lDelay; +// QSlider *slAutoSelect; +// QCheckBox *cbVisualActivate; +// QCheckBox *cbCursor; +// QCheckBox *cbLargeCursor; + + QTabWidget *tabwidget; + QWidget *advancedTab; + KMouseDlg* generalTab; + MouseSettings *settings; + + QCheckBox *mouseKeys; + KIntNumInput *mk_delay, *mk_interval, *mk_time_to_max, *mk_max_speed, + *mk_curve; + + +}; + +#endif + diff --git a/kcms/input/pics/CMakeLists.txt b/kcms/input/pics/CMakeLists.txt new file mode 100644 index 0000000000..4ef49ea13b --- /dev/null +++ b/kcms/input/pics/CMakeLists.txt @@ -0,0 +1 @@ +install( FILES mouse_rh.png mouse_lh.png DESTINATION ${DATA_INSTALL_DIR}/kcminput/pics ) diff --git a/kcms/input/pics/mouse_lh.png b/kcms/input/pics/mouse_lh.png new file mode 100644 index 0000000000000000000000000000000000000000..796d5994252bad45f8f076f1cb1e3621efd9cc4f GIT binary patch literal 10704 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 literal 0 HcmV?d00001 diff --git a/kcms/input/pics/mouse_rh.svgz b/kcms/input/pics/mouse_rh.svgz new file mode 100644 index 0000000000000000000000000000000000000000..fc2b069a8d842c03af188c03d808f3dfb621ce93 GIT binary patch literal 4528 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 O;QtM-4PW0)MgRa0Bl0l- literal 0 HcmV?d00001 diff --git a/kcms/input/xcursor/cursortheme.cpp b/kcms/input/xcursor/cursortheme.cpp new file mode 100644 index 0000000000..1ea66886a9 --- /dev/null +++ b/kcms/input/xcursor/cursortheme.cpp @@ -0,0 +1,155 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include + +#include "themepage.h" +#include "cursortheme.h" + +#include + +#ifdef HAVE_XFIXES +# include +# include +#endif + + +CursorTheme::CursorTheme(const QString &title, const QString &description) +{ + setTitle(title); + setDescription(description); + setSample("left_ptr"); + setIsHidden(false); + setIsWritable(false); +} + + +QPixmap CursorTheme::icon() const +{ + if (m_icon.isNull()) + m_icon = createIcon(); + + return m_icon; +} + + +QImage CursorTheme::autoCropImage(const QImage &image) const +{ + // Compute an autocrop rectangle for the image + QRect r(image.rect().bottomRight(), image.rect().topLeft()); + const quint32 *pixels = reinterpret_cast(image.bits()); + + for (int y = 0; y < image.height(); y++) + { + for (int x = 0; x < image.width(); x++) + { + if (*(pixels++)) + { + if (x < r.left()) r.setLeft(x); + if (x > r.right()) r.setRight(x); + if (y < r.top()) r.setTop(y); + if (y > r.bottom()) r.setBottom(y); + } + } + } + + // Normalize the rectangle + return image.copy(r.normalized()); +} + + +QPixmap CursorTheme::loadPixmap(const QString &name, int size) const +{ + QImage image = loadImage(name, size); + if (image.isNull()) + return QPixmap(); + + return QPixmap::fromImage(image); +} + + +static int nominalCursorSize(int iconSize) +{ + for (int i = 512; i > 8; i /= 2) + { + if (i < iconSize) + return i; + + if ((i * .75) < iconSize) + return int(i * .75); + } + + return 8; +} + + +QPixmap CursorTheme::createIcon() const +{ + int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize); + int cursorSize = nominalCursorSize(iconSize); + QSize size = QSize(iconSize, iconSize); + + QPixmap pixmap = createIcon(cursorSize); + + if (!pixmap.isNull()) + { + // Scale the pixmap if it's larger than the preferred icon size + if (pixmap.width() > size.width() || pixmap.height() > size.height()) + pixmap = pixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + + return pixmap; +} + + +QPixmap CursorTheme::createIcon(int size) const +{ + QPixmap pixmap; + QImage image = loadImage(sample(), size); + + if (image.isNull() && sample() != "left_ptr") + image = loadImage("left_ptr", size); + + if (!image.isNull()) + { + pixmap = QPixmap::fromImage(image); + } + + return pixmap; +} + + +void CursorTheme::setCursorName(qulonglong cursor, const QString &name) const +{ +#ifdef HAVE_XFIXES + static bool haveXfixes = ThemePage::haveXfixes(); + + if (haveXfixes) + { + XFixesSetCursorName(QX11Info::display(), cursor, + QFile::encodeName(name)); + } +#endif +} + diff --git a/kcms/input/xcursor/cursortheme.h b/kcms/input/xcursor/cursortheme.h new file mode 100644 index 0000000000..d280005f4c --- /dev/null +++ b/kcms/input/xcursor/cursortheme.h @@ -0,0 +1,143 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 CURSORTHEME_H +#define CURSORTHEME_H + +#include +#include + +/** + * This is the abstract base class for all cursor themes stored in a + * CursorThemeModel and previewed in a PreviewWidget. + * + * All cursor themes have a title, a description, an icon, and an internal + * name, all of which, except for the internal name, CursorThemeModel + * supplies to item views. + * + * A cursor theme may also have a path to the directory where the theme + * is located in the filesystem. If isWritable() returns true, This directory + * may be deleted in order to remove the theme at the users request. + * + * Subclasses must reimplement loadImage() and loadCursor(), which are + * called by PreviewWidget to load cursors and cursor images. Subclasses may + * optionally reimplement loadPixmap(), which in the default implementation + * calls loadImage(), and converts the returned image to a pixmap. + * Subclasses may also reimplement the protected function createIcon(), + * which creates the icon pixmap that's supplied to item views. The default + * implementation calls loadImage() to load the sample cursor, and creates + * the icon from that. + */ +class CursorTheme +{ + public: + enum ItemDataRole { + // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM)) + // to define additional roles. + DisplayDetailRole = 0x24A3DAF8 + }; + + CursorTheme() {} + CursorTheme(const QString &title, const QString &description = QString()); + virtual ~CursorTheme() {} + + const QString title() const { return m_title; } + const QString description() const { return m_description; } + const QString sample() const { return m_sample; } + const QString name() const { return m_name; } + const QString path() const { return m_path; } + /** @returns A list of the available sizes in this cursor theme, + @warning This list may be empty if the engine doesn't support + the recognition of the size. */ + const QList availableSizes() const + { return m_availableSizes; } + bool isWritable() const { return m_writable; } + bool isHidden() const { return m_hidden; } + QPixmap icon() const; + + /// Hash value for the internal name + uint hash() const { return m_hash; } + + /// Loads the cursor image @p name, with the nominal size @p size. + /// The image should be autocropped to the smallest possible size. + /// If the theme doesn't have the cursor @p name, it should return a null image. + virtual QImage loadImage(const QString &name, int size = 0) const = 0; + + /// Convenience function. Default implementation calls + /// QPixmap::fromImage(loadImage()); + virtual QPixmap loadPixmap(const QString &name, int size = 0) const; + + /// Loads the cursor @p name, with the nominal size @p size. + /// If the theme doesn't have the cursor @p name, it should return + /// the default cursor from the active theme instead. + virtual qulonglong loadCursor(const QString &name, int size = 0) const = 0; + + /** Creates the icon returned by @ref icon(). Don't use this function + directly but use @ref icon() instead, because @ref icon() caches + the icon. + @returns A pixmap with a cursor (usually left_ptr) that can + be used as icon for this theme. The size is adopted to + standard icon sizes.*/ + virtual QPixmap createIcon() const; + /** @returns A pixmap with a cursor (usually left_ptr) that can + be used as icon for this theme. */ + virtual QPixmap createIcon(int size) const; + + protected: + void setTitle( const QString &title ) { m_title = title; } + void setDescription( const QString &desc ) { m_description = desc; } + void setSample( const QString &sample ) { m_sample = sample; } + inline void setName( const QString &name ); + void setPath( const QString &path ) { m_path = path; } + void setAvailableSizes( const QList &availableSizes ) + { m_availableSizes = availableSizes; } + void setIcon( const QPixmap &icon ) { m_icon = icon; } + void setIsWritable( bool val ) { m_writable = val; } + void setIsHidden( bool val ) { m_hidden = val; } + + /// Convenience function for cropping an image. + QImage autoCropImage( const QImage &image ) const; + + // Convenience function that uses Xfixes to tag a cursor with a name + void setCursorName(qulonglong cursor, const QString &name) const; + + QString m_title; + QString m_description; + QString m_path; + QList m_availableSizes; + QString m_sample; + mutable QPixmap m_icon; + bool m_writable:1; + bool m_hidden:1; + + private: + QString m_name; + uint m_hash; + + friend class CursorThemeModel; +}; + +void CursorTheme::setName(const QString &name) +{ + m_name = name; + m_hash = qHash(name); +} + +#endif // CURSORTHEME_H + diff --git a/kcms/input/xcursor/itemdelegate.cpp b/kcms/input/xcursor/itemdelegate.cpp new file mode 100644 index 0000000000..e7370056e6 --- /dev/null +++ b/kcms/input/xcursor/itemdelegate.cpp @@ -0,0 +1,174 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 "itemdelegate.h" +#include "cursortheme.h" + +#include +#include +#include + +namespace +{ + const int decorationMargin = 8; +} + + +ItemDelegate::ItemDelegate(QObject *parent) + : QAbstractItemDelegate(parent) +{ +} + + +ItemDelegate::~ItemDelegate() +{ +} + + +QString ItemDelegate::firstLine(const QModelIndex &index) const +{ + if (index.isValid()) + return index.model()->data(index, Qt::DisplayRole).toString(); + + return QString(); +} + + +QString ItemDelegate::secondLine(const QModelIndex &index) const +{ + if (index.isValid()) + return index.model()->data(index, CursorTheme::DisplayDetailRole).toString(); + + return QString(); +} + + +QPixmap ItemDelegate::decoration(const QModelIndex &index) const +{ + if (index.isValid()) + return qvariant_cast(index.model()->data(index, Qt::DecorationRole)); + + return QPixmap(); +} + + +QSize ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (!index.isValid()) + return QSize(); + + QFont normalfont = option.font; + QFont boldfont = normalfont; + boldfont.setBold(true); + + // Extract the items we want to measure + QString firstRow = firstLine(index); + QString secondRow = secondLine(index); + + // Compute the height + QFontMetrics fm1(boldfont); + QFontMetrics fm2(normalfont); + int height = fm1.lineSpacing() + fm2.lineSpacing(); + height = qMax(height, option.decorationSize.height()); + + // Compute the text width + int width = fm1.width(firstRow); + width = qMax(width, fm2.width(secondRow)); + + // Add decoration width + margin + width += option.decorationSize.width() + decorationMargin; + + return QSize(width, height + 16); +} + + +QPalette::ColorRole ItemDelegate::foregroundRole(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(index) + + if (option.state & QStyle::State_Selected) + return QPalette::HighlightedText; + + return QPalette::Text; +} + + +void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (!index.isValid()) + return; + + painter->save(); + + QFont normalfont = option.font; + QFont boldfont = normalfont; + boldfont.setBold(true); + + QString firstRow = firstLine(index); + QString secondRow = secondLine(index); + QPixmap pixmap = decoration(index); + + QColor textcol = option.palette.color(foregroundRole(option, index)); + + // Draw the background + QStyleOptionViewItemV4 opt = option; + QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); + style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); + + // Draw the icon + int x = option.rect.left() + (option.decorationSize.width() - pixmap.width() + decorationMargin) / 2; + int y = option.rect.top() + (option.rect.height() - pixmap.height()) / 2; + + QRect pixmapRect = QStyle::visualRect(option.direction, option.rect, + QRect(x, y, pixmap.width(), pixmap.height())); + + painter->drawPixmap(pixmapRect.x(), pixmapRect.y(), pixmap); + + // Draw the text + QFontMetrics fm1(boldfont); + QFontMetrics fm2(normalfont); + + int textAreaHeight = fm1.lineSpacing(); + if (!secondRow.isEmpty()) { + textAreaHeight += fm2.lineSpacing(); + } + + x = option.rect.left() + option.decorationSize.width() + decorationMargin; + int y1 = option.rect.top() + (option.rect.height() - textAreaHeight) / 2; + int y2 = y1 + fm1.lineSpacing(); + + QRect firstRowRect = QStyle::visualRect(option.direction, option.rect, + QRect(x, y1, fm1.width(firstRow), fm1.lineSpacing())); + + QRect secondRowRect = QStyle::visualRect(option.direction, option.rect, + QRect(x, y2, fm2.width(secondRow), fm2.lineSpacing())); + + painter->setPen(textcol); + + // First line + painter->setFont(boldfont); + painter->drawText(firstRowRect, Qt::AlignCenter, firstRow); + + // Second line + painter->setFont(normalfont); + painter->drawText(secondRowRect, Qt::AlignCenter, secondRow); + + painter->restore(); +} + diff --git a/kcms/input/xcursor/itemdelegate.h b/kcms/input/xcursor/itemdelegate.h new file mode 100644 index 0000000000..9acb0e97bb --- /dev/null +++ b/kcms/input/xcursor/itemdelegate.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 ITEMDELEGATE_H +#define ITEMDELEGATE_H + +#include + +class QPainter; + +class ItemDelegate : public QAbstractItemDelegate +{ + public: + ItemDelegate(QObject *parent = 0); + ~ItemDelegate(); + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + + private: + QString firstLine(const QModelIndex &index) const; + QString secondLine(const QModelIndex &index) const; + QPixmap decoration(const QModelIndex &index) const; + QPalette::ColorRole foregroundRole(const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +#endif diff --git a/kcms/input/xcursor/previewwidget.cpp b/kcms/input/xcursor/previewwidget.cpp new file mode 100644 index 0000000000..79d1305f93 --- /dev/null +++ b/kcms/input/xcursor/previewwidget.cpp @@ -0,0 +1,239 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 +#include + +#include "previewwidget.h" + +#include +#include +#include +#include + +#include "cursortheme.h" + + + +namespace { + + // Preview cursors + const char * const cursor_names[] = + { + "left_ptr", + "left_ptr_watch", + "wait", + "pointing_hand", + "whats_this", + "ibeam", + "size_all", + "size_fdiag", + "cross", + "split_h", + "size_ver", + "size_hor", + "size_bdiag", + "split_v", + }; + + const int numCursors = 9; // The number of cursors from the above list to be previewed + const int cursorSpacing = 20; // Spacing between preview cursors + const int widgetMinWidth = 10; // The minimum width of the preview widget + const int widgetMinHeight = 48; // The minimum height of the preview widget +} + + +class PreviewCursor +{ + public: + PreviewCursor( const CursorTheme *theme, const QString &name, int size ); + ~PreviewCursor(); + + const QPixmap &pixmap() const { return m_pixmap; } + int width() const { return m_pixmap.width(); } + int height() const { return m_pixmap.height(); } + inline QRect rect() const; + void setPosition( const QPoint &p ) { m_pos = p; } + void setPosition( int x, int y ) { m_pos = QPoint(x, y); } + QPoint position() const { return m_pos; } + operator const uint32_t () const { return m_cursor; } + operator const QPixmap& () const { return pixmap(); } + + private: + QPixmap m_pixmap; + uint32_t m_cursor; + QPoint m_pos; +}; + + +PreviewCursor::PreviewCursor(const CursorTheme *theme, const QString &name, int size) +{ + // Create the preview pixmap + QImage image = theme->loadImage(name, size); + + if (image.isNull()) + return; + + m_pixmap = QPixmap::fromImage(image); + + // Load the cursor + m_cursor = theme->loadCursor(name, size); + // ### perhaps we should tag the cursor so it doesn't get + // replaced when a new theme is applied +} + +PreviewCursor::~PreviewCursor() +{ + if (QX11Info::isPlatformX11() && m_cursor != XCB_CURSOR_NONE) { + xcb_free_cursor(QX11Info::connection(), m_cursor); + } +} + +QRect PreviewCursor::rect() const +{ + return QRect(m_pos, m_pixmap.size()) + .adjusted(-(cursorSpacing / 2), -(cursorSpacing / 2), + cursorSpacing / 2, cursorSpacing / 2); +} + + + +// ------------------------------------------------------------------------------ + + + +PreviewWidget::PreviewWidget(QWidget *parent) : QWidget(parent) +{ + setMouseTracking(true); + current = NULL; +} + + +PreviewWidget::~PreviewWidget() +{ + qDeleteAll(list); + list.clear(); +} + + +QSize PreviewWidget::sizeHint() const +{ + int totalWidth = 0; + int maxHeight = 0; + + foreach (const PreviewCursor *c, list) + { + totalWidth += c->width(); + maxHeight = qMax(c->height(), maxHeight); + } + + totalWidth += (list.count() - 1) * cursorSpacing; + maxHeight = qMax(maxHeight, widgetMinHeight); + + return QSize(qMax(totalWidth, widgetMinWidth), qMax(height(), maxHeight)); +} + + +void PreviewWidget::layoutItems() +{ + if (!list.isEmpty()) + { + QSize size = sizeHint(); + int cursorWidth = size.width() / list.count(); + int nextX = (width() - size.width()) / 2; + + foreach (PreviewCursor *c, list) + { + c->setPosition(nextX + (cursorWidth - c->width()) / 2, + (height() - c->height()) / 2); + nextX += cursorWidth; + } + } + + needLayout = false; +} + + +void PreviewWidget::setTheme(const CursorTheme *theme, const int size) +{ + qDeleteAll(list); + list.clear(); + + if (theme) + { + for (int i = 0; i < numCursors; i++) + list << new PreviewCursor(theme, cursor_names[i], size); + + needLayout = true; + updateGeometry(); + } + + current = NULL; + update(); +} + + +void PreviewWidget::paintEvent(QPaintEvent *) +{ + QPainter p(this); + + if (needLayout) + layoutItems(); + + foreach(const PreviewCursor *c, list) + { + if (c->pixmap().isNull()) + continue; + + p.drawPixmap(c->position(), *c); + } +} + + +void PreviewWidget::mouseMoveEvent(QMouseEvent *e) +{ + if (needLayout) + layoutItems(); + + foreach (const PreviewCursor *c, list) + { + if (c->rect().contains(e->pos())) + { + if (c != current) + { + const uint32_t cursor = *c; + if (QX11Info::isPlatformX11() && (cursor != XCB_CURSOR_NONE)) { + xcb_change_window_attributes(QX11Info::connection(), winId(), XCB_CW_CURSOR, &cursor); + } + current = c; + } + return; + } + } + + setCursor(Qt::ArrowCursor); + current = NULL; +} + + +void PreviewWidget::resizeEvent(QResizeEvent *) +{ + if (!list.isEmpty()) + needLayout = true; +} + diff --git a/kcms/input/xcursor/previewwidget.h b/kcms/input/xcursor/previewwidget.h new file mode 100644 index 0000000000..4a11e2d2a8 --- /dev/null +++ b/kcms/input/xcursor/previewwidget.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 PREVIEWWIDGET_H +#define PREVIEWWIDGET_H + +#include + +class CursorTheme; +class PreviewCursor; + +class PreviewWidget : public QWidget +{ + public: + PreviewWidget(QWidget *parent); + ~PreviewWidget(); + + void setTheme(const CursorTheme *theme, const int size); + void setUseLables(bool); + QSize sizeHint() const; + + protected: + void paintEvent(QPaintEvent *); + void mouseMoveEvent(QMouseEvent *); + void resizeEvent(QResizeEvent *); + + private: + void layoutItems(); + + QList list; + const PreviewCursor *current; + bool needLayout:1; +}; + +#endif // PREVIEWWIDGET_H + diff --git a/kcms/input/xcursor/sortproxymodel.cpp b/kcms/input/xcursor/sortproxymodel.cpp new file mode 100644 index 0000000000..b9d6309278 --- /dev/null +++ b/kcms/input/xcursor/sortproxymodel.cpp @@ -0,0 +1,50 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 +#include "sortproxymodel.h" +#include "cursortheme.h" + + +int SortProxyModel::compare(const QModelIndex &left, const QModelIndex &right, int role) const +{ + const QAbstractItemModel *model = sourceModel(); + + QString first = model->data(left, role).toString(); + QString second = model->data(right, role).toString(); + + if (filterCaseSensitivity() == Qt::CaseSensitive) + { + first = first.toLower(); + second = second.toLower(); + } + + return QString::localeAwareCompare(first, second); +} + + +bool SortProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + const int result = compare(left, right, Qt::DisplayRole); + + if (result != 0) + return (result < 0); + else + return compare(left, right, CursorTheme::DisplayDetailRole) < 0; +} diff --git a/kcms/input/xcursor/sortproxymodel.h b/kcms/input/xcursor/sortproxymodel.h new file mode 100644 index 0000000000..95c9646c7c --- /dev/null +++ b/kcms/input/xcursor/sortproxymodel.h @@ -0,0 +1,77 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 SORTPROXYMODEL_H +#define SORTPROXYMODEL_H + +#include +#include + +/** + * SortProxyModel is a sorting proxy model intended to be used in combination + * with the ItemDelegate class. + * + * First it compares the Qt::DisplayRoles, and if they match it compares + * the CursorTheme::DisplayDetailRoles. + * + * The model assumes both display roles are QStrings. + */ +class SortProxyModel : public QSortFilterProxyModel +{ + public: + SortProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {} + ~SortProxyModel() {} + inline const CursorTheme *theme(const QModelIndex &index) const; + inline QModelIndex findIndex(const QString &name) const; + inline QModelIndex defaultIndex() const; + inline void removeTheme(const QModelIndex &index); + + private: + int compare(const QModelIndex &left, const QModelIndex &right, int role) const; + + protected: + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; +}; + + +const CursorTheme *SortProxyModel::theme(const QModelIndex &index) const +{ + CursorThemeModel *model = static_cast(sourceModel()); + return model->theme(mapToSource(index)); +} + +QModelIndex SortProxyModel::findIndex(const QString &name) const +{ + CursorThemeModel *model = static_cast(sourceModel()); + return mapFromSource(model->findIndex(name)); +} + +QModelIndex SortProxyModel::defaultIndex() const +{ + CursorThemeModel *model = static_cast(sourceModel()); + return mapFromSource(model->defaultIndex()); +} + +void SortProxyModel::removeTheme(const QModelIndex &index) +{ + CursorThemeModel *model = static_cast(sourceModel()); + model->removeTheme(mapToSource(index)); +} + +#endif // SORTPROXYMODEL_H diff --git a/kcms/input/xcursor/thememodel.cpp b/kcms/input/xcursor/thememodel.cpp new file mode 100644 index 0000000000..0dc04cff79 --- /dev/null +++ b/kcms/input/xcursor/thememodel.cpp @@ -0,0 +1,419 @@ +/* + * Copyright © 2005-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include + +#include "thememodel.h" +#include "thememodel.moc" +#include "xcursortheme.h" + +#include +#include + +// Check for older version +#if !defined(XCURSOR_LIB_MAJOR) && defined(XCURSOR_MAJOR) +# define XCURSOR_LIB_MAJOR XCURSOR_MAJOR +# define XCURSOR_LIB_MINOR XCURSOR_MINOR +#endif + + + +CursorThemeModel::CursorThemeModel(QObject *parent) + : QAbstractTableModel(parent) +{ + insertThemes(); +} + +CursorThemeModel::~CursorThemeModel() +{ + qDeleteAll(list); + list.clear(); +} + +void CursorThemeModel::refreshList() +{ + beginResetModel(); + qDeleteAll(list); + list.clear(); + endResetModel(); + insertThemes(); +} + +QVariant CursorThemeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + // Only provide text for the headers + if (role != Qt::DisplayRole) + return QVariant(); + + // Horizontal header labels + if (orientation == Qt::Horizontal) + { + switch (section) + { + case NameColumn: + return i18n("Name"); + + case DescColumn: + return i18n("Description"); + + default: return QVariant(); + } + } + + // Numbered vertical header lables + return QString(section); +} + + +QVariant CursorThemeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= list.count()) + return QVariant(); + + const CursorTheme *theme = list.at(index.row()); + + // Text label + if (role == Qt::DisplayRole) + { + switch (index.column()) + { + case NameColumn: + return theme->title(); + + case DescColumn: + return theme->description(); + + default: return QVariant(); + } + } + + // Description for the first name column + if (role == CursorTheme::DisplayDetailRole && index.column() == NameColumn) + return theme->description(); + + // Icon for the name column + if (role == Qt::DecorationRole && index.column() == NameColumn) + return theme->icon(); + + return QVariant(); +} + + +void CursorThemeModel::sort(int column, Qt::SortOrder order) +{ + Q_UNUSED(column); + Q_UNUSED(order); + + // Sorting of the model isn't implemented, as the KCM currently uses + // a sorting proxy model. +} + + +const CursorTheme *CursorThemeModel::theme(const QModelIndex &index) +{ + if (!index.isValid()) + return NULL; + + if (index.row() < 0 || index.row() >= list.count()) + return NULL; + + return list.at(index.row()); +} + + +QModelIndex CursorThemeModel::findIndex(const QString &name) +{ + uint hash = qHash(name); + + for (int i = 0; i < list.count(); i++) + { + const CursorTheme *theme = list.at(i); + if (theme->hash() == hash) + return index(i, 0); + } + + return QModelIndex(); +} + + +QModelIndex CursorThemeModel::defaultIndex() +{ + return findIndex(defaultName); +} + + +const QStringList CursorThemeModel::searchPaths() +{ + if (!baseDirs.isEmpty()) + return baseDirs; + +#if XCURSOR_LIB_MAJOR == 1 && XCURSOR_LIB_MINOR < 1 + // These are the default paths Xcursor will scan for cursor themes + QString path("~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons"); + + // If XCURSOR_PATH is set, use that instead of the default path + char *xcursorPath = std::getenv("XCURSOR_PATH"); + if (xcursorPath) + path = xcursorPath; +#else + // Get the search path from Xcursor + QString path = XcursorLibraryPath(); +#endif + + // Separate the paths + baseDirs = path.split(':', QString::SkipEmptyParts); + + // Remove duplicates + QMutableStringListIterator i(baseDirs); + while (i.hasNext()) + { + const QString path = i.next(); + QMutableStringListIterator j(i); + while (j.hasNext()) + if (j.next() == path) + j.remove(); + } + + // Expand all occurrences of ~/ to the home dir + baseDirs.replaceInStrings(QRegExp("^~\\/"), QDir::home().path() + '/'); + return baseDirs; +} + + +bool CursorThemeModel::hasTheme(const QString &name) const +{ + const uint hash = qHash(name); + + foreach (const CursorTheme *theme, list) + if (theme->hash() == hash) + return true; + + return false; +} + + +bool CursorThemeModel::isCursorTheme(const QString &theme, const int depth) +{ + // Prevent infinite recursion + if (depth > 10) + return false; + + // Search each icon theme directory for 'theme' + foreach (const QString &baseDir, searchPaths()) + { + QDir dir(baseDir); + if (!dir.exists() || !dir.cd(theme)) + continue; + + // If there's a cursors subdir, we'll assume this is a cursor theme + if (dir.exists("cursors")) + return true; + + // If the theme doesn't have an index.theme file, it can't inherit any themes. + if (!dir.exists("index.theme")) + continue; + + // Open the index.theme file, so we can get the list of inherited themes + KConfig config(dir.path() + "/index.theme", KConfig::NoGlobals); + KConfigGroup cg(&config, "Icon Theme"); + + // Recurse through the list of inherited themes, to check if one of them + // is a cursor theme. + QStringList inherits = cg.readEntry("Inherits", QStringList()); + foreach (const QString &inherit, inherits) + { + // Avoid possible DoS + if (inherit == theme) + continue; + + if (isCursorTheme(inherit, depth + 1)) + return true; + } + } + + return false; +} + + +bool CursorThemeModel::handleDefault(const QDir &themeDir) +{ + QFileInfo info(themeDir.path()); + + // If "default" is a symlink + if (info.isSymLink()) + { + QFileInfo target(info.symLinkTarget()); + if (target.exists() && (target.isDir() || target.isSymLink())) + defaultName = target.fileName(); + + return true; + } + + // If there's no cursors subdir, or if it's empty + if (!themeDir.exists("cursors") || QDir(themeDir.path() + "/cursors") + .entryList(QDir::Files | QDir::NoDotAndDotDot ).isEmpty()) + { + if (themeDir.exists("index.theme")) + { + XCursorTheme theme(themeDir); + if (!theme.inherits().isEmpty()) + defaultName = theme.inherits().at(0); + } + return true; + } + + defaultName = QLatin1String("default"); + return false; +} + + +void CursorThemeModel::processThemeDir(const QDir &themeDir) +{ + bool haveCursors = themeDir.exists("cursors"); + + // Special case handling of "default", since it's usually either a + // symlink to another theme, or an empty theme that inherits another + // theme. + if (defaultName.isNull() && themeDir.dirName() == "default") + { + if (handleDefault(themeDir)) + return; + } + + // If the directory doesn't have a cursors subdir and lacks an + // index.theme file it can't be a cursor theme. + if (!themeDir.exists("index.theme") && !haveCursors) + return; + + static bool isX11 = QX11Info::isPlatformX11(); + if (!isX11) { + // TODO: implement Wayland Cursor Theme support + return; + } + // Create a cursor theme object for the theme dir + XCursorTheme *theme = new XCursorTheme(themeDir); + + // Skip this theme if it's hidden. + if (theme->isHidden()) { + delete theme; + return; + } + + // If there's no cursors subdirectory we'll do a recursive scan + // to check if the theme inherits a theme with one. + if (!haveCursors) + { + bool foundCursorTheme = false; + + foreach (const QString &name, theme->inherits()) + if ((foundCursorTheme = isCursorTheme(name))) + break; + + if (!foundCursorTheme) { + delete theme; + return; + } + } + + // Append the theme to the list + beginInsertRows(QModelIndex(), list.size(), list.size()); + list.append(theme); + endInsertRows(); +} + + +void CursorThemeModel::insertThemes() +{ + // Scan each base dir for Xcursor themes and add them to the list. + foreach (const QString &baseDir, searchPaths()) + { + QDir dir(baseDir); + if (!dir.exists()) + continue; + + // Process each subdir in the directory + foreach (const QString &name, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) + { + // Don't process the theme if a theme with the same name already exists + // in the list. Xcursor will pick the first one it finds in that case, + // and since we use the same search order, the one Xcursor picks should + // be the one already in the list. + if (hasTheme(name) || !dir.cd(name)) + continue; + + processThemeDir(dir); + dir.cdUp(); // Return to the base dir + } + } + + // The theme Xcursor will end up using if no theme is configured + if (defaultName.isNull() || !hasTheme(defaultName)) + defaultName = QLatin1String("KDE_Classic"); +} + + +bool CursorThemeModel::addTheme(const QDir &dir) +{ + XCursorTheme *theme = new XCursorTheme(dir); + + // Don't add the theme to the list if it's hidden + if (theme->isHidden()) { + delete theme; + return false; + } + + // ### If the theme is hidden, the user will probably find it strange that it + // doesn't appear in the list view. There also won't be a way for the user + // to delete the theme using the KCM. Perhaps a warning about this should + // be issued, and the user be given a chance to undo the installation. + + // If an item with the same name already exists in the list, + // we'll remove it before inserting the new one. + for (int i = 0; i < list.count(); i++) + { + if (list.at(i)->hash() == theme->hash()) { + removeTheme(index(i, 0)); + break; + } + } + + // Append the theme to the list + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + list.append(theme); + endInsertRows(); + + return true; +} + + +void CursorThemeModel::removeTheme(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + beginRemoveRows(QModelIndex(), index.row(), index.row()); + delete list.takeAt(index.row()); + endRemoveRows(); +} + diff --git a/kcms/input/xcursor/thememodel.h b/kcms/input/xcursor/thememodel.h new file mode 100644 index 0000000000..bcf046a9c8 --- /dev/null +++ b/kcms/input/xcursor/thememodel.h @@ -0,0 +1,114 @@ +/* + * Copyright © 2005-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 THEMEMODEL_H +#define THEMEMODEL_H + +#include +#include + +class QDir; +class CursorTheme; + +// The two TableView/TreeView columns provided by the model +enum Columns { NameColumn = 0, DescColumn }; + + +/** + * The CursorThemeModel class provides a model for all locally installed + * Xcursor themes, and the KDE/Qt legacy bitmap theme. + * + * This class automatically scans the locations in the file system from + * which Xcursor loads cursors, and creates an internal list of all + * available cursor themes. + * + * The model provides this theme list to item views in the form of a list + * of rows with two columns; the first column has the theme's descriptive + * name and its sample cursor as its icon, and the second column contains + * the theme's description. + * + * Additional Xcursor themes can be added to a model after it's been + * created, by calling addTheme(), which takes QDir as a parameter, + * with the themes location. The intention is for this function to be + * called when a new Xcursor theme has been installed, after the model + * was instantiated. + * + * The KDE legacy theme is a read-only entry, with the descriptive name + * "KDE Classic", and the internal name "#kde_legacy#". + * + * Calling defaultIndex() will return the index of the theme Xcursor + * will use if the user hasn't explicitly configured a cursor theme. + */ +class CursorThemeModel : public QAbstractTableModel +{ + Q_OBJECT + + public: + CursorThemeModel(QObject *parent = 0); + ~CursorThemeModel(); + inline int columnCount(const QModelIndex &parent = QModelIndex()) const; + inline int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role) const; + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + + /// Returns the CursorTheme at @p index. + const CursorTheme *theme(const QModelIndex &index); + + /// Returns the index for the CursorTheme with the internal name @p name, + /// or an invalid index if no matching theme can be found. + QModelIndex findIndex(const QString &name); + + /// Returns the index for the default theme. + QModelIndex defaultIndex(); + + /// Adds the theme in @p dir, and returns @a true if successful or @a false otherwise. + bool addTheme(const QDir &dir); + void removeTheme(const QModelIndex &index); + + /// Returns the list of base dirs Xcursor looks for themes in. + const QStringList searchPaths(); + + /// Refresh the list of themes by checking what's on disk. + void refreshList(); + + private: + bool handleDefault(const QDir &dir); + void processThemeDir(const QDir &dir); + void insertThemes(); + bool hasTheme(const QString &theme) const; + bool isCursorTheme(const QString &theme, const int depth = 0); + + private: + QList list; + QStringList baseDirs; + QString defaultName; +}; + +int CursorThemeModel::rowCount(const QModelIndex &) const +{ + return list.count(); +} + +int CursorThemeModel::columnCount(const QModelIndex &) const +{ + return 2; +} + +#endif // THEMEMODEL_H diff --git a/kcms/input/xcursor/themepage.cpp b/kcms/input/xcursor/themepage.cpp new file mode 100644 index 0000000000..6a8fbd6f0e --- /dev/null +++ b/kcms/input/xcursor/themepage.cpp @@ -0,0 +1,589 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include "../../krdb/krdb.h" + +#include +#include +#include +#include + +#include "themepage.h" +#include "themepage.moc" + +#include "thememodel.h" +#include "itemdelegate.h" +#include "sortproxymodel.h" +#include "cursortheme.h" + +#include +#include + +#ifdef HAVE_XFIXES +# include +#endif + + +ThemePage::ThemePage(QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + installKnsButton->setIcon(QIcon::fromTheme("get-hot-new-stuff")); + installButton->setIcon(QIcon::fromTheme("document-import")); + removeButton->setIcon(QIcon::fromTheme("edit-delete")); + + model = new CursorThemeModel(this); + + proxy = new SortProxyModel(this); + proxy->setSourceModel(model); + proxy->setFilterCaseSensitivity(Qt::CaseSensitive); + proxy->sort(NameColumn, Qt::AscendingOrder); + + // Get the icon size for QListView + int size = style()->pixelMetric(QStyle::PM_LargeIconSize); + + view->setModel(proxy); + view->setItemDelegate(new ItemDelegate(this)); + view->setIconSize(QSize(size, size)); + view->setSelectionMode(QAbstractItemView::SingleSelection); + + // Make sure we find out about selection changes + connect(view->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + SLOT(selectionChanged())); + + // Make sure we find out about size changes + connect(sizeComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(sizeChanged())); + + // Make sure we find out about user activity + connect(sizeComboBox, + SIGNAL(activated(int)), + SLOT(preferredSizeChanged())); + + // Disable the install button if we can't install new themes to ~/.icons, + // or Xcursor isn't set up to look for cursor themes there. + if (!model->searchPaths().contains(QDir::homePath() + "/.icons") || !iconsIsWritable()) { + installButton->setEnabled(false); + installKnsButton->setEnabled(false); + } + + connect(installKnsButton, SIGNAL(clicked()), SLOT(getNewClicked())); + connect(installButton, SIGNAL(clicked()), SLOT(installClicked())); + connect(removeButton, SIGNAL(clicked()), SLOT(removeClicked())); +} + + +ThemePage::~ThemePage() +{ +} + + +bool ThemePage::iconsIsWritable() const +{ + const QFileInfo icons = QFileInfo(QDir::homePath() + "/.icons"); + const QFileInfo home = QFileInfo(QDir::homePath()); + + return ((icons.exists() && icons.isDir() && icons.isWritable()) || + (!icons.exists() && home.isWritable())); +} + + +void ThemePage::updateSizeComboBox() +{ + // clear the combo box + sizeComboBox->clear(); + + // refill the combo box and adopt its icon size + QModelIndex selected = selectedIndex(); + int maxIconWidth = 0; + int maxIconHeight = 0; + if (selected.isValid()) + { + const CursorTheme *theme = proxy->theme(selected); + const QList sizes = theme->availableSizes(); + QIcon m_icon; + if (sizes.size() > 1) // only refill the combobox if there is more that 1 size + { + int i; + QList comboBoxList; + QPixmap m_pixmap; + + // insert the items + m_pixmap = theme->createIcon(0); + if (m_pixmap.width() > maxIconWidth) + maxIconWidth = m_pixmap.width(); + if (m_pixmap.height() > maxIconHeight) + maxIconHeight = m_pixmap.height(); + sizeComboBox->addItem( + QIcon(m_pixmap), + i18nc("@item:inlistbox size", "resolution dependent"), + 0); + comboBoxList << 0; + foreach (i, sizes) + { + m_pixmap = theme->createIcon(i); + if (m_pixmap.width() > maxIconWidth) + maxIconWidth = m_pixmap.width(); + if (m_pixmap.height() > maxIconHeight) + maxIconHeight = m_pixmap.height(); + sizeComboBox->addItem(QIcon(m_pixmap), QString::number(i), i); + comboBoxList << i; + }; + + // select an item + int selectItem = comboBoxList.indexOf(preferredSize); + if (selectItem < 0) // preferredSize not available for this theme + { + /* Search the value next to preferredSize. The first entry (0) + is ignored. (If preferredSize would have been 0, then we + would had found it yet. As preferredSize is not 0, we won't + default to "automatic size".)*/ + int j; + int distance; + int smallestDistance; + selectItem = 1; + j = comboBoxList.value(selectItem); + smallestDistance = j < preferredSize ? preferredSize - j : j - preferredSize; + for (int i = 2; i < comboBoxList.size(); ++i) + { + j = comboBoxList.value(i); + distance = j < preferredSize ? preferredSize - j : j - preferredSize; + if (distance < smallestDistance || (distance == smallestDistance && j > preferredSize)) + { + smallestDistance = distance; + selectItem = i; + }; + } + }; + sizeComboBox->setCurrentIndex(selectItem); + }; + }; + sizeComboBox->setIconSize(QSize(maxIconWidth, maxIconHeight)); + + // enable or disable the combobox + KConfig c("kcminputrc"); + KConfigGroup cg(&c, "Mouse"); + if (cg.isEntryImmutable("cursorSize")) { + sizeComboBox->setEnabled(false); + sizeLabel->setEnabled(false); + } else { + sizeComboBox->setEnabled(sizeComboBox->count() > 0); + sizeLabel->setEnabled(sizeComboBox->count() > 0); + }; +} + + +int ThemePage::selectedSize() const +{ + if (sizeComboBox->isEnabled() && sizeComboBox->currentIndex() >= 0) + return sizeComboBox->itemData(sizeComboBox->currentIndex(), Qt::UserRole).toInt(); + return 0; +} + + +void ThemePage::updatePreview() +{ + QModelIndex selected = selectedIndex(); + + if (selected.isValid()) { + const CursorTheme *theme = proxy->theme(selected); + preview->setTheme(theme, selectedSize()); + removeButton->setEnabled(theme->isWritable()); + } else { + preview->setTheme(NULL, 0); + removeButton->setEnabled(false); + }; +} + + +bool ThemePage::haveXfixes() +{ + bool result = false; + +#ifdef HAVE_XFIXES + if (!QX11Info::isPlatformX11()) { + return result; + } + int event_base, error_base; + if (XFixesQueryExtension(QX11Info::display(), &event_base, &error_base)) + { + int major, minor; + XFixesQueryVersion(QX11Info::display(), &major, &minor); + result = (major >= 2); + } +#endif + + return result; +} + + +bool ThemePage::applyTheme(const CursorTheme *theme, const int size) +{ + // Require the Xcursor version that shipped with X11R6.9 or greater, since + // in previous versions the Xfixes code wasn't enabled due to a bug in the + // build system (freedesktop bug #975). +#if HAVE_XFIXES && XFIXES_MAJOR >= 2 && XCURSOR_LIB_VERSION >= 10105 + if (!theme) + return false; + + if (!haveXfixes()) + return false; + + QByteArray themeName = QFile::encodeName(theme->name()); + + // Set up the proper launch environment for newly started apps + OrgKdeKLauncherInterface klauncher(QStringLiteral("org.kde.klauncher5"), + QStringLiteral("/KLauncher"), + QDBusConnection::sessionBus()); + klauncher.setLaunchEnv(QStringLiteral("XCURSOR_THEME"), themeName); + + // Update the Xcursor X resources + runRdb(0); + + // Notify all applications that the cursor theme has changed + KGlobalSettings::self()->emitChange(KGlobalSettings::CursorChanged); + + // Reload the standard cursors + QStringList names; + + // Qt cursors + names << "left_ptr" << "up_arrow" << "cross" << "wait" + << "left_ptr_watch" << "ibeam" << "size_ver" << "size_hor" + << "size_bdiag" << "size_fdiag" << "size_all" << "split_v" + << "split_h" << "pointing_hand" << "openhand" + << "closedhand" << "forbidden" << "whats_this" << "copy" << "move" << "link"; + + // X core cursors + names << "X_cursor" << "right_ptr" << "hand1" + << "hand2" << "watch" << "xterm" + << "crosshair" << "left_ptr_watch" << "center_ptr" + << "sb_h_double_arrow" << "sb_v_double_arrow" << "fleur" + << "top_left_corner" << "top_side" << "top_right_corner" + << "right_side" << "bottom_right_corner" << "bottom_side" + << "bottom_left_corner" << "left_side" << "question_arrow" + << "pirate"; + + foreach (const QString &name, names) + { + XFixesChangeCursorByName(QX11Info::display(), theme->loadCursor(name, size), QFile::encodeName(name)); + } + + return true; +#else + Q_UNUSED(theme) + return false; +#endif +} + + +void ThemePage::save() +{ + const CursorTheme *theme = selectedIndex().isValid() ? proxy->theme(selectedIndex()) : NULL; + const int size = selectedSize(); + + KConfig config("kcminputrc"); + KConfigGroup c(&config, "Mouse"); + if (theme) + { + c.writeEntry("cursorTheme", theme->name()); + }; + c.writeEntry("cursorSize", size); + preferredSize = size; + c.sync(); + + if (!applyTheme(theme, size)) + { + KMessageBox::information(this, + i18n("You have to restart KDE for these changes to take effect."), + i18n("Cursor Settings Changed"), "CursorSettingsChanged"); + } + + appliedIndex = selectedIndex(); + appliedSize = size; +} + + +void ThemePage::load() +{ + view->selectionModel()->clear(); + // Get the name of the theme libXcursor currently uses + QString currentTheme; + if (QX11Info::isPlatformX11()) { + currentTheme = XcursorGetTheme(QX11Info::display()); + } + + // Get the name of the theme KDE is configured to use + KConfig c("kcminputrc"); + KConfigGroup cg(&c, "Mouse"); + currentTheme = cg.readEntry("cursorTheme", currentTheme); + + // Find the theme in the listview + if (!currentTheme.isEmpty()) + appliedIndex = proxy->findIndex(currentTheme); + else + appliedIndex = proxy->defaultIndex(); + + // Disable the listview and the buttons if we're in kiosk mode + if (cg.isEntryImmutable("cursorTheme")) + { + view->setEnabled(false); + installButton->setEnabled(false); + removeButton->setEnabled(false); + } + + // Load cursor size + int size = cg.readEntry("cursorSize", 0); + if (size <= 0) + preferredSize = 0; + else + preferredSize = size; + updateSizeComboBox(); // This handles also the kiosk mode + + appliedSize = size; + + const CursorTheme *theme = proxy->theme(appliedIndex); + + if (appliedIndex.isValid()) + { + // Select the current theme + view->setCurrentIndex(appliedIndex); + view->scrollTo(appliedIndex, QListView::PositionAtCenter); + + // Update the preview widget as well + preview->setTheme(theme, size); + } + + if (!theme || !theme->isWritable()) + removeButton->setEnabled(false); +} + + +void ThemePage::defaults() +{ + view->selectionModel()->clear(); + QModelIndex defaultIndex = proxy->findIndex("Oxygen_Black"); + view->setCurrentIndex(defaultIndex); + preferredSize = 0; + updateSizeComboBox(); +} + + +void ThemePage::selectionChanged() +{ + updateSizeComboBox(); + updatePreview(); + + emit changed(appliedIndex != selectedIndex()); +} + +QModelIndex ThemePage::selectedIndex() const +{ + QModelIndexList selection = view->selectionModel()->selectedIndexes(); + if (!selection.isEmpty()) { + return (selection.at(0)); + } + return QModelIndex(); +} + +void ThemePage::sizeChanged() +{ + updatePreview(); + emit changed(selectedSize() != appliedSize); +} + +void ThemePage::preferredSizeChanged() +{ + int index = sizeComboBox->currentIndex(); + if (index >= 0) + preferredSize = sizeComboBox->itemData(index, Qt::UserRole).toInt(); + else + preferredSize = 0; +} + +void ThemePage::getNewClicked() +{ + KNS3::DownloadDialog dialog("xcursor.knsrc", this); + if (dialog.exec()) { + KNS3::Entry::List list = dialog.changedEntries(); + if (list.count() > 0) + model->refreshList(); + } +} + +void ThemePage::installClicked() +{ + // Get the URL for the theme we're going to install + QUrl url = KUrlRequesterDialog::getUrl(QUrl(), this, i18n("Drag or Type Theme URL")); + + if (url.isEmpty()) + return; + + QString tempFile; + if (!KIO::NetAccess::download(url, tempFile, this)) + { + QString text; + + if (url.isLocalFile()) + text = i18n("Unable to find the cursor theme archive %1.", + url.toDisplayString()); + else + text = i18n("Unable to download the cursor theme archive; " + "please check that the address %1 is correct.", + url.toDisplayString()); + + KMessageBox::sorry(this, text); + return; + } + + if (!installThemes(tempFile)) + KMessageBox::error(this, i18n("The file %1 does not appear to be a valid " + "cursor theme archive.", url.fileName())); + + KIO::NetAccess::removeTempFile(tempFile); +} + + +void ThemePage::removeClicked() +{ + // We don't have to check if the current index is valid, since + // the remove button will be disabled when there's no selection. + const CursorTheme *theme = proxy->theme(selectedIndex()); + + // Don't let the user delete the currently configured theme + if (selectedIndex() == appliedIndex) { + KMessageBox::sorry(this, i18n("You cannot delete the theme you are currently " + "using.
    You have to switch to another theme first.
    ")); + return; + } + + // Get confirmation from the user + QString question = i18n("Are you sure you want to remove the " + "%1 cursor theme?
    " + "This will delete all the files installed by this theme.
    ", + theme->title()); + + int answer = KMessageBox::warningContinueCancel(this, question, + i18n("Confirmation"), KStandardGuiItem::del()); + + if (answer != KMessageBox::Continue) + return; + + // Delete the theme from the harddrive + KIO::del(QUrl::fromLocalFile(theme->path())); // async + + // Remove the theme from the model + proxy->removeTheme(selectedIndex()); + + // TODO: + // Since it's possible to substitute cursors in a system theme by adding a local + // theme with the same name, we shouldn't remove the theme from the list if it's + // still available elsewhere. We could add a + // bool CursorThemeModel::tryAddTheme(const QString &name), and call that, but + // since KIO::del() is an asynchronos operation, the theme we're deleting will be + // readded to the list again before KIO has removed it. +} + + +bool ThemePage::installThemes(const QString &file) +{ + KTar archive(file); + + if (!archive.open(QIODevice::ReadOnly)) + return false; + + const KArchiveDirectory *archiveDir = archive.directory(); + QStringList themeDirs; + + // Extract the dir names of the cursor themes in the archive, and + // append them to themeDirs + foreach(const QString &name, archiveDir->entries()) + { + const KArchiveEntry *entry = archiveDir->entry(name); + if (entry->isDirectory() && entry->name().toLower() != "default") + { + const KArchiveDirectory *dir = static_cast(entry); + if (dir->entry("index.theme") && dir->entry("cursors")) + themeDirs << dir->name(); + } + } + + if (themeDirs.isEmpty()) + return false; + + // The directory we'll install the themes to + QString destDir = QDir::homePath() + "/.icons/"; + KStandardDirs::makeDir(destDir); // Make sure the directory exists + + // Process each cursor theme in the archive + foreach (const QString &dirName, themeDirs) + { + QDir dest(destDir + dirName); + if (dest.exists()) + { + QString question = i18n("A theme named %1 already exists in your icon " + "theme folder. Do you want replace it with this one?", dirName); + + int answer = KMessageBox::warningContinueCancel(this, question, + i18n("Overwrite Theme?"), + KStandardGuiItem::overwrite()); + + if (answer != KMessageBox::Continue) + continue; + + // ### If the theme that's being replaced is the current theme, it + // will cause cursor inconsistencies in newly started apps. + } + + // ### Should we check if a theme with the same name exists in a global theme dir? + // If that's the case it will effectively replace it, even though the global theme + // won't be deleted. Checking for this situation is easy, since the global theme + // will be in the listview. Maybe this should never be allowed since it might + // result in strange side effects (from the average users point of view). OTOH + // a user might want to do this 'upgrade' a global theme. + + const KArchiveDirectory *dir = static_cast + (archiveDir->entry(dirName)); + dir->copyTo(dest.path()); + model->addTheme(dest); + } + + archive.close(); + return true; +} + diff --git a/kcms/input/xcursor/themepage.h b/kcms/input/xcursor/themepage.h new file mode 100644 index 0000000000..cf82be79c4 --- /dev/null +++ b/kcms/input/xcursor/themepage.h @@ -0,0 +1,99 @@ +/* + * Copyright © 2003-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * 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 THEMEPAGE_H +#define THEMEPAGE_H + +#include +#include + +#include "ui_themepage.h" + +class CursorThemeModel; +class SortProxyModel; +class CursorTheme; + +class ThemePage : public QWidget, private Ui::ThemePage +{ + Q_OBJECT + + public: + ThemePage(QWidget* parent = 0); + ~ThemePage(); + + // Called by the KCM + void save(); + void load(); + void defaults(); + + static bool haveXfixes(); + + Q_SIGNALS: + void changed(bool); + + private Q_SLOTS: + void selectionChanged(); + /** Updates the preview. If the size has changed, it also emits changed() */ + void sizeChanged(); + /** Sets #preferredSize to the item that is currently selected in sizeComboBox. + If none is selected, it is set to 0. */ + void preferredSizeChanged(); + /** Updates the size combo box. It loads the size list of the selected cursor + theme with the corresponding icons and chooses an appropriate entry. It + enables the combo box and the label if the theme provides more than one + size, otherwise it disables it. If the size setting is looked in kiosk + mode, it stays always disabled. */ + void updateSizeComboBox(); + void getNewClicked(); + void installClicked(); + void removeClicked(); + + private: + /** @returns 0 if in the UI "automatic size" is selected, otherwise + returns the custom size. */ + int selectedSize() const; + /** Holds the last size that was choosen by the user. Example: The user chooses + theme1 which provides the sizes 24 and 36. He chooses 36. preferredSize gets + set to 36. Now, he switchs to theme2 which provides the sizes 30 and 40. + preferredSize still is 36, so the UI will default to 40, which is next to 36. + Now, he chooses theme3 which provides the sizes 34 and 44. preferredSize is + still 36, so the UI defaults to 34. Now the user changes manually to 44. This + will also change preferredSize. */ + int preferredSize; + void updatePreview(); + QModelIndex selectedIndex() const; + bool installThemes(const QString &file); + /** Applies a given theme, using XFixes, XCursor and KGlobalSettings. + @param theme The cursor theme to be applied. It is save to pass 0 here + (will result in \e false as return value). + @param size The size hint that is used to select the cursor size. + @returns If the changes could be applied. Will return \e false if \e theme is + 0 or if the XFixes and XCursor libraries aren't available in the required + version, otherwise returns \e true. */ + bool applyTheme(const CursorTheme *theme, const int size); + bool iconsIsWritable() const; + + CursorThemeModel *model; + SortProxyModel *proxy; + + int appliedSize; + // This index refers to the CursorThemeModel, not the proxy or the view + QPersistentModelIndex appliedIndex; +}; + +#endif // THEMEPAGE_H diff --git a/kcms/input/xcursor/themepage.ui b/kcms/input/xcursor/themepage.ui new file mode 100644 index 0000000000..be73663816 --- /dev/null +++ b/kcms/input/xcursor/themepage.ui @@ -0,0 +1,120 @@ + + + ThemePage + + + + 0 + 0 + 541 + 360 + + + + + + + Select the cursor theme you want to use (hover preview to test cursor): + + + + + + + + 0 + 0 + + + + + 0 + 48 + + + + + + + + + 0 + 1 + + + + true + + + QAbstractItemView::ScrollPerPixel + + + + + + + Get new color schemes from the Internet + + + Get New Theme... + + + + + + + Install From File... + + + + + + + Remove Theme + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + + 0 + 0 + + + + + + + + Size: + + + + + + + + KPushButton + QPushButton +
    kpushbutton.h
    +
    + + PreviewWidget + QWidget +
    previewwidget.h
    + 1 +
    +
    + + +
    diff --git a/kcms/input/xcursor/xcursor.knsrc b/kcms/input/xcursor/xcursor.knsrc new file mode 100644 index 0000000000..27f5b7659e --- /dev/null +++ b/kcms/input/xcursor/xcursor.knsrc @@ -0,0 +1,6 @@ +[KNewStuff3] +ProvidersUrl=http://download.kde.org/ocs/providers.xml +Categories=X11 Mouse Theme +InstallPath=.icons +Uncompress=archive + diff --git a/kcms/input/xcursor/xcursortheme.cpp b/kcms/input/xcursor/xcursortheme.cpp new file mode 100644 index 0000000000..e80ea1e365 --- /dev/null +++ b/kcms/input/xcursor/xcursortheme.cpp @@ -0,0 +1,229 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published + * by the Free Software Foundation. + * + * 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 +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "xcursortheme.h" + + +// Static variable holding alternative names for some cursors +QHash XCursorTheme::alternatives; + +XCursorTheme::XCursorTheme(const QDir &themeDir) + : CursorTheme(themeDir.dirName()) +{ + // Directory information + setName(themeDir.dirName()); + setPath(themeDir.path()); + setIsWritable(QFileInfo(themeDir.path()).isWritable()); // ### perhaps this shouldn't be cached + + if (themeDir.exists("index.theme")) + parseIndexFile(); + + QString cursorFile = path() + "/cursors/left_ptr"; + QList sizeList; + XcursorImages *images = XcursorFilenameLoadAllImages(qPrintable(cursorFile)); + if (images) + { + for (int i = 0; i < images->nimage; ++i) + { + if (!sizeList.contains(images->images[i]->size)) + sizeList.append(images->images[i]->size); + }; + XcursorImagesDestroy(images); + qSort(sizeList.begin(), sizeList.end()); + m_availableSizes = sizeList; + }; + if (!sizeList.isEmpty()) + { + QString sizeListString = QString::number(sizeList.takeFirst()); + while (!sizeList.isEmpty()) + { + sizeListString.append(", "); + sizeListString.append(QString::number(sizeList.takeFirst())); + }; + QString tempString = i18nc( + "@info/plain The argument is the list of available sizes (in pixel). Example: " + "'Available sizes: 24' or 'Available sizes: 24, 36, 48'", + "(Available sizes: %1)", + sizeListString); + if (m_description.isEmpty()) + m_description = tempString; + else + m_description = m_description + ' ' + tempString; + }; +} + + +void XCursorTheme::parseIndexFile() +{ + KConfig config(path() + "/index.theme", KConfig::NoGlobals); + KConfigGroup cg(&config, "Icon Theme"); + + m_title = cg.readEntry("Name", m_title); + m_description = cg.readEntry("Comment", m_description); + m_sample = cg.readEntry("Example", m_sample); + m_hidden = cg.readEntry("Hidden", false); + m_inherits = cg.readEntry("Inherits", QStringList()); +} + + +QString XCursorTheme::findAlternative(const QString &name) const +{ + if (alternatives.isEmpty()) + { + alternatives.reserve(18); + + // Qt uses non-standard names for some core cursors. + // If Xcursor fails to load the cursor, Qt creates it with the correct name using the + // core protcol instead (which in turn calls Xcursor). We emulate that process here. + // Note that there's a core cursor called cross, but it's not the one Qt expects. + alternatives.insert("cross", "crosshair"); + alternatives.insert("up_arrow", "center_ptr"); + alternatives.insert("wait", "watch"); + alternatives.insert("ibeam", "xterm"); + alternatives.insert("size_all", "fleur"); + alternatives.insert("pointing_hand", "hand2"); + + // Precomputed MD5 hashes for the hardcoded bitmap cursors in Qt and KDE. + // Note that the MD5 hash for left_ptr_watch is for the KDE version of that cursor. + alternatives.insert("size_ver", "00008160000006810000408080010102"); + alternatives.insert("size_hor", "028006030e0e7ebffc7f7070c0600140"); + alternatives.insert("size_bdiag", "fcf1c3c7cd4491d801f1e1c78f100000"); + alternatives.insert("size_fdiag", "c7088f0f3e6c8088236ef8e1e3e70000"); + alternatives.insert("whats_this", "d9ce0ab605698f320427677b458ad60b"); + alternatives.insert("split_h", "14fef782d02440884392942c11205230"); + alternatives.insert("split_v", "2870a09082c103050810ffdffffe0204"); + alternatives.insert("forbidden", "03b6e0fcb3499374a867c041f52298f0"); + alternatives.insert("left_ptr_watch", "3ecb610c1bf2410f44200f48c40d3599"); + alternatives.insert("hand2", "e29285e634086352946a0e7090d73106"); + alternatives.insert("openhand", "9141b49c8149039304290b508d208c40"); + alternatives.insert("closedhand", "05e88622050804100c20044008402080"); + } + + return alternatives.value(name, QString()); +} + + +XcursorImage *XCursorTheme::xcLoadImage(const QString &image, int size) const +{ + QByteArray cursorName = QFile::encodeName(image); + QByteArray themeName = QFile::encodeName(name()); + + return XcursorLibraryLoadImage(cursorName, themeName, size); +} + + +XcursorImages *XCursorTheme::xcLoadImages(const QString &image, int size) const +{ + QByteArray cursorName = QFile::encodeName(image); + QByteArray themeName = QFile::encodeName(name()); + + return XcursorLibraryLoadImages(cursorName, themeName, size); +} + + +int XCursorTheme::autodetectCursorSize() const +{ + /* This code is basically borrowed from display.c of the XCursor library + We can't use "int XcursorGetDefaultSize(Display *dpy)" because if + previously the cursor size was set to a custom value, it would return + this custom value. */ + int size = 0; + int dpi = 0; + Display *dpy = QX11Info::display(); + // The string "v" is owned and will be destroyed by Xlib + char *v = XGetDefault(dpy, "Xft", "dpi"); + if (v) + dpi = atoi(v); + if (dpi) + size = dpi * 16 / 72; + if (size == 0) + { + int dim; + if (DisplayHeight(dpy, DefaultScreen(dpy)) < + DisplayWidth(dpy, DefaultScreen(dpy))) + { + dim = DisplayHeight(dpy, DefaultScreen(dpy)); + } else { + dim = DisplayWidth(dpy, DefaultScreen(dpy)); + }; + size = dim / 48; + } + return size; +} + +qulonglong XCursorTheme::loadCursor(const QString &name, int size) const +{ + if (size <= 0) + size = autodetectCursorSize(); + + // Load the cursor images + XcursorImages *images = xcLoadImages(name, size); + + if (!images) + images = xcLoadImages(findAlternative(name), size); + + if (!images) + return None; + + // Create the cursor + Cursor handle = XcursorImagesLoadCursor(QX11Info::display(), images); + XcursorImagesDestroy(images); + + setCursorName(handle, name); + return handle; +} + + +QImage XCursorTheme::loadImage(const QString &name, int size) const +{ + if (size <= 0) + size = autodetectCursorSize(); + + // Load the image + XcursorImage *xcimage = xcLoadImage(name, size); + + if (!xcimage) + xcimage = xcLoadImage(findAlternative(name), size); + + if (!xcimage) { + return QImage(); + } + + // Convert the XcursorImage to a QImage, and auto-crop it + QImage image((uchar *)xcimage->pixels, xcimage->width, xcimage->height, + QImage::Format_ARGB32_Premultiplied ); + + image = autoCropImage(image); + XcursorImageDestroy(xcimage); + + return image; +} + diff --git a/kcms/input/xcursor/xcursortheme.h b/kcms/input/xcursor/xcursortheme.h new file mode 100644 index 0000000000..c05c8e0abf --- /dev/null +++ b/kcms/input/xcursor/xcursortheme.h @@ -0,0 +1,71 @@ +/* + * Copyright © 2006-2007 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 or at your option version 3 as published by + * the Free Software Foundation. + * + * 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 XCURSORTHEME_H +#define XCURSORTHEME_H + +#include + +#include "cursortheme.h" + +class QDir; + +struct _XcursorImage; +struct _XcursorImages; + +typedef _XcursorImage XcursorImage; +typedef _XcursorImages XcursorImages; + +/** + * The XCursorTheme class is a CursorTheme implementation for Xcursor themes. + */ +class XCursorTheme : public CursorTheme +{ + public: + /** + * Initializes itself from the @p dir information, and parses the + * index.theme file if the dir has one. + */ + XCursorTheme(const QDir &dir); + virtual ~XCursorTheme() {} + + const QStringList inherits() const { return m_inherits; } + QImage loadImage(const QString &name, int size = 0) const; + qulonglong loadCursor(const QString &name, int size = 0) const; + + protected: + XCursorTheme(const QString &title, const QString &desc) + : CursorTheme(title, desc) {} + void setInherits(const QStringList &val) { m_inherits = val; } + + private: + XcursorImage *xcLoadImage(const QString &name, int size) const; + XcursorImages *xcLoadImages(const QString &name, int size) const; + void parseIndexFile(); + QString findAlternative(const QString &name) const; + /** Returns the size that the XCursor library would use if no + cursor size is given. This depends mainly on Xft.dpi. */ + int autodetectCursorSize() const; + + QStringList m_inherits; + static QHash alternatives; +}; + +#endif // XCURSORTHEME_H + diff --git a/kcms/keyboard/CMakeLists.txt b/kcms/keyboard/CMakeLists.txt new file mode 100644 index 0000000000..73492b478d --- /dev/null +++ b/kcms/keyboard/CMakeLists.txt @@ -0,0 +1,177 @@ +set(CMAKE_REQUIRED_LIBRARIES -lXi) +check_function_exists(_XiGetDevicePresenceNotifyEvent XiGetDevicePresenceNotifyEvent_EXISTS) + +if( X11_Xinput_FOUND AND XiGetDevicePresenceNotifyEvent_EXISTS ) + set(XiGetDevicePresence_FOUND 1) + add_definitions(-DHAVE_XINPUT_AND_DEVICE_NOTIFY=1) +else() + message(STATUS "_XiGetDevicePresenceNotifyEvent is not found, libXi version 1.2.0 or later is required to keep layouts with keyboard hotplugging") +endif() + + + +### kded daemon ### + +set( kded_keyboard_SRCS + keyboard_daemon.cpp + layout_memory.cpp + layout_memory_persister.cpp + x11_helper.cpp +# xinput_helper.cpp + xkb_helper.cpp + keyboard_config.cpp + keyboard_hardware.cpp + numlockx.c + bindings.cpp +# next are temporary for sys tray UI + layout_tray_icon.cpp + layouts_menu.cpp + flags.cpp + xkb_rules.cpp +) + +add_library(kded_keyboard MODULE ${kded_keyboard_SRCS}) + +target_link_libraries(kded_keyboard + Qt5::Concurrent + Qt5::Widgets + Qt5::X11Extras + Qt5::Xml + KF5::ConfigCore + KF5::CoreAddons + KF5::DBusAddons + KF5::GlobalAccel + KF5::I18n + KF5::Notifications + KF5::Service + KF5::WindowSystem + KF5::Plasma + KF5::XmlGui + KF5::KDE4Support + ${X11_LIBRARIES} + ${X11_Xkbfile_LIB} + ) + +if(X11_XTest_FOUND) + target_link_libraries(kded_keyboard ${X11_XTest_LIB}) +endif() + +if(XiGetDevicePresence_FOUND) + target_link_libraries(kded_keyboard ${X11_Xinput_LIB}) +endif() + +install( TARGETS kded_keyboard DESTINATION ${PLUGIN_INSTALL_DIR} ) +install( FILES keyboard.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded ) + + +### plasma applet ### +# +# set( plasma_applet_keyboard_SRCS +# keyboard_applet.cpp +# flags.cpp +# keyboard_config.cpp +# xkb_rules.cpp +# x11_helper.cpp +# xkb_helper.cpp +# layouts_menu.cpp +# ) +# +# add_library(plasma_applet_keyboard MODULE ${plasma_applet_keyboard_SRCS}) +# +# target_link_libraries(plasma_applet_keyboard +# KF5::Plasma ${KDE4_KDEUI_LIBS} Qt5::Xml ${X11_Xkbfile_LIB} ${X11_LIBRARIES} +# ${text_paint_LIB} +# ) +# +# install( TARGETS plasma_applet_keyboard DESTINATION ${PLUGIN_INSTALL_DIR} ) +# install( FILES plasma_applet_keyboard.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +# +# +### widget lib ### + +set( keyboard_layout_widget_SRCS + layout_widget.cpp + keyboard_config.cpp + flags.cpp + x11_helper.cpp + xkb_helper.cpp +) + +# MODULE? +add_library(keyboard_layout_widget MODULE ${keyboard_layout_widget_SRCS}) + +target_link_libraries(keyboard_layout_widget + Qt5::X11Extras + Qt5::Xml + KF5::I18n + KF5::Service + KF5::Plasma + KF5::KDE4Support + ${X11_LIBRARIES} + ${X11_Xkbfile_LIB} +) + +install( TARGETS keyboard_layout_widget DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +### kcm keyboard ### +include_directories("preview") + +set(kcm_keyboard_PART_SRCS + kcm_keyboard.cpp + kcm_keyboard_widget.cpp + kcm_view_models.cpp + kcm_add_layout_dialog.cpp + keyboard_config.cpp + x11_helper.cpp + xkb_helper.cpp + xkb_rules.cpp + flags.cpp + iso_codes.cpp + kcmmisc.cpp + bindings.cpp + preview/keyaliases.cpp + preview/keyboardlayout.cpp + preview/keyboardpainter.cpp + preview/keysymbols.cpp + preview/keysymhelper.cpp + preview/kbpreviewframe.cpp + preview/keysym2ucs.cpp +) + + +qt5_wrap_ui(kcm_keyboard_PART_SRCS kcm_keyboard.ui kcm_add_layout_dialog.ui kcmmiscwidget.ui) + +add_library(kcm_keyboard MODULE ${kcm_keyboard_PART_SRCS}) + +target_link_libraries(kcm_keyboard + Qt5::Concurrent + Qt5::Widgets + Qt5::X11Extras + Qt5::Xml + KF5::KCMUtils + KF5::GlobalAccel + KF5::I18n + KF5::KIOCore + KF5::KIOWidgets + KF5::WindowSystem + KF5::Plasma + KF5::XmlGui + KF5::KDE4Support + ${X11_Xkbfile_LIB} + ${X11_LIBRARIES} + ${text_paint_LIB} +) + +install(TARGETS kcm_keyboard DESTINATION ${PLUGIN_INSTALL_DIR} ) + +install( FILES kcm_keyboard.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + +# Images + +add_subdirectory( pics ) + + +# Unit tests + +# add_subdirectory( tests ) diff --git a/kcms/keyboard/Messages.sh b/kcms/keyboard/Messages.sh new file mode 100755 index 0000000000..8d5275220b --- /dev/null +++ b/kcms/keyboard/Messages.sh @@ -0,0 +1,5 @@ +#! /usr/bin/env bash +$EXTRACTRC kcm*.ui >> rc.cpp +$XGETTEXT rc.cpp kcmmisc.cpp preview/*.cpp -o $podir/kcmkeyboard.pot +$XGETTEXT kcm_*.cpp keyboard_*.cpp layout_*.cpp flags.cpp layouts_menu.cpp bindings.cpp -o $podir/kxkb.pot +rm -f rc.cpp diff --git a/kcms/keyboard/README b/kcms/keyboard/README new file mode 100644 index 0000000000..25c50b47f6 --- /dev/null +++ b/kcms/keyboard/README @@ -0,0 +1,44 @@ +This is new project to replace keyboard (kcmmisc) and kxkb +to manage keyboard harware configuration and layouts. + +Components: + +kcm_init: +* no kcm_init - all initialization (including after keyboard hot-plug) is done by kded daemon + +Keyboard daemon: +* configures keyboard layouts on start +* provides DBUS API "org.kde.KXKB/kxkb" +* listens to window/desktop switching if layout switch mode is not global +* listens to new keyboard devices and reinitializes keyboard layouts and hardware settings +* listens to Global KDE Shortcut to switch layouts +* listens to Global Shortcut settings change +* listens to keyboard configuration changes +* provides systray icon for layout + +Keyboard applet: +* displays current layout with text and (optionally flag) +* allows to toggle layouts by click or set them with context menu + +Layout widget: +* displays current layout with text embedded in another widget (e.g. lock dialog) +* currently only short text (no flag or long text) +* dynamically loaded as a plugin + +KCM Module: +* allows to configure keyboard hardware, layouts and xkb options (advanced) + +Advantages (over old code): +* One UI module to configure keyboard layouts and hardware +* Allows to configure keyboard model/xkb options without configuring layouts +* Less cluttered layout configuration control (add layout is separate) +* Layout control/DBus interface is separate from the indicator +* Does not require libxklvier +* Takes language names from iso-codes project +* Takes country names/translations from xkeyboard-config project +* Information about current layouts is always taken from X server, so should be more robust +* Cleaner code (rewritten from scratch) +* Due to many points above should start faster (though no benchmarks performed) + +New features: +* Allow selection of keyboard layout by language diff --git a/kcms/keyboard/TODO b/kcms/keyboard/TODO new file mode 100644 index 0000000000..2e58efb289 --- /dev/null +++ b/kcms/keyboard/TODO @@ -0,0 +1,37 @@ +Tests: +* tests + +Core: +* better handling when layouts set manually and not present in config + +KCM UI: +* use listboxes instead of combos in add layout dialog +* allow multiple layouts to be added in same dialog? + +KCM UI cleanup: +* layouts, sizes, alignment etc in kcm + +plasma applet: + +kxkb part: +* tooltip (currently does not work in lockdlg for some reason) + +tray icon: + +Code cleanup: +* rules, iso_codes: + better error handling + +Improvement: +* remove XInput libs from plasma applet and layout widget (find a nicer way) +* optimize fetching groups and layouts (cache them) / fetch current group directly +* refactor/optimize/clean the code +* refactor client code for D-BUS API to use library instead? + +External improvements: +* Add KSharedConfig::configChanged() signal +* make iso-codes external package +* make flags external package + +Documentation: +* update documentation for keyboard module diff --git a/kcms/keyboard/bindings.cpp b/kcms/keyboard/bindings.cpp new file mode 100644 index 0000000000..21541e095d --- /dev/null +++ b/kcms/keyboard/bindings.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "bindings.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "x11_helper.h" +#include "flags.h" + + +static const char* actionName = I18N_NOOP("Switch to Next Keyboard Layout"); +static const char* COMPONENT_NAME = I18N_NOOP("KDE Keyboard Layout Switcher"); + + +KeyboardLayoutActionCollection::KeyboardLayoutActionCollection(QObject* parent, bool configAction_): + KActionCollection(parent, COMPONENT_NAME), + configAction(configAction_) +{ + QAction* toggleAction = addAction( actionName ); + toggleAction->setText( i18n(actionName) ); + KGlobalAccel::self()->setShortcut(toggleAction, + QList() << QKeySequence(Qt::ALT+Qt::CTRL+Qt::Key_K), + KGlobalAccel::NoAutoloading); + if( configAction ) { + toggleAction->setProperty("isConfigurationAction", true); + } +} + +KeyboardLayoutActionCollection::~KeyboardLayoutActionCollection() +{ + clear(); +} + +QAction* KeyboardLayoutActionCollection::getToggeAction() +{ + return action(0); +} + +QAction* KeyboardLayoutActionCollection::createLayoutShortcutActon(const LayoutUnit& layoutUnit, const Rules* rules, bool autoload) +{ + QString longLayoutName = Flags::getLongText( layoutUnit, rules ); + QString actionName = "Switch keyboard layout to "; + actionName += longLayoutName; + QAction* action = addAction( actionName ); + action->setText( i18n("Switch keyboard layout to %1", longLayoutName) ); + KGlobalAccel::GlobalShortcutLoading loading = autoload ? KGlobalAccel::Autoloading : KGlobalAccel::NoAutoloading; + QList shortcuts; + if (!autoload) { + shortcuts << layoutUnit.getShortcut(); + } + KGlobalAccel::self()->setShortcut(action, shortcuts, loading); + action->setData(layoutUnit.toString()); + if( configAction ) { + action->setProperty("isConfigurationAction", true); + } + return action; +} + +void KeyboardLayoutActionCollection::setToggleShortcut(const QKeySequence& keySequence) +{ + KGlobalAccel::self()->setShortcut(getToggeAction(), QList() << keySequence, KGlobalAccel::NoAutoloading); +} + +//KAction* KeyboardLayoutActionCollection::setShortcut(LayoutUnit& layoutUnit, const QKeySequence& keySequence, const Rules* rules) +//{ +// KAction* action = getAction(layoutUnit); +// if( action == NULL && ! keySequence.isEmpty() ) { +// action = createLayoutShortcutActon(layoutUnit, rules, false); +// } +// else if( action != NULL && keySequence.isEmpty() ){ +//// action->setGlobalShortcut(KShortcut(keySequence), KAction::ActiveShortcut, KAction::NoAutoloading); // do we need this? +// removeAction(action); +// action = NULL; +// } +//// if( configAction ) { +//// layoutUnit.setShortcut(keySequence); // shortcut was restored +//// } +// return action; +//} + +void KeyboardLayoutActionCollection::setLayoutShortcuts(QList& layoutUnits, const Rules* rules) +{ + for (QList::iterator i = layoutUnits.begin(); i != layoutUnits.end(); ++i) { + LayoutUnit& layoutUnit = *i; + if( ! layoutUnit.getShortcut().isEmpty() ) { + createLayoutShortcutActon(layoutUnit, rules, false); + } + } + kDebug() << "Cleaning component shortcuts on save" << KGlobalAccel::cleanComponent(COMPONENT_NAME); +} + +void KeyboardLayoutActionCollection::loadLayoutShortcuts(QList& layoutUnits, const Rules* rules) +{ + for (QList::iterator i = layoutUnits.begin(); i != layoutUnits.end(); ++i) { + LayoutUnit& layoutUnit = *i; + QAction* action = createLayoutShortcutActon(layoutUnit, rules, true); + const auto shortcut = KGlobalAccel::self()->shortcut(action); + if( ! shortcut.isEmpty() ) { + kDebug() << "Restored shortcut for" << layoutUnit.toString() << shortcut.first(); + layoutUnit.setShortcut(shortcut.first()); + } + else { + kDebug() << "Skipping empty shortcut for" << layoutUnit.toString(); + removeAction(action); + } + } + kDebug() << "Cleaning component shortcuts on load" << KGlobalAccel::cleanComponent(COMPONENT_NAME); +} + +//KAction* KeyboardLayoutActionCollection::getAction(const LayoutUnit& layoutUnit) +//{ +// for(int i=1; idata() == layoutUnit.toString() ) +// return static_cast(action(i)); +// } +// return NULL; +//} + +void KeyboardLayoutActionCollection::resetLayoutShortcuts() +{ + for(int i=1; isetShortcut(action(i), QList(), KGlobalAccel::NoAutoloading); + KGlobalAccel::self()->setDefaultShortcut(action(i), QList(), KGlobalAccel::NoAutoloading); + } +} diff --git a/kcms/keyboard/bindings.h b/kcms/keyboard/bindings.h new file mode 100644 index 0000000000..c5764556d9 --- /dev/null +++ b/kcms/keyboard/bindings.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 BINDINGS_H_ +#define BINDINGS_H_ + +#include + + +//class QObject; +class Rules; +class LayoutUnit; +template class QList; + + +class KeyboardLayoutActionCollection : public KActionCollection { +public: + KeyboardLayoutActionCollection(QObject* parent, bool configAction); + virtual ~KeyboardLayoutActionCollection(); + + QAction* getToggeAction(); +// KAction* getAction(const LayoutUnit& layoutUnit); + QAction* createLayoutShortcutActon(const LayoutUnit& layoutUnit, const Rules* rules, bool autoload); +// KAction* setShortcut(LayoutUnit& layoutUnit, const QKeySequence& keySequence, const Rules* rules); + void setLayoutShortcuts(QList& layoutUnits, const Rules* rules); + void setToggleShortcut(const QKeySequence& keySequence); + void loadLayoutShortcuts(QList& layoutUnits, const Rules* rules); + void resetLayoutShortcuts(); + +private: + bool configAction; +}; + +//KActionCollection* createGlobalActionCollection(QObject *parent, KAction** mainAction); +//KAction* createLayoutShortcutActon(KActionCollection* actionCollection, const LayoutUnit& layoutUnit, const Rules* rules); + +#endif /* BINDINGS_H_ */ diff --git a/kcms/keyboard/flags.cpp b/kcms/keyboard/flags.cpp new file mode 100644 index 0000000000..461accfcbc --- /dev/null +++ b/kcms/keyboard/flags.cpp @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "flags.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "x11_helper.h" + +//for text handling +#include "keyboard_config.h" +#include "xkb_rules.h" + + +static const int FLAG_MAX_WIDTH = 21; +static const int FLAG_MAX_HEIGHT = 14; +static const char flagTemplate[] = "l10n/%1/flag.png"; + +Flags::Flags(): + svg(NULL) +{ + transparentPixmap = new QPixmap(FLAG_MAX_WIDTH, FLAG_MAX_HEIGHT); + transparentPixmap->fill(Qt::transparent); +} + +Flags::~Flags() +{ + if( svg != NULL ) { + disconnect(svg, SIGNAL(repaintNeeded()), this, SLOT(themeChanged())); + delete svg; + } + delete transparentPixmap; +} + +const QIcon Flags::getIcon(const QString& layout) +{ + if( ! iconMap.contains(layout) ) { + iconMap[ layout ] = createIcon(layout); + } + return iconMap[ layout ]; +} + +QIcon Flags::createIcon(const QString& layout) +{ + QIcon icon; + if( ! layout.isEmpty() ) { + if( layout == "epo" ) { + QString file = KStandardDirs::locate("data", "kcmkeyboard/pics/epo.png"); + icon.addFile(file); + } + else { + QString countryCode = getCountryFromLayoutName( layout ); + if( ! countryCode.isEmpty() ) { + QString file = KStandardDirs::locate("locale", QString(flagTemplate).arg(countryCode)); + // kDebug() << "Creating icon for" << layout << "with" << file; + icon.addFile(file); + } + } + } + return icon; +} + + +//static +//const QStringList NON_COUNTRY_LAYOUTS = QString("ara,brai,epo,latam,mao").split(","); + +QString Flags::getCountryFromLayoutName(const QString& layout) const +{ + QString countryCode = layout; + + if( countryCode == "nec_vndr/jp" ) + return "jp"; + +// if( NON_COUNTRY_LAYOUTS.contain(layout) ) + if( countryCode.length() > 2 ) + return ""; + + return countryCode; +} + +//TODO: move this to some other class? + +QString Flags::getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) +{ + if( layoutUnit.isEmpty() ) + return QString("--"); + + QString layoutText = layoutUnit.layout; + + foreach(const LayoutUnit& lu, keyboardConfig.layouts) { + if( layoutUnit.layout == lu.layout && layoutUnit.variant == lu.variant ) { + layoutText = lu.getDisplayName(); + break; + } + } + +//TODO: good autolabel +// if( layoutText == layoutUnit.layout && layoutUnit.getDisplayName() != layoutUnit.layout ) { +// layoutText = layoutUnit.getDisplayName(); +// } + + return layoutText; +} + +QString Flags::getFullText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig, const Rules* rules) +{ + QString shortText = Flags::getShortText(layoutUnit, keyboardConfig); + QString longText = Flags::getLongText(layoutUnit, rules); + return i18nc("short layout label - full layout name", "%1 - %2", shortText, longText); +} + +static QString getDisplayText(const QString& layout, const QString& variant, const Rules* rules) +{ + if( variant.isEmpty() ) + return layout; + if( rules == NULL || rules->version == "1.0" ) + return i18nc("layout - variant", "%1 - %2", layout, variant); + return variant; +} + +QString Flags::getLongText(const LayoutUnit& layoutUnit, const Rules* rules) +{ + if( rules == NULL ) { + return getDisplayText(layoutUnit.layout, layoutUnit.variant, rules); + } + + QString layoutText = layoutUnit.layout; + const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); + if( layoutInfo != NULL ) { + layoutText = layoutInfo->description; + + if( ! layoutUnit.variant.isEmpty() ) { + const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant); + QString variantText = variantInfo != NULL ? variantInfo->description : layoutUnit.variant; + + layoutText = getDisplayText(layoutText, variantText, rules); + } + } + + return layoutText; +} + +static +QString getPixmapKey(const KeyboardConfig& keyboardConfig) +{ + switch(keyboardConfig.indicatorType) { + case KeyboardConfig::SHOW_FLAG: + return "_fl"; + case KeyboardConfig::SHOW_LABEL_ON_FLAG: + return "_bt"; + case KeyboardConfig::SHOW_LABEL: + return "_lb"; + } + return "_"; // should not happen +} + +void Flags::drawLabel(QPainter& painter, const QString& layoutText, bool flagShown) +{ + QFont font = painter.font(); + + QRect rect = painter.window(); +// int fontSize = layoutText.length() == 2 +// ? height * 7 / 10 +// : height * 5 / 10; + + int fontSize = rect.height();// * 7 /10; + + font.setPixelSize(fontSize); + font.setWeight(QFont::DemiBold); + + QFontMetrics fm = painter.fontMetrics(); + int width = fm.width(layoutText); + + if( width > rect.width() * 2 / 3 ) { + fontSize = round( (double)fontSize * ((double)rect.width()*2/3) / width ); + } + + int smallestReadableSize = KGlobalSettings::smallestReadableFont().pixelSize(); + if( fontSize < smallestReadableSize ) { + fontSize = smallestReadableSize; + } + font.setPixelSize(fontSize); + +#ifdef DONT_USE_PLASMA + painter.setFont(font); + painter.setPen(Qt::white); + painter.drawText(QRect(rect).adust(1,1,0,0), Qt::AlignCenter | Qt::AlignHCenter, layoutText); + painter.setPen(Qt::black); + painter.drawText(rect, Qt::AlignCenter | Qt::AlignHCenter, layoutText); +#else + // we init svg so that we get notification about theme change + getSvg(); + + Plasma::Theme theme; + QColor textColor = flagShown ? Qt::black : theme.color(Plasma::Theme::TextColor); + QPoint offset = QPoint(0, 0); + + auto shadowText = [&font, &textColor, &offset](QString text) { + //don't try to paint stuff on a future null pixmap because the text is empty + if (text.isEmpty()) { + return QPixmap(); + } + + // Draw text + QFontMetrics fm(font); + QRect textRect = fm.boundingRect(text); + QPixmap textPixmap(textRect.width(), fm.height()); + textPixmap.fill(Qt::transparent); + QPainter p(&textPixmap); + p.setPen(textColor); + p.setFont(font); + // FIXME: the center alignment here is odd: the rect should be the size needed by + // the text, but for some fonts and configurations this is off by a pixel or so + // and "centering" the text painting 'fixes' that. Need to research why + // this is the case and determine if we should be painting it differently here, + // doing soething different with the boundingRect call or if it's a problem + // in Qt itself + p.drawText(textPixmap.rect(), Qt::AlignCenter, text); + p.end(); + + return textPixmap; + }; + + // QPixmap pixmap = Plasma::PaintUtils::texturedText(layoutText, font, svg); + QPixmap labelPixmap = shadowText(layoutText); + + int y = round((rect.height() - labelPixmap.height()) / 2.0); + int x = round((rect.width() - labelPixmap.width()) / 2.0); + painter.drawPixmap(QPoint(x, y), labelPixmap); +#endif +} + +const QIcon Flags::getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) +{ + QString keySuffix(getPixmapKey(keyboardConfig)); + QString key(layoutUnit.toString() + keySuffix); + if( iconOrTextMap.contains(key) ) { + return iconOrTextMap[ key ]; + } + + if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_FLAG ) { + QIcon icon = getIcon(layoutUnit.layout); + if( ! icon.isNull() ) { + iconOrTextMap[ key ] = icon; + return icon; + } + } + + QString layoutText = Flags::getShortText(layoutUnit, keyboardConfig); + + const QSize TRAY_ICON_SIZE(21, 14); + QPixmap pixmap = QPixmap(TRAY_ICON_SIZE); + pixmap.fill(Qt::transparent); + + QPainter painter(&pixmap); +// p.setRenderHint(QPainter::SmoothPixmapTransform); +// p.setRenderHint(QPainter::Antialiasing); + + if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG ) { + QIcon iconf = createIcon(layoutUnit.layout); + iconf.paint(&painter, painter.window(), Qt::AlignCenter); + } + + drawLabel(painter, layoutText, keyboardConfig.isFlagShown()); + + painter.end(); + + QIcon icon(pixmap); + iconOrTextMap[ key ] = icon; + + return icon; +} + +Plasma::Svg* Flags::getSvg() +{ + if( svg == NULL ) { + svg = new Plasma::Svg; + svg->setImagePath("widgets/labeltexture"); + svg->setContainsMultipleImages(true); + connect(svg, SIGNAL(repaintNeeded()), this, SLOT(themeChanged())); + } + return svg; +} + +void Flags::themeChanged() +{ +// kDebug() << "Theme changed, new text color" << Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor); + clearCache(); + emit pixmapChanged(); +} + +void Flags::clearCache() +{ +// kDebug() << "Clearing flag pixmap cache"; + iconOrTextMap.clear(); +} diff --git a/kcms/keyboard/flags.h b/kcms/keyboard/flags.h new file mode 100644 index 0000000000..06ec831b90 --- /dev/null +++ b/kcms/keyboard/flags.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 FLAGS_H_ +#define FLAGS_H_ + +#include +#include +#include + +class QPixmap; +class QIcon; +class LayoutUnit; +class KeyboardConfig; +class Rules; +class QPainter; +namespace Plasma { + class Svg; +} + +class Flags : public QObject +{ + Q_OBJECT + +public: + Flags(); + virtual ~Flags(); + + const QIcon getIcon(const QString& layout); + const QIcon getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); + const QPixmap& getTransparentPixmap() const { return *transparentPixmap; } + + static QString getLongText(const LayoutUnit& layoutUnit, const Rules* rules); + static QString getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); + static QString getFullText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig, const Rules* rules); + +public Q_SLOTS: + void themeChanged(); + void clearCache(); + +Q_SIGNALS: + void pixmapChanged(); + +private: + QIcon createIcon(const QString& layout); + QString getCountryFromLayoutName(const QString& fullLayoutName) const; + void drawLabel(QPainter& painter, const QString& layoutText, bool flagShown); + Plasma::Svg* getSvg(); + + QMap iconMap; + QMap iconOrTextMap; + QPixmap* transparentPixmap; + Plasma::Svg* svg; +}; + +#endif /* FLAGS_H_ */ diff --git a/kcms/keyboard/iso_codes.cpp b/kcms/keyboard/iso_codes.cpp new file mode 100644 index 0000000000..3e3b210b9f --- /dev/null +++ b/kcms/keyboard/iso_codes.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "iso_codes.h" + +#include +#include +#include + +#include + + +class IsoCodesPrivate { +public: + IsoCodesPrivate(const QString& isoCode_, const QString& isoCodesXmlDir_): + isoCode(isoCode_), + isoCodesXmlDir(isoCodesXmlDir_), + loaded(false) + {} + void buildIsoEntryList(); + + const QString isoCode; + const QString isoCodesXmlDir; + QList isoEntryList; + bool loaded; +}; + +class XmlHandler : public QXmlDefaultHandler +{ +public: + XmlHandler(const QString& isoCode_, QList& isoEntryList_): + isoCode(isoCode_), + qName("iso_"+isoCode+"_entry"), + isoEntryList(isoEntryList_) {} + + bool startElement(const QString &namespaceURI, const QString &localName, + const QString &qName, const QXmlAttributes &attributes); +// bool fatalError(const QXmlParseException &exception); +// QString errorString() const; + +private: + const QString isoCode; + const QString qName; + QList& isoEntryList; +}; + +bool XmlHandler::startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, + const QString &qName, const QXmlAttributes &attributes) +{ + if( qName == this->qName ) { + IsoCodeEntry entry; + for(int i=0; i IsoCodes::getEntryList() +{ + if( ! d->loaded ) { + d->buildIsoEntryList(); + } + return d->isoEntryList; +} + +//const char* IsoCodes::iso_639="639"; +const char* IsoCodes::iso_639_3="639_3"; +const char* IsoCodes::attr_name="name"; +//const char* IsoCodes::attr_iso_639_2B_code="iso_639_2B_code"; +//const char* IsoCodes::attr_iso_639_2T_code="iso_639_2T_code"; +//const char* IsoCodes::attr_iso_639_1_code="iso_639_1_code"; +const char* IsoCodes::attr_iso_639_3_id="id"; + +const IsoCodeEntry* IsoCodes::getEntry(const QString& attributeName, const QString& attributeValue) +{ + if( ! d->loaded ) { + d->buildIsoEntryList(); + } + for(QList::Iterator it = d->isoEntryList.begin(); it != d->isoEntryList.end(); ++it) { + const IsoCodeEntry* isoCodeEntry = &(*it); + if( isoCodeEntry->value(attributeName) == attributeValue ) + return isoCodeEntry; + } + return NULL; +} + +void IsoCodesPrivate::buildIsoEntryList() +{ + loaded = true; + + QFile file(QString("%1/iso_%2.xml").arg(isoCodesXmlDir, isoCode)); + if( !file.open(QFile::ReadOnly | QFile::Text) ) { + kError() << "Can't open the xml file" << file.fileName(); + return; + } + + XmlHandler xmlHandler(isoCode, isoEntryList); + + QXmlSimpleReader reader; + reader.setContentHandler(&xmlHandler); + reader.setErrorHandler(&xmlHandler); + + QXmlInputSource xmlInputSource(&file); + + if( ! reader.parse(xmlInputSource) ) { + kError() << "Failed to parse the xml file" << file.fileName(); + return; + } + + kDebug() << "Loaded" << isoEntryList.count() << ("iso entry definitions for iso"+isoCode) << "from" << file.fileName(); +} diff --git a/kcms/keyboard/iso_codes.h b/kcms/keyboard/iso_codes.h new file mode 100644 index 0000000000..6a337392e9 --- /dev/null +++ b/kcms/keyboard/iso_codes.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 ISO_CODES_H_ +#define ISO_CODES_H_ + +#include +#include +#include + + +/** + * Represents an item for iso-* standards which consists of attributes and their values + */ +struct IsoCodeEntry: public QMap +{ +}; + +class IsoCodesPrivate; + +/** + * Represents a set of codes for iso-* standards. + * Uses iso-codes project to read and localize the values. + */ +class IsoCodes +{ +public: +// static const char* iso_639; + static const char* iso_639_3; + + static const char* attr_name; +// static const char* attr_iso_639_2B_code; +// static const char* attr_iso_639_2T_code; +// static const char* attr_iso_639_1_code; + static const char* attr_iso_639_3_id; + + /** + * @param isoCode Code for iso standard, i.e. "639", for convenience there's iso_* constants defined + */ + explicit IsoCodes(const QString& isoCode, const QString& isoCodesXmlDir="/usr/share/xml/iso-codes"); + ~IsoCodes(); + + /** + * @return Returns the list of items for this iso-* standard + */ + QList getEntryList(); + /** + * @return Returns the item for which given attribute has specified value + */ + const IsoCodeEntry* getEntry(const QString& attributeName, const QString& attributeValue); + +private: + IsoCodesPrivate* const d; +}; + +#endif /* ISO_CODES_H_ */ diff --git a/kcms/keyboard/kcm_add_layout_dialog.cpp b/kcms/keyboard/kcm_add_layout_dialog.cpp new file mode 100644 index 0000000000..444da8eaf5 --- /dev/null +++ b/kcms/keyboard/kcm_add_layout_dialog.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "kcm_add_layout_dialog.h" +#include +#include + +#include "xkb_rules.h" +#include "flags.h" +#include "iso_codes.h" + +#include "ui_kcm_add_layout_dialog.h" + + +AddLayoutDialog::AddLayoutDialog(const Rules* rules_, Flags* flags_, bool showLabel, QWidget* parent): + QDialog(parent), + rules(rules_), + flags(flags_), + selectedLanguage("no_language") +{ + layoutDialogUi = new Ui_AddLayoutDialog(); + layoutDialogUi->setupUi(this); + + QSet languages; + foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { + QSet langs = QSet::fromList(layoutInfo->languages); + languages.unite( langs ); + } + IsoCodes isoCodes(IsoCodes::iso_639_3); + foreach(const QString& lang, languages) { + const IsoCodeEntry* isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_3_id, lang); +// const IsoCodeEntry* isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_2B_code, lang); +// if( isoCodeEntry == NULL ) { +// isoCodeEntry = isoCodes.getEntry(IsoCodes::attr_iso_639_2T_code, lang); +// } + QString name = isoCodeEntry != NULL ? i18n(isoCodeEntry->value(IsoCodes::attr_name).toUtf8()) : lang; + layoutDialogUi->languageComboBox->addItem(name, lang); + } + layoutDialogUi->languageComboBox->model()->sort(0); + layoutDialogUi->languageComboBox->insertItem(0, i18n("Any language"), ""); + layoutDialogUi->languageComboBox->setCurrentIndex(0); + + if( showLabel ) { + layoutDialogUi->labelEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH); + } + else { + layoutDialogUi->labelLabel->setVisible(false); + layoutDialogUi->labelEdit->setVisible(false); + } + + languageChanged(0); + connect(layoutDialogUi->languageComboBox, SIGNAL(activated(int)), this, SLOT(languageChanged(int))); + connect(layoutDialogUi->layoutComboBox, SIGNAL(activated(int)), this, SLOT(layoutChanged(int))); + connect(layoutDialogUi->prevbutton,SIGNAL(clicked()),this,SLOT(preview())); +} + +void AddLayoutDialog::languageChanged(int langIdx) +{ + QString lang = layoutDialogUi->languageComboBox->itemData(langIdx).toString(); + if( lang == selectedLanguage ) + return; + + QPixmap emptyPixmap(layoutDialogUi->layoutComboBox->iconSize()); + emptyPixmap.fill(Qt::transparent); + + layoutDialogUi->layoutComboBox->clear(); + int defaultIndex = -1; + int i = 0; + foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { + if( lang.isEmpty() || layoutInfo->isLanguageSupportedByLayout(lang) ) { + if( flags ) { + QIcon icon(flags->getIcon(layoutInfo->name)); + if( icon.isNull() ) { + icon = QIcon(emptyPixmap); // align text with no icons + } + layoutDialogUi->layoutComboBox->addItem(icon, layoutInfo->description, layoutInfo->name); + } + else { + layoutDialogUi->layoutComboBox->addItem(layoutInfo->description, layoutInfo->name); + } + + // try to guess best default layout selection for given language + if( ! lang.isEmpty() && defaultIndex == -1 && layoutInfo->isLanguageSupportedByDefaultVariant(lang) ) { + defaultIndex = i; + } + i++; + } + } + if( defaultIndex == -1 ) { + defaultIndex = 0; + } + + layoutDialogUi->layoutComboBox->model()->sort(0); + layoutDialogUi->layoutComboBox->setCurrentIndex(defaultIndex); + layoutChanged(defaultIndex); + + selectedLanguage = lang; +} + +void AddLayoutDialog::layoutChanged(int layoutIdx) +{ + QString layoutName = layoutDialogUi->layoutComboBox->itemData(layoutIdx).toString(); + if( layoutName == selectedLayout ) + return; + + QString lang = layoutDialogUi->languageComboBox->itemData(layoutDialogUi->languageComboBox->currentIndex()).toString(); + + layoutDialogUi->variantComboBox->clear(); + const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutName); + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + if( lang.isEmpty() || layoutInfo->isLanguageSupportedByVariant(variantInfo, lang) ) { + layoutDialogUi->variantComboBox->addItem(variantInfo->description, variantInfo->name); + } + } + + layoutDialogUi->variantComboBox->model()->sort(0); + + if( lang.isEmpty() || layoutInfo->isLanguageSupportedByDefaultVariant(lang) ) { + layoutDialogUi->variantComboBox->insertItem(0, i18nc("variant", "Default"), ""); + } + layoutDialogUi->variantComboBox->setCurrentIndex(0); + + layoutDialogUi->labelEdit->setText(layoutName); + + selectedLayout = layoutName; +} + +void AddLayoutDialog::accept() +{ + selectedLayoutUnit.layout = layoutDialogUi->layoutComboBox->itemData(layoutDialogUi->layoutComboBox->currentIndex()).toString(); + selectedLayoutUnit.variant = layoutDialogUi->variantComboBox->itemData(layoutDialogUi->variantComboBox->currentIndex()).toString(); + QString label = layoutDialogUi->labelEdit->text(); + if( label == selectedLayoutUnit.layout ) { + label = ""; + } + selectedLayoutUnit.setDisplayName( label ); + selectedLayoutUnit.setShortcut(layoutDialogUi->kkeysequencewidget->keySequence()); + QDialog::accept(); +} + + +void AddLayoutDialog::preview(){ + int index = layoutDialogUi->variantComboBox->currentIndex(); + QString variant = layoutDialogUi->variantComboBox->itemData(index).toString(); + KeyboardPainter* layoutPreview = new KeyboardPainter(); + layoutPreview->generateKeyboardLayout(selectedLayout, variant); + layoutPreview->setModal(true); + layoutPreview->exec(); + delete layoutPreview; +} diff --git a/kcms/keyboard/kcm_add_layout_dialog.h b/kcms/keyboard/kcm_add_layout_dialog.h new file mode 100644 index 0000000000..6b82271787 --- /dev/null +++ b/kcms/keyboard/kcm_add_layout_dialog.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KCM_ADD_LAYOUT_DIALOG_H_ +#define KCM_ADD_LAYOUT_DIALOG_H_ + +#include + +#include "keyboard_config.h" +#include "preview/keyboardpainter.h" + +class Rules; +class Flags; +class Ui_AddLayoutDialog; + +class AddLayoutDialog: public QDialog +{ + Q_OBJECT + +public: + AddLayoutDialog(const Rules* rules, Flags* flags, bool showLabel, QWidget* parent=NULL); + + LayoutUnit getSelectedLayoutUnit() { return selectedLayoutUnit; } + QString getvariant(QString variant); + void accept(); + +public Q_SLOTS: + void languageChanged(int langIdx); + void layoutChanged(int layoutIdx); + void preview(); + +private: + const Rules* rules; + Flags* flags; + Ui_AddLayoutDialog* layoutDialogUi; + QString selectedLanguage; + QString selectedLayout; + LayoutUnit selectedLayoutUnit; +}; + + +#endif /* KCM_ADD_LAYOUT_DIALOG_H_ */ diff --git a/kcms/keyboard/kcm_add_layout_dialog.ui b/kcms/keyboard/kcm_add_layout_dialog.ui new file mode 100644 index 0000000000..78304fbc1e --- /dev/null +++ b/kcms/keyboard/kcm_add_layout_dialog.ui @@ -0,0 +1,149 @@ + + + AddLayoutDialog + + + + 0 + 0 + 525 + 270 + + + + Add Layout + + + + + + + 0 + 0 + + + + + + + + Layout: + + + + + + + + 0 + 0 + + + + + + + + Shortcut: + + + + + + + Variant: + + + + + + + + + + Label: + + + + + + + Limit selection by language: + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + Preview + + + + + + + + KKeySequenceWidget + QWidget +
    kkeysequencewidget.h
    +
    +
    + + + + buttonBox + accepted() + AddLayoutDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddLayoutDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
    diff --git a/kcms/keyboard/kcm_keyboard.cpp b/kcms/keyboard/kcm_keyboard.cpp new file mode 100644 index 0000000000..30dc5fad2f --- /dev/null +++ b/kcms/keyboard/kcm_keyboard.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "kcm_keyboard.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +//#include + +#include "kcm_keyboard_widget.h" +#include "x11_helper.h" +#include "keyboard_config.h" +#include "xkb_rules.h" +#include "keyboard_dbus.h" + +#include "xkb_helper.h" + +//temp hack +#include "kcmmisc.h" + + +K_PLUGIN_FACTORY(KeyboardModuleFactory, registerPlugin();) +K_EXPORT_PLUGIN(KeyboardModuleFactory("kcmkeyboard")) + +KCMKeyboard::KCMKeyboard(QWidget *parent, const QVariantList &args) + : KCModule(parent/*, name*/) +{ + KAboutData *about = + new KAboutData("kcmkeyboard", QString(), i18n("KDE Keyboard Control Module"), + 0, QString(), KAboutData::License_GPL, + i18n("(c) 2010 Andriy Rysin")); + + setAboutData( about ); + setQuickHelp( i18n("

    Keyboard

    This control module can be used to configure keyboard" + " parameters and layouts.")); + + + rules = Rules::readRules(Rules::READ_EXTRAS); + + keyboardConfig = new KeyboardConfig(); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(KDialog::spacingHint()); + + widget = new KCMKeyboardWidget(rules, keyboardConfig, args, parent); + layout->addWidget(widget); + + connect(widget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); + + setButtons(Help|Default|Apply); +} + +KCMKeyboard::~KCMKeyboard() +{ + delete keyboardConfig; + delete rules; +} + +void KCMKeyboard::defaults() +{ + keyboardConfig->setDefaults(); + widget->updateUI(); + widget->getKcmMiscWidget()->defaults(); + emit changed(true); +} + +void KCMKeyboard::load() +{ + keyboardConfig->load(); + widget->updateUI(); + widget->getKcmMiscWidget()->load(); +} + +//static void initializeKeyboardSettings(); +void KCMKeyboard::save() +{ + keyboardConfig->save(); + widget->save(); + widget->getKcmMiscWidget()->save(); + + QDBusMessage message = QDBusMessage::createSignal(KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE); + QDBusConnection::sessionBus().send(message); +} + +#include "kcm_keyboard.moc" diff --git a/kcms/keyboard/kcm_keyboard.desktop b/kcms/keyboard/kcm_keyboard.desktop new file mode 100644 index 0000000000..3aef59650a --- /dev/null +++ b/kcms/keyboard/kcm_keyboard.desktop @@ -0,0 +1,241 @@ +[Desktop Entry] +Exec=kcmshell5 kcm_keyboard +Icon=preferences-desktop-keyboard +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/keyboard/index.html +Categories=Qt;KDE;X-KDE-settings-hardware; + +X-KDE-Library=kcm_keyboard +X-KDE-Init-Symbol=keyboard +X-KDE-ParentApp=kcontrol +X-KDE-OnlyShowOnQtPlatforms=xcb; + +X-KDE-System-Settings-Parent-Category=input-devices +X-KDE-Weight=50 +OnlyShowIn=KDE; + +Name=Keyboard +Name[af]=Sleutelbord +Name[ar]=لوحة المفاتيح +Name[ast]=Tecláu +Name[be]=Клавіятура +Name[be@latin]=Klavijatura +Name[bg]=Клавиатура +Name[bn]=কীবোর্ড +Name[bn_IN]=কি-বোর্ড +Name[br]=Stokellaoueg +Name[bs]=Tastatura +Name[ca]=Teclat +Name[ca@valencia]=Teclat +Name[cs]=Klávesnice +Name[csb]=Klawiatura +Name[cy]=Bysellfwrdd +Name[da]=Tastatur +Name[de]=Tastatur +Name[el]=Πληκτρολόγιο +Name[en_GB]=Keyboard +Name[eo]=Klavaro +Name[es]=Teclado +Name[et]=Klaviatuur +Name[eu]=Teklatua +Name[fa]=صفحه کلید +Name[fi]=Näppäimistö +Name[fr]=Clavier +Name[fy]=Toetseboerd +Name[ga]=Méarchlár +Name[gl]=Teclado +Name[gu]=કીબોર્ડ +Name[he]=מקלדת +Name[hi]=कुंजीपट +Name[hne]=कुंजीपट +Name[hr]=Tipkovnica +Name[hsb]=Tastatura +Name[hu]=Billentyűzet +Name[ia]=Claviero +Name[id]=Papan Ketik +Name[is]=Lyklaborð +Name[it]=Tastiera +Name[ja]=キーボード +Name[ka]=კლავიატურა +Name[kk]=Перенетақта +Name[km]=ក្ដារ​ចុច +Name[kn]=ಕೀಲಿಮಣೆ +Name[ko]=키보드 +Name[ku]=Klavye +Name[lt]=Klaviatūra +Name[lv]=Tastatūra +Name[mai]=कुँजीपटल +Name[mk]=Тастатура +Name[ml]=കീബോര്‍ഡ് +Name[mr]=कळफलक +Name[nb]=Tastatur +Name[nds]=Tastatuur +Name[ne]=कुञ्जीपाटी +Name[nl]=Toetsenbord +Name[nn]=Tastatur +Name[oc]=Clavièr +Name[or]=କିବୋର୍ଡ଼ +Name[pa]=ਕੀਬੋਰਡ +Name[pl]=Klawiatura +Name[pt]=Teclado +Name[pt_BR]=Teclado +Name[ro]=Tastatură +Name[ru]=Клавиатура +Name[se]=Boallobeavdi +Name[si]=යතුරුපුවරුව +Name[sk]=Klávesnica +Name[sl]=Tipkovnica +Name[sr]=Тастатура +Name[sr@ijekavian]=Тастатура +Name[sr@ijekavianlatin]=Tastatura +Name[sr@latin]=Tastatura +Name[sv]=Tangentbord +Name[ta]=விசைப்பலகை +Name[te]=కీబోర్డ్ +Name[tg]=Клавиатура +Name[th]=แป้นพิมพ์ +Name[tr]=Klavye +Name[ug]=ھەرپتاختا +Name[uk]=Клавіатура +Name[uz]=Tugmatag +Name[uz@cyrillic]=Тугматаг +Name[vi]=Bàn phím +Name[wa]=Taprece +Name[xh]=Ibhodi enezitshixo +Name[x-test]=xxKeyboardxx +Name[zh_CN]=键盘 +Name[zh_TW]=鍵盤 + +Comment=Keyboard settings +Comment[af]=Sleutelbord instellings +Comment[ar]=إعدادات لوحة المفاتيح +Comment[ast]=Preferencies del tecláu +Comment[be]=Настаўленні клавіятуры +Comment[be@latin]=Nałady klavijatury +Comment[bg]=Настройки на клавиатура +Comment[bn]=কীবোর্ড সেটিংস +Comment[bn_IN]=কি-বোর্ড সংক্রান্ত বৈশিষ্ট্য +Comment[br]=Kefluniañ ar stokellaoueg +Comment[bs]=Postavke tastature +Comment[ca]=Arranjament del teclat +Comment[ca@valencia]=Arranjament del teclat +Comment[cs]=Nastavení klávesnice +Comment[csb]=Nastôw klawiaturë +Comment[cy]=Gosodiadau Bysellfwrdd +Comment[da]=Tastaturindstillinger +Comment[de]=Einstellung der Tastatur +Comment[el]=Ρυθμίσεις πληκτρολογίου +Comment[en_GB]=Keyboard settings +Comment[eo]=Agordo de la klavaro +Comment[es]=Preferencias del teclado +Comment[et]=Klaviatuuri seadistused +Comment[eu]=Teklatuaren ezarpenak +Comment[fa]=تنظیمات صفحه کلید +Comment[fi]=Näppäimistön asetukset +Comment[fr]=Configuration du clavier +Comment[fy]=Toetseboerd ynstelle +Comment[ga]=Socruithe Méarchláir +Comment[gl]=Configuración do teclado +Comment[gu]=કીબોર્ડ ગોઠવણીઓ +Comment[he]=הגדרות המקלדת +Comment[hi]=कुंजीपट विन्यास +Comment[hne]=कुंजीपट सेटिंग +Comment[hr]=Postavke tipkovnice +Comment[hsb]=Nastajenja za tastaturu +Comment[hu]=A billentyűzet beállításai +Comment[ia]=Preferentias de claviero +Comment[id]=Pengaturan Papan Ketik +Comment[is]=Stillingar lyklaborðs +Comment[it]=Impostazioni della tastiera +Comment[ja]=キーボードの設定 +Comment[ka]=კლავიატურის კონფიგურაცია +Comment[kk]=Перенетақтаны баптау +Comment[km]=ការ​កំណត់​ក្ដារចុច +Comment[kn]=ಕೀಲಿಮಣೆ ಸಂಯೋಜನೆಗಳು +Comment[ko]=키보드 설정 +Comment[ku]=Mîhengên Klavyeyê +Comment[lt]=Klaviatūros parametrai +Comment[lv]=Tastatūras parametri +Comment[mai]=कुंजीपट बिन्यास +Comment[mk]=Поставувања на тастатурата +Comment[ml]=കീബോര്‍ഡിന്റെ സജ്ജീകരണങ്ങള്‍ +Comment[mr]=कळफलक संयोजना +Comment[nb]=Tastaturinnstillinger +Comment[nds]=Tastatuurinstellen +Comment[ne]=कुञ्जीपाटी सेटिङ +Comment[nl]=Toetsenbord instellen +Comment[nn]=Tastaturinnstillingar +Comment[oc]=Paramètres de clavièr +Comment[or]=କିବୋର୍ଡ଼ ସଂରଚନା +Comment[pa]=ਕੀਬੋਰਡ ਸੈਟਿੰਗ +Comment[pl]=Ustawienia klawiatury +Comment[pt]=Configuração do teclado +Comment[pt_BR]=Configurações do teclado +Comment[ro]=Configurări tastatură +Comment[ru]=Настройка клавиатуры +Comment[se]=Boallobeavdeheivehusat +Comment[si]=යතුරුපුවරු සැකසුම් +Comment[sk]=Nastavenie klávesnice +Comment[sl]=Nastavitve tipkovnice +Comment[sr]=Поставке тастатуре +Comment[sr@ijekavian]=Поставке тастатуре +Comment[sr@ijekavianlatin]=Postavke tastature +Comment[sr@latin]=Postavke tastature +Comment[sv]=Anpassa tangentbordets inställningar +Comment[ta]=விசைப்பலகை அமைப்புகள் +Comment[te]=కీబోర్డ్ అమరికలు +Comment[tg]=Танзимоти клавиатура +Comment[th]=ตั้งค่าต่าง ๆ ของแป้นพิมพ์ +Comment[tr]=Klavye ayarları +Comment[ug]=ھەرپتاختا تەڭشەك +Comment[uk]=Параметри клавіатури +Comment[uz]=Tugmatagning moslamalari +Comment[uz@cyrillic]=Тугматагнинг мосламалари +Comment[vi]=Thiết lập bàn phím +Comment[wa]=Apontiaedje del taprece +Comment[xh]=Izicwangciso zebhodi enezitshixo +Comment[x-test]=xxKeyboard settingsxx +Comment[zh_CN]=键盘设置 +Comment[zh_TW]=鍵盤設定 + +X-KDE-Keywords=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key +X-KDE-Keywords[bs]=tastatura,ponavljanje tastature,kliknute glasnoću,umetnuti uređaj,ponoviti,glasnoća,NumLock,NumPad,tip tastature,model tastature,izgled tastature,izgled tipki,jezik,rezervna tastatura,uključivanje tastature,Ctrl tipka,velika slova,esperanto,cirkumfleks,ukloniti X server,LED tastatura,sastavljene tipke +X-KDE-Keywords[ca]=Teclat,Repetició de teclat,Volum de clic,Dispositius d'entrada,repetició,volum,BloqNum,NumPad,Tipus de teclat,Model de teclat,Disposició de teclat,Idioma,Teclat alternatiu,Commutació de teclat,Tecla Ctrl,Bloq Maj,Esperanto,Circumflex,Matar servidor X,LED de teclat,Tecla compose +X-KDE-Keywords[ca@valencia]=Teclat,Repetició de teclat,Volum de clic,Dispositius d'entrada,repetició,volum,BloqNum,NumPad,Tipus de teclat,Model de teclat,Disposició de teclat,Idioma,Teclat alternatiu,Commutació de teclat,Tecla Ctrl,Bloq Maj,Esperanto,Circumflex,Matar servidor X,LED de teclat,Tecla compose +X-KDE-Keywords[da]=Tastatur,keyboard,tastaturgentagelse,klikvolume,inputenheder,gentag,lydstyrke,NumLock,numerisk tastatur,tastaturtype,tastaturmodel,tastaturlayout,tastelayout,sprog,alternativt tastatur,skift af tastatur,Ctrl-tast,lås skift,caps lock,Esperanto,Circumflex,dræb X Server,LED-tastatur,Compose-tast +X-KDE-Keywords[de]=Tastatur,Tastenwiederholung,Klicklautstärke,Eingabegeräte,Wiederholung,Lautstärke,Zahlen-Feststelltaste,Zahlenblock,Tastaturtyp,Tastaturmodell,Tastaturlayout,Tastenlayout,Sprache,Alternative Tastatur,Tastaturwechsel,Tastaturbelegung,Strg-Taste,Umschalttaste,Esperanto,Zirkumflex,X-Server beenden,Tastatur LED,Compose-Taste +X-KDE-Keywords[el]=πληκτρολόγιο,επανάληψη πληκτρολογίου,ένταση κλικ,συσκευές εισόδου,επανάληψη,ένταση,NumLock,αριθμητικό πληκτρολόγιο,τύπος πληκτρολογίου,μοντέλο πληκτρολογίου,διάταξη πληκτρολογίου,γλώσσα,εναλλακτικό πληκτρολόγιο,εναλλαγή πληκτρολογίου,πλήκτρο Ctrl,Caps Lock,Esperanto,Circumflex,Kill X Server,LED πληκτρολόγιο,πλήκτρο σύνθεσης +X-KDE-Keywords[es]=Teclado,Repetición del teclado,Volumen del clic,Dispositivos de entrada,repetición,volumen,Bloqueo numérico,Teclado numérico,Tipo de teclado,Modelo de teclado,Disposición del teclado,Disposición de las teclas,Idioma,Teclado alternativo,Cambiar de teclado,Tecla Ctrl,Bloqueo de mayúsculas,Esperanto,Circunflejo,Matar el servidor X,LED del teclado,Tecla de composición +X-KDE-Keywords[et]=Klaviatuur,Klaviatuurikordus,Klõpsu helitugevus,Sisendseadmed,kordus,helitugevus,NumLock,NumPad,numbriklahvistik,Klaviatuurimudel,Klaviatuuri mudel,Klaviatuuripaigutus,Klaviatuuri paigutus,Paigutus,Keel,Alternatiivne klaviatuur,Klaviatuuri vahetamine,Ctrl,Caps Lock,Esperanto,Tsirkumfleks,Katus,X-serveri tapmine,LDE-klaviatuur,Muuteklahv +X-KDE-Keywords[eu]=teklatu, teklatuaren errepikapen,klikaren bolumena,sarrerako gailuak,errepikatu,bolumena,BlokZenb,zenbakizko teklatu,teklatu mota,teklatuaren modeloa,teklatu-diseinua,teklen diseinua,hizkuntza, teklatu alternatiboa,teklatua aldatzea,ktrl tekla,BlokMaius,esperanto,zirkunflexua,hil X zerbitzaria,LED teklatua,tekla konposatua +X-KDE-Keywords[fi]=näppäimistö,näppäimistön toisto,näppäilyäänen voimakkuus,syöttölaitteet,toisto,numlock,numerolukko,numpad,numeronäppäimistö,näppäimistön tyyppi,näppäimistön malli,näppäimistöasettelu,näppäinasettelu,kieli,vaihtoehtoinen näppäimistö,näppäimistön vaihto,näppäimistön vaihtaminen,Ctrl-näppäin,caps lock,Esperanto,tapa X-palvelin,LED-näppäimistö,compose-näppäin +X-KDE-Keywords[fr]=Clavier, Répétition du clavier, Volume du clic, Périphériques d'entrée, répétition, volume, Verrouillage numérique, Pavé numérique, Type de clavier, Modèle de clavier, Disposition du clavier, Disposition des touches, Langue, Clavier alternatif, Changement de clavier, Touche Ctrl, Verrouillage des majuscule, Espéranto, Circonflexe, Tuer le serveur X, Voyants du clavier, Touche de composition +X-KDE-Keywords[gl]=teclado, repetición de teclas, volume do clic, dispositivo de entrada, repetición, volume, Bloq núm, Bloq num, tipo de teclado, modelo, disposición idioma, teclado alternativo, troco de teclado, Ctrl, Bloq maiús, til, circunflexo, matar o servidor X, LED +X-KDE-Keywords[hu]=Billentyűzet,Billentyűzet ismétlés,Kattintási hangerő,Beviteli eszközök,ismétlés,hangerő,NumLock,Numerikus billentyűzet,Billentyűzet típus,Billentyűzet modell,Billentyűzetkiosztás,Nyelv,Alternatív billentyűzet,Billentyűzetváltó,Ctrl billentyű,Caps Lock,Eszperantó,Ékezet,X kiszolgáló kilövése,LED billentyűzet,Levélírás billentyű +X-KDE-Keywords[ia]=Claviero,Repetition de claviero,Volumine de click,Dispositivos de ingresso,volumine, NumLock,Typo de claviero,modello de Claviero,disposition de claviero, Disposition de clave, Linguage,Claviero alternate,commutation de claviero,Clave Ctrl,Caps Lock,Esperanto, Circumflexe,Occide X Server, Claviero LED, Clave composite +X-KDE-Keywords[it]=tastiera,ripetizione tastiera,clic volume,dispositivi di ingresso,ripetizione,volume,bloc num,tastierino numerico,tipo tastiera, modello tastiera,mappatura tastiera,mappatura tasto,lingua,tastiera alternativa,cambio tastiera, tasto ctrl,maiusc,esperanto,circonflesso,uccidi server x,led tastiera,tasto composizione +X-KDE-Keywords[kk]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key +X-KDE-Keywords[km]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key +X-KDE-Keywords[ko]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,키보드,키보드 반복,입력 장치, 숫자패드,키보드 종류,레이아웃,입력,언어 +X-KDE-Keywords[mr]=की-बोर्ड,की-बोर्ड रिपीट, क्लिक व्हॉल्यूम, इनपुट डिव्हाइस, रिपीट, व्हॉल्यूम,न्यूम.लॉक,न्यूम.पॅड,की-बोर्ड टाईप, की-बोर्ड मॉडेल, की-बोर्ड लेआउट, कि लेआउट, कि लेआउट, भाषा, वैकल्पिक की-बोर्ड,की-बोर्ड स्विचिंग,सी.टी.आर.एल.की, कॅप्स लॉक, एस्परांटो,सर्कम्फलेकस,किल एक्स सर्व्हर, एल.इ.डी की बोर्ड, कंपोज की +X-KDE-Keywords[nb]=Tastatur,Tasterepetisjon,Klikklydstyrke,Inndataenheter,repeter,lydstyrke,NumLock,NumPad.Tastaturtype,Tastaturmodell,Tastaturutforming,Tateutlegg,Språk,Alternativt tastatur,Tastaturbytte,CTRL-tast,Caps Lock,Esperanto,circumflex,Drep X-tjener,LED-tastatur,Sammensett-tast +X-KDE-Keywords[nds]=Tastatuur,Tastwedderhalen,Tastluutstärk,Ingaavreedschappen, wedderhalen,Luutstärk,NumLock,TallenRast,Tallenblock,Tastatuurtyp,Tastatuurmodell,Tasttoornen,Layout,Spraak,Anner Tastatuur,Tastatuurwesseln,Ctrl,Strg,GrootschrRast, Grootschriev-Rast,Caps Lock,capslock,butenlannsch,Bookstaven,Akzent,Sünnertekens,X-Server afscheten +X-KDE-Keywords[nl]=Toetsenbord,Toetsenbordherhaling,Klikvolume,Invoerapparaten,herhaling,volume,NumLock,NumPad,Type toetsenbord,Model toetsenbord,Toetsenbordindeling,Toetsenindeling,Taal,Toetsenbord alterneren,Toetsenbord omschakelen,Ctrl-toets,Caps Lock,Esperanto,Circumflex,Kill X Server,LED-toetsenbord,Compositietoets +X-KDE-Keywords[pl]=Klawiatura,Powtórzenia klawiatury,Głośność kliknięcia,Urządzenia wejścia,powtórzenie,głośność +X-KDE-Keywords[pt]=Teclado,repetição do teclado,volume do 'click',dispositivos de entrada,repetição,volume,NumLock,NumPad,Tipo de teclado,Modelo de teclado,Disposição do teclado,Disposição das teclas,Língua,Teclado alternativo,Mudança de teclado,Ctrl,Caps Lock,Esperanto,Circunflexo,Matar o Servidor X,LED do Teclado,Tecla Compose +X-KDE-Keywords[pt_BR]=Teclado,repetição do teclado,volume do clique,dispositivos de entrada,repetição,volume,NumLock,NumPad,Tipo de teclado,Modelo de teclado,Leiaute do teclado,Leiaute das teclas,Idioma,Teclado alternativo,Mudança de teclado,Tecla Ctrl,Caps Lock,Esperanto,Circunflexo,Finalizar o servidor X,LED do teclado,Tecla Compose +X-KDE-Keywords[ru]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,клавиатура,повтор клавиши,громкость щелчка,громкость клика,устройство ввода,повтор,громкость,цифровая клавиатура,тип клавиатуры,модель клавиатуры,раскладка клавиатуры,расположение клавиш,язык,альтернативная клавиатура,переключение клавиатуры +X-KDE-Keywords[sk]=Klávesnica,opakovanie klávesnice,hlasitosť kliknutia,vstupné zariadenia,opakovanie, halsitosť,NumLock, NumPad,typ klávesnice,model klávesnice,rozloženie klávesnice,rozloženie kláves,jazyk, alternatívna klávesnica,prepínanie klávesnice,Ctrl,Caps Lock,Esperanto, Circumflex,zabiť X server,LED klávesnica,zložená klávesa +X-KDE-Keywords[sl]=tipkovnica,ponavljanje tipkovnice,tipkovno ponavljanje,glasnost klika,vhodne naprave,ponavljanje,glasnost,numlock,številčnica,vrsta tipkovnice,model tipkovnice,razporeditev tipk,razporeditev tipkovnice,jezik,nadomestna tipkovnica,alternativna tipkovnica,preklapljanje tipkovnice,ctrl,tipka ctrl,capslock,esperanto,cirkumfleks,končaj strežnik x,led,lučke,tipka za sestavljanje +X-KDE-Keywords[sr]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,тастатура,понављање тастатуре,јачина клика,улазни уређаји,понављање,јачина,NumLock,нумеричка тастатура,тип тастатуре,модел тастатуре,распоред тастатуре,распоред тастера,језик,алтернативна тастатура,мењач тастатуре,Ctrl,CapsLock,есперанто,циркумфлекс,ЛЕД тастатура,укини икс сервер +X-KDE-Keywords[sr@ijekavian]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,тастатура,понављање тастатуре,јачина клика,улазни уређаји,понављање,јачина,NumLock,нумеричка тастатура,тип тастатуре,модел тастатуре,распоред тастатуре,распоред тастера,језик,алтернативна тастатура,мењач тастатуре,Ctrl,CapsLock,есперанто,циркумфлекс,ЛЕД тастатура,укини икс сервер +X-KDE-Keywords[sr@ijekavianlatin]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,tastatura,ponavljanje tastature,jačina klika,ulazni uređaji,ponavljanje,jačina,NumLock,numerička tastatura,tip tastature,model tastature,raspored tastature,raspored tastera,jezik,alternativna tastatura,menjač tastature,Ctrl,CapsLock,esperanto,cirkumfleks,LED tastatura,ukini X server +X-KDE-Keywords[sr@latin]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,tastatura,ponavljanje tastature,jačina klika,ulazni uređaji,ponavljanje,jačina,NumLock,numerička tastatura,tip tastature,model tastature,raspored tastature,raspored tastera,jezik,alternativna tastatura,menjač tastature,Ctrl,CapsLock,esperanto,cirkumfleks,LED tastatura,ukini X server +X-KDE-Keywords[sv]=Tangentbord,Tangentbordsupprepning,Klickvolym,Indataenheter,upprepa,volym,NumLock,Numeriskt tangentbord,Tangentbordstyp,Tangentbordsmodell,Tangentbordslayout,Språk,Alternativt tangentbord,Tangentbordsbyte,Ctrl-tangent,Caps Lock,Esperanto,Circumflex,Döda X-server,LED-tangentbord,Compose-tangent +X-KDE-Keywords[tr]=Klavye,Klavye tekrarlaması,Tıklama sesi,Girdi Aygıtları,tekrarla,ses,NumLock,Sayısal Tuşlar,Klavye tipi,Klavye modeli,Klavye düzeni,Tuş düzeni,Dil,Klavyeyi Değiştir,Klavye Seçimi,Ctrl Tuşu,Caps Lock,Esperanto,İnceltme İşareti,X Sunucuyu Sonlandır,LED Klavye,Tuş Düzeni Oluştur +X-KDE-Keywords[uk]=клавіатура,повторення натискань,гучність клацання,пристрої введення,повторення,гучність,тип клавіатури,розкладка клавіатури,мова,інша клавіатура,інша розкладка,перемикання розкладок,клавіша Ctrl,есперанто,циркумфлекс,лампочки на клавіатурі,клавіша перемикання,Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key +X-KDE-Keywords[vi]=Bàn phím, lặp bàn phím, âm lượng nhấn nút,thiết bị nhập,lặp lại,âm lượng,NumLock,NumPad, kiểu bàn phím,mẫu bàn phím,loại bàn phím, bố trí phím,ngôn ngữ,bàn phím thay thế,chuyển đổi bàn phím,phím Ctrl,Caps Lock, Esperanto,Circumflex,tắt máy chủ X,bàn phím LED,phím tổ hợp +X-KDE-Keywords[x-test]=xxKeyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Keyxx +X-KDE-Keywords[zh_CN]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key,键盘,键盘重复,按键音量,输入设备,重复,音量,数字锁定,数字键盘,小键盘,键盘类型,键盘模型,键盘布局,按键布局,语言,额外键盘,键盘切换,Ctrl 键,大写锁定,杀死 X 服务器,LED 键盘灯,Compose 键,死键 +X-KDE-Keywords[zh_TW]=Keyboard,Keyboard repeat,Click volume,Input Devices,repeat,volume,NumLock,NumPad,Keyboard type,Keyboard model,Keyboard layout,Key layout,Language,Alternate Keyboard,Keyboard switching,Ctrl Key,Caps Lock,Esperanto,Circumflex,Kill X Server,LED Keyboard,Compose Key diff --git a/kcms/keyboard/kcm_keyboard.h b/kcms/keyboard/kcm_keyboard.h new file mode 100644 index 0000000000..c88fe3dd85 --- /dev/null +++ b/kcms/keyboard/kcm_keyboard.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KCM_KEYBOARD_H_ +#define KCM_KEYBOARD_H_ + +#include + +class KCMKeyboardWidget; +class KeyboardConfig; +class Rules; + +class KCMKeyboard: public KCModule +{ +Q_OBJECT + +public: + KCMKeyboard(QWidget *parent, const QVariantList &); + virtual ~KCMKeyboard(); + + void save(); + void load(); + void defaults(); + +private: + Rules* rules; + KeyboardConfig* keyboardConfig; + KCMKeyboardWidget *widget; +}; + +#endif /* KCM_KEYBOARD_H_ */ diff --git a/kcms/keyboard/kcm_keyboard.ui b/kcms/keyboard/kcm_keyboard.ui new file mode 100644 index 0000000000..57bb251baf --- /dev/null +++ b/kcms/keyboard/kcm_keyboard.ui @@ -0,0 +1,481 @@ + + + TabWidget + + + + 0 + 0 + 677 + 485 + + + + 1 + + + + Hardware + + + + 0 + + + + + + 1 + 0 + + + + Keyboard &model: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + keyboardModelComboBox + + + + + + + + 2 + 0 + + + + Here you can choose a keyboard model. This setting is independent of your keyboard layout and refers to the "hardware" model, i.e. the way your keyboard is manufactured. Modern keyboards that come with your computer usually have two extra keys and are referred to as "104-key" models, which is probably what you want if you do not know what kind of keyboard you have. + + + + 15 + + + QComboBox::AdjustToContentsOnFirstShow + + + + + + + + 1 + 1 + + + + + 0 + 100 + + + + + 0 + 0 + + + + + 0 + + + + + + + + + Layouts + + + + + + + + Layout Indicator + + + + + + Show layout indicator + + + + + + + Show for single layout + + + + + + + Show flag + + + + + + + Show label + + + + + + + Show label on flag + + + + + + + + + + If you select "Application" or "Window" switching policy, changing the keyboard layout will only affect the current application or window. + + + Switching Policy + + + + + + &Global + + + true + + + + + + + &Desktop + + + + + + + &Application + + + + + + + &Window + + + + + + + + + + Shortcuts for Switching Layout + + + + + + Main shortcuts: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + xkbGrpShortcutBtn + + + + + + + This is a shortcut for switching layouts which is handled by X.org. It allows modifier-only shortcuts. + + + None + + + + + + + ... + + + + + + + 3rd level shortcuts: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + xkb3rdLevelShortcutBtn + + + + + + + This is a shortcut for switching to a third level of the active layout (if it has one) which is handled by X.org. It allows modifier-only shortcuts. + + + None + + + + + + + ... + + + + + + + Alternative shortcut: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kdeKeySequence + + + + + + + This is a shortcut for switching layouts which is handled by KDE. It does not support modifier-only shortcuts and also may not work in some situations (e.g. if popup is active or from screensaver). + + + false + + + + + + + + + + + + true + + + Configure layouts + + + false + + + true + + + + + + + + Add + + + + + + + false + + + Remove + + + + + + + false + + + Move Up + + + + + + + false + + + Move Down + + + + + + + false + + + Preview + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QAbstractItemView::SelectRows + + + false + + + false + + + + + + + Spare layouts + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 20 + + + + + + + + + + + true + + + + + + Main layout count: + + + + + + + + + + Qt::Horizontal + + + + 431 + 20 + + + + + + + + + + + + + + + Advanced + + + + + + &Configure keyboard options + + + + + + + false + + + QAbstractItemView::NoSelection + + + true + + + + + + + + + KButtonGroup + QGroupBox +
    kbuttongroup.h
    + 1 +
    + + KKeySequenceWidget + QWidget +
    kkeysequencewidget.h
    +
    +
    + + + + changed(bool) + +
    diff --git a/kcms/keyboard/kcm_keyboard_widget.cpp b/kcms/keyboard/kcm_keyboard_widget.cpp new file mode 100644 index 0000000000..21685eb527 --- /dev/null +++ b/kcms/keyboard/kcm_keyboard_widget.cpp @@ -0,0 +1,692 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "kcm_keyboard_widget.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "keyboard_config.h" +#include "preview/keyboardpainter.h" +#include "xkb_rules.h" +#include "flags.h" +#include "x11_helper.h" +#include "kcm_view_models.h" +#include "kcm_add_layout_dialog.h" +#include "bindings.h" + +#include "kcmmisc.h" + +#include "ui_kcm_add_layout_dialog.h" + + +static const QString GROUP_SWITCH_GROUP_NAME("grp"); +static const QString LV3_SWITCH_GROUP_NAME("lv3"); +//static const QString RESET_XKB_OPTIONS("-option"); + +static const int TAB_HARDWARE = 0; +static const int TAB_LAYOUTS = 1; +static const int TAB_ADVANCED = 2; + +static const int MIN_LOOPING_COUNT = 2; + + +KCMKeyboardWidget::KCMKeyboardWidget(Rules* rules_, KeyboardConfig* keyboardConfig_, + const QVariantList &args, QWidget* /*parent*/): + rules(rules_), + actionCollection(NULL), + uiUpdating(false) +{ + flags = new Flags(); + keyboardConfig = keyboardConfig_; + + uiWidget = new Ui::TabWidget; + uiWidget->setupUi(this); + + kcmMiscWidget = new KCMiscKeyboardWidget(uiWidget->lowerHardwareWidget); + uiWidget->lowerHardwareWidget->layout()->addWidget( kcmMiscWidget ); + connect(kcmMiscWidget, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); + + if( rules != NULL ) { + initializeKeyboardModelUI(); + initializeXkbOptionsUI(); + initializeLayoutsUI(); + } + else { + uiWidget->tabLayouts->setEnabled(false); + uiWidget->tabAdvanced->setEnabled(false); + uiWidget->keyboardModelComboBox->setEnabled(false); + } + + handleParameters(args); +} + +KCMKeyboardWidget::~KCMKeyboardWidget() +{ + delete flags; +} + +void KCMKeyboardWidget::handleParameters(const QVariantList &args) +{ + // TODO: improve parameter handling + setCurrentIndex(TAB_HARDWARE); + foreach(const QVariant& arg, args) { + if( arg.type() == QVariant::String ) { + QString str = arg.toString(); + if( str == "--tab=layouts" ) { + setCurrentIndex(TAB_LAYOUTS); + } + else if( str == "--tab=advanced" ) { + setCurrentIndex(TAB_ADVANCED); + } + } + } +} + +void KCMKeyboardWidget::save() +{ + if( rules == NULL ) + return; + + if( actionCollection != NULL ) { + actionCollection->resetLayoutShortcuts(); + actionCollection->clear(); + delete actionCollection; + } + actionCollection = new KeyboardLayoutActionCollection(this, true); + actionCollection->setToggleShortcut(uiWidget->kdeKeySequence->keySequence()); + actionCollection->setLayoutShortcuts(keyboardConfig->layouts, rules); + + //TODO: skip if no change in shortcuts? + KGlobalSettings::emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_SHORTCUTS); +} + +void KCMKeyboardWidget::updateUI() +{ + if( rules == NULL ) + return; + + uiWidget->layoutsTableView->setModel(uiWidget->layoutsTableView->model()); + layoutsTableModel->refresh(); + uiWidget->layoutsTableView->resizeRowsToContents(); + + uiUpdating = true; + updateHardwareUI(); + updateXkbOptionsUI(); + updateSwitcingPolicyUI(); + updateLayoutsUI(); + updateShortcutsUI(); + uiUpdating = false; +} + +void KCMKeyboardWidget::uiChanged() +{ + if( rules == NULL ) + return; + + ((LayoutsTableModel*)uiWidget->layoutsTableView->model())->refresh(); +// this collapses the tree so use more fine-grained updates +// ((LayoutsTableModel*)uiWidget->xkbOptionsTreeView->model())->refresh(); + + if( uiUpdating ) + return; + + keyboardConfig->showIndicator = uiWidget->showIndicatorChk->isChecked(); + keyboardConfig->showSingle = uiWidget->showSingleChk->isChecked(); + + keyboardConfig->configureLayouts = uiWidget->layoutsGroupBox->isChecked(); + keyboardConfig->keyboardModel = uiWidget->keyboardModelComboBox->itemData(uiWidget->keyboardModelComboBox->currentIndex()).toString(); + + if( uiWidget->showFlagRadioBtn->isChecked() ) { + keyboardConfig->indicatorType = KeyboardConfig::SHOW_FLAG; + } + else + if( uiWidget->showLabelRadioBtn->isChecked() ) { + keyboardConfig->indicatorType = KeyboardConfig::SHOW_LABEL; + } + else { +// if( uiWidget->showFlagRadioBtn->isChecked() ) { + keyboardConfig->indicatorType = KeyboardConfig::SHOW_LABEL_ON_FLAG; + } + + keyboardConfig->resetOldXkbOptions = uiWidget->configureKeyboardOptionsChk->isChecked(); + + if( uiWidget->switchByDesktopRadioBtn->isChecked() ) { + keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_DESKTOP; + } + else + if( uiWidget->switchByApplicationRadioBtn->isChecked() ) { + keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_APPLICATION; + } + else + if( uiWidget->switchByWindowRadioBtn->isChecked() ) { + keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_WINDOW; + } + else { + keyboardConfig->switchingPolicy = KeyboardConfig::SWITCH_POLICY_GLOBAL; + } + + updateXkbShortcutsButtons(); + + updateLoopCount(); + int loop = uiWidget->layoutLoopCountSpinBox->text().isEmpty() + ? KeyboardConfig::NO_LOOPING + : uiWidget->layoutLoopCountSpinBox->value(); + keyboardConfig->layoutLoopCount = loop; + + layoutsTableModel->refresh(); + + emit changed(true); +} + +void KCMKeyboardWidget::initializeKeyboardModelUI() +{ + foreach(ModelInfo* modelInfo, rules->modelInfos) { + QString vendor = modelInfo->vendor; + if( vendor.isEmpty() ) { + vendor = i18nc("unknown keyboard model vendor", "Unknown"); + } + uiWidget->keyboardModelComboBox->addItem(i18nc("vendor | keyboard model", "%1 | %2", vendor, modelInfo->description), modelInfo->name); + } + uiWidget->keyboardModelComboBox->model()->sort(0); + connect(uiWidget->keyboardModelComboBox, SIGNAL(activated(int)), this, SLOT(uiChanged())); +} + +void KCMKeyboardWidget::addLayout() +{ + if( keyboardConfig->layouts.count() >= X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT ) { // artificial limit now + QMessageBox msgBox; + msgBox.setText(i18np("Only up to %1 keyboard layout is supported", "Only up to %1 keyboard layouts are supported", X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT)); + // more information https://bugs.freedesktop.org/show_bug.cgi?id=19501 + msgBox.exec(); + return; + } + + AddLayoutDialog dialog(rules, keyboardConfig->isFlagShown() ? flags : NULL, keyboardConfig->isLabelShown(), this); + dialog.setModal(true); + if( dialog.exec() == QDialog::Accepted ) { + keyboardConfig->layouts.append( dialog.getSelectedLayoutUnit() ); + layoutsTableModel->refresh(); + uiWidget->layoutsTableView->resizeRowsToContents(); + uiChanged(); + } + + updateLoopCount(); +} + +static +inline int min(int x, int y) { return x < y ? x : y; } + +void KCMKeyboardWidget::updateLoopCount() +{ + int maxLoop = min(X11Helper::MAX_GROUP_COUNT, keyboardConfig->layouts.count() - 1); + uiWidget->layoutLoopCountSpinBox->setMaximum(maxLoop); + + bool layoutsConfigured = uiWidget->layoutsGroupBox->isChecked(); + + if( maxLoop < MIN_LOOPING_COUNT ) { + uiWidget->layoutLoopingCheckBox->setEnabled(false); + uiWidget->layoutLoopingCheckBox->setChecked(false); + } + else if( maxLoop >= X11Helper::MAX_GROUP_COUNT ) { + uiWidget->layoutLoopingCheckBox->setEnabled(false); + uiWidget->layoutLoopingCheckBox->setChecked(true); + } + else { + uiWidget->layoutLoopingCheckBox->setEnabled(layoutsConfigured); + } + + uiWidget->layoutLoopingGroupBox->setEnabled( + layoutsConfigured && uiWidget->layoutLoopingCheckBox->isChecked()); + + if( uiWidget->layoutLoopingCheckBox->isChecked() ) { + if( uiWidget->layoutLoopCountSpinBox->text().isEmpty() ) { + uiWidget->layoutLoopCountSpinBox->setValue(maxLoop); +// keyboardConfig->layoutLoopCount = maxLoop; + } + } + else { + uiWidget->layoutLoopCountSpinBox->clear(); +// keyboardConfig->layoutLoopCount = KeyboardConfig::NO_LOOPING; + } +} + +void KCMKeyboardWidget::initializeLayoutsUI() +{ + layoutsTableModel = new LayoutsTableModel(rules, flags, keyboardConfig, uiWidget->layoutsTableView); + uiWidget->layoutsTableView->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed | QAbstractItemView::AnyKeyPressed); + uiWidget->layoutsTableView->setModel(layoutsTableModel); + uiWidget->layoutsTableView->setIconSize( flags->getTransparentPixmap().size() ); + + //TODO: do we need to delete this delegate or parent will take care of it? + VariantComboDelegate* variantDelegate = new VariantComboDelegate(keyboardConfig, rules, uiWidget->layoutsTableView); + uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::VARIANT_COLUMN, variantDelegate); + + LabelEditDelegate* labelDelegate = new LabelEditDelegate(keyboardConfig, uiWidget->layoutsTableView); + uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::DISPLAY_NAME_COLUMN, labelDelegate); + + KKeySequenceWidgetDelegate* shortcutDelegate = new KKeySequenceWidgetDelegate(keyboardConfig, uiWidget->layoutsTableView); + uiWidget->layoutsTableView->setItemDelegateForColumn(LayoutsTableModel::SHORTCUT_COLUMN, shortcutDelegate); + + //TODO: is it ok to hardcode sizes? any better approach? + uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::MAP_COLUMN, 70); + uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::LAYOUT_COLUMN, 200); + uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::VARIANT_COLUMN, 200); + uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::DISPLAY_NAME_COLUMN, 50); + uiWidget->layoutsTableView->setColumnWidth(LayoutsTableModel::SHORTCUT_COLUMN, 130); + + connect(layoutsTableModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(uiChanged())); + + uiWidget->layoutLoopCountSpinBox->setMinimum(MIN_LOOPING_COUNT); + +#ifdef DRAG_ENABLED + uiWidget->layoutsTableView->setDragEnabled(true); + uiWidget->layoutsTableView->setAcceptDrops(true); +#endif + + uiWidget->moveUpBtn->setIcon(QIcon::fromTheme("arrow-up")); + uiWidget->moveDownBtn->setIcon(QIcon::fromTheme("arrow-down")); + uiWidget->addLayoutBtn->setIcon(QIcon::fromTheme("list-add")); + uiWidget->removeLayoutBtn->setIcon(QIcon::fromTheme("list-remove")); + + QIcon clearIcon = qApp->isLeftToRight() ? QIcon::fromTheme("edit-clear-locationbar-rtl") : QIcon::fromTheme("edit-clear-locationbar-ltr"); + uiWidget->xkbGrpClearBtn->setIcon(clearIcon); + uiWidget->xkb3rdLevelClearBtn->setIcon(clearIcon); + + QIcon configIcon = QIcon::fromTheme("configure"); + uiWidget->xkbGrpShortcutBtn->setIcon(configIcon); + uiWidget->xkb3rdLevelShortcutBtn->setIcon(configIcon); + + uiWidget->kdeKeySequence->setModifierlessAllowed(false); + + connect(uiWidget->addLayoutBtn, SIGNAL(clicked(bool)), this, SLOT(addLayout())); + connect(uiWidget->removeLayoutBtn, SIGNAL(clicked(bool)), this, SLOT(removeLayout())); +// connect(uiWidget->layoutsTable, SIGNAL(itemSelectionChanged()), this, SLOT(layoutSelectionChanged())); + connect(uiWidget->layoutsTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(layoutSelectionChanged())); + +// connect(uiWidget->moveUpBtn, SIGNAL(triggered(QAction*)), this, SLOT(moveUp())); +// connect(uiWidget->moveDownBtn, SIGNAL(triggered(QAction*)), this, SLOT(moveDown())); + connect(uiWidget->moveUpBtn, SIGNAL(clicked(bool)), this, SLOT(moveUp())); + connect(uiWidget->moveDownBtn, SIGNAL(clicked(bool)), this, SLOT(moveDown())); + + connect(uiWidget->previewbutton,SIGNAL(clicked(bool)),this,SLOT(previewLayout())); + + connect(uiWidget->xkbGrpClearBtn, SIGNAL(clicked(bool)), this, SLOT(clearGroupShortcuts())); + connect(uiWidget->xkb3rdLevelClearBtn, SIGNAL(clicked(bool)), this, SLOT(clear3rdLevelShortcuts())); + +// connect(uiWidget->xkbGrpClearBtn, SIGNAL(triggered(QAction*)), this, SLOT(uiChanged())); +// connect(uiWidget->xkb3rdLevelClearBtn, SIGNAL(triggered(QAction*)), this, SLOT(uiChanged())); + connect(uiWidget->kdeKeySequence, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(uiChanged())); + connect(uiWidget->switchingPolicyButtonGroup, SIGNAL(clicked(int)), this, SLOT(uiChanged())); + + connect(uiWidget->xkbGrpShortcutBtn, SIGNAL(clicked(bool)), this, SLOT(scrollToGroupShortcut())); + connect(uiWidget->xkb3rdLevelShortcutBtn, SIGNAL(clicked(bool)), this, SLOT(scrollTo3rdLevelShortcut())); + + // connect(uiWidget->configureLayoutsChk, SIGNAL(toggled(bool)), uiWidget->layoutsGroupBox, SLOT(setEnabled(bool))); + connect(uiWidget->layoutsGroupBox, SIGNAL(toggled(bool)), this, SLOT(configureLayoutsChanged())); + + connect(uiWidget->showIndicatorChk, SIGNAL(clicked(bool)), this, SLOT(uiChanged())); + connect(uiWidget->showIndicatorChk, SIGNAL(toggled(bool)), uiWidget->showSingleChk, SLOT(setEnabled(bool))); + connect(uiWidget->showFlagRadioBtn, SIGNAL(clicked(bool)), this, SLOT(uiChanged())); + connect(uiWidget->showLabelRadioBtn, SIGNAL(clicked(bool)), this, SLOT(uiChanged())); + connect(uiWidget->showLabelOnFlagRadioBtn, SIGNAL(clicked(bool)), this, SLOT(uiChanged())); + connect(uiWidget->showSingleChk, SIGNAL(toggled(bool)), this, SLOT(uiChanged())); + + connect(uiWidget->layoutLoopingCheckBox, SIGNAL(clicked(bool)), this, SLOT(uiChanged())); + connect(uiWidget->layoutLoopCountSpinBox, SIGNAL(valueChanged(int)), this, SLOT(uiChanged())); +} + +void KCMKeyboardWidget::previewLayout(){ + QMessageBox q; + QModelIndex index = uiWidget->layoutsTableView->currentIndex() ; + QModelIndex idcountry = index.sibling(index.row(),0) ; + QString country=uiWidget->layoutsTableView->model()->data(idcountry).toString(); + QModelIndex idvariant = index.sibling(index.row(),2) ; + QString variant=uiWidget->layoutsTableView->model()->data(idvariant).toString(); + if(index.row()==-1 || index.column()==-1){ + q.setText(i18n("No layout selected ")); + q.exec(); + } + else{ + KeyboardPainter* layoutPreview = new KeyboardPainter(); + const LayoutInfo* layoutInfo = rules->getLayoutInfo(country); + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + if(variant==variantInfo->description){ + variant=variantInfo->name; + break; + } + } + layoutPreview->generateKeyboardLayout(country,variant); + layoutPreview->exec(); + layoutPreview->setModal(true); + } +} + +void KCMKeyboardWidget::configureLayoutsChanged() +{ + if( uiWidget->layoutsGroupBox->isChecked() && keyboardConfig->layouts.isEmpty() ) { + populateWithCurrentLayouts(); + } + uiChanged(); +} + +static QPair getSelectedRowRange(const QModelIndexList& selected) +{ + if( selected.isEmpty() ) { + return QPair(-1, -1); + } + + QList rows; + foreach(const QModelIndex& index, selected) { + rows << index.row(); + } + qSort(rows); + return QPair(rows[0], rows[rows.size()-1]); +} + +void KCMKeyboardWidget::layoutSelectionChanged() +{ + QModelIndexList selected = uiWidget->layoutsTableView->selectionModel()->selectedIndexes(); + uiWidget->removeLayoutBtn->setEnabled( ! selected.isEmpty() ); + QPair rowsRange( getSelectedRowRange(selected) ); + uiWidget->moveUpBtn->setEnabled( ! selected.isEmpty() && rowsRange.first > 0); + uiWidget->previewbutton->setEnabled(! selected.isEmpty()); + uiWidget->moveDownBtn->setEnabled( ! selected.isEmpty() && rowsRange.second < keyboardConfig->layouts.size()-1 ); +} + +void KCMKeyboardWidget::removeLayout() +{ + if( ! uiWidget->layoutsTableView->selectionModel()->hasSelection() ) + return; + + QModelIndexList selected = uiWidget->layoutsTableView->selectionModel()->selectedIndexes(); + QPair rowsRange( getSelectedRowRange(selected) ); + foreach(const QModelIndex& idx, selected) { + if( idx.column() == 0 ) { + keyboardConfig->layouts.removeAt(rowsRange.first); + } + } + layoutsTableModel->refresh(); + uiChanged(); + + if( keyboardConfig->layouts.size() > 0 ) { + int rowToSelect = rowsRange.first; + if( rowToSelect >= keyboardConfig->layouts.size() ) { + rowToSelect--; + } + + QModelIndex topLeft = layoutsTableModel->index(rowToSelect, 0, QModelIndex()); + QModelIndex bottomRight = layoutsTableModel->index(rowToSelect, layoutsTableModel->columnCount(topLeft)-1, QModelIndex()); + QItemSelection selection(topLeft, bottomRight); + uiWidget->layoutsTableView->selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); + uiWidget->layoutsTableView->setFocus(); + } + + layoutSelectionChanged(); + + updateLoopCount(); +} + +void KCMKeyboardWidget::moveUp() +{ + moveSelectedLayouts(-1); +} + +void KCMKeyboardWidget::moveDown() +{ + moveSelectedLayouts(1); +} + +void KCMKeyboardWidget::moveSelectedLayouts(int shift) +{ + QItemSelectionModel* selectionModel = uiWidget->layoutsTableView->selectionModel(); + if( selectionModel == NULL || !selectionModel->hasSelection() ) + return; + + QModelIndexList selected = selectionModel->selectedRows(); + if( selected.count() < 1 ) + return; + + int newFirstRow = selected[0].row() + shift; + int newLastRow = selected[ selected.size()-1 ].row() + shift; + + if( newFirstRow >= 0 && newLastRow <= keyboardConfig->layouts.size() - 1 ) { + QList selectionRows; + foreach(const QModelIndex& index, selected) { + int newRowIndex = index.row() + shift; + keyboardConfig->layouts.move(index.row(), newRowIndex); + selectionRows << newRowIndex; + } + uiChanged(); + + QItemSelection selection; + foreach(int row, selectionRows) { + QModelIndex topLeft = layoutsTableModel->index(row, 0, QModelIndex()); + QModelIndex bottomRight = layoutsTableModel->index(row, layoutsTableModel->columnCount(topLeft)-1, QModelIndex()); + selection << QItemSelectionRange(topLeft, bottomRight); + } + uiWidget->layoutsTableView->selectionModel()->select(selection, QItemSelectionModel::SelectCurrent); + uiWidget->layoutsTableView->setFocus(); + } +} + +void KCMKeyboardWidget::scrollToGroupShortcut() +{ + this->setCurrentIndex(TAB_ADVANCED); + if( ! uiWidget->configureKeyboardOptionsChk->isChecked() ) { + uiWidget->configureKeyboardOptionsChk->setChecked(true); + } + ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->gotoGroup(GROUP_SWITCH_GROUP_NAME, uiWidget->xkbOptionsTreeView); +} + +void KCMKeyboardWidget::scrollTo3rdLevelShortcut() +{ + this->setCurrentIndex(TAB_ADVANCED); + if( ! uiWidget->configureKeyboardOptionsChk->isChecked() ) { + uiWidget->configureKeyboardOptionsChk->setChecked(true); + } + ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->gotoGroup(LV3_SWITCH_GROUP_NAME, uiWidget->xkbOptionsTreeView); +} + +void KCMKeyboardWidget::clearGroupShortcuts() +{ + clearXkbGroup(GROUP_SWITCH_GROUP_NAME); +} + +void KCMKeyboardWidget::clear3rdLevelShortcuts() +{ + clearXkbGroup(LV3_SWITCH_GROUP_NAME); +} + +void KCMKeyboardWidget::clearXkbGroup(const QString& groupName) +{ + for(int ii=keyboardConfig->xkbOptions.count()-1; ii>=0; ii--) { + if( keyboardConfig->xkbOptions[ii].startsWith(groupName + Rules::XKB_OPTION_GROUP_SEPARATOR) ) { + keyboardConfig->xkbOptions.removeAt(ii); + } + } + ((XkbOptionsTreeModel*)uiWidget->xkbOptionsTreeView->model())->reset(); + uiWidget->xkbOptionsTreeView->update(); + updateXkbShortcutsButtons(); + emit changed(true); +} + +static +bool xkbOptionGroupLessThan(const OptionGroupInfo* og1, const OptionGroupInfo* og2) +{ + return og1->description.toLower() < og2->description.toLower(); +} +static +bool xkbOptionLessThan(const OptionInfo* o1, const OptionInfo* o2) +{ + return o1->description.toLower() < o2->description.toLower(); +} + +void KCMKeyboardWidget::initializeXkbOptionsUI() +{ + qSort(rules->optionGroupInfos.begin(), rules->optionGroupInfos.end(), xkbOptionGroupLessThan); + foreach(OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { + qSort(optionGroupInfo->optionInfos.begin(), optionGroupInfo->optionInfos.end(), xkbOptionLessThan); + } + + XkbOptionsTreeModel* model = new XkbOptionsTreeModel(rules, keyboardConfig, uiWidget->xkbOptionsTreeView); + uiWidget->xkbOptionsTreeView->setModel(model); + connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(uiChanged())); + + connect(uiWidget->configureKeyboardOptionsChk, SIGNAL(toggled(bool)), this, SLOT(configureXkbOptionsChanged())); + // connect(uiWidget->configureKeyboardOptionsChk, SIGNAL(toggled(bool)), this, SLOT(uiChanged())); + connect(uiWidget->configureKeyboardOptionsChk, SIGNAL(toggled(bool)), uiWidget->xkbOptionsTreeView, SLOT(setEnabled(bool))); +} + +void KCMKeyboardWidget::configureXkbOptionsChanged() +{ + if( uiWidget->configureKeyboardOptionsChk->isChecked() && keyboardConfig->xkbOptions.isEmpty() ) { + populateWithCurrentXkbOptions(); + } + ((LayoutsTableModel*)uiWidget->xkbOptionsTreeView->model())->refresh(); + uiChanged(); +} + +void KCMKeyboardWidget::updateSwitcingPolicyUI() +{ + switch (keyboardConfig->switchingPolicy){ + case KeyboardConfig::SWITCH_POLICY_DESKTOP: + uiWidget->switchByDesktopRadioBtn->setChecked(true); + break; + case KeyboardConfig::SWITCH_POLICY_APPLICATION: + uiWidget->switchByApplicationRadioBtn->setChecked(true); + break; + case KeyboardConfig::SWITCH_POLICY_WINDOW: + uiWidget->switchByWindowRadioBtn->setChecked(true); + break; + default: + case KeyboardConfig::SWITCH_POLICY_GLOBAL: + uiWidget->switchByGlobalRadioBtn->setChecked(true); + } +} + +void KCMKeyboardWidget::updateXkbShortcutButton(const QString& groupName, QPushButton* button) +{ + QStringList grpOptions; + if( keyboardConfig->resetOldXkbOptions ) { + QRegExp regexp = QRegExp("^" + groupName + Rules::XKB_OPTION_GROUP_SEPARATOR); + grpOptions = keyboardConfig->xkbOptions.filter(regexp); + } + switch( grpOptions.size() ) { + case 0: + button->setText(i18nc("no shortcuts defined", "None")); + break; + case 1: { + const QString& option = grpOptions.first(); + const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName); + const OptionInfo* optionInfo = optionGroupInfo->getOptionInfo(option); + if( optionInfo == NULL || optionInfo->description == NULL ) { + kError() << "Could not find option info for " << option; + button->setText(grpOptions.first()); + } + else { + button->setText(optionInfo->description); + } + } + break; + default: + button->setText(i18np("%1 shortcut", "%1 shortcuts", grpOptions.size())); + } +} + +void KCMKeyboardWidget::updateXkbShortcutsButtons() +{ + updateXkbShortcutButton(GROUP_SWITCH_GROUP_NAME, uiWidget->xkbGrpShortcutBtn); + updateXkbShortcutButton(LV3_SWITCH_GROUP_NAME, uiWidget->xkb3rdLevelShortcutBtn); +} + +void KCMKeyboardWidget::updateShortcutsUI() +{ + updateXkbShortcutsButtons(); + + delete actionCollection; + actionCollection = new KeyboardLayoutActionCollection(this, true); + QAction* toggleAction = actionCollection->getToggeAction(); + const auto shortcuts = KGlobalAccel::self()->shortcut(toggleAction); + uiWidget->kdeKeySequence->setKeySequence(shortcuts.isEmpty() ? QKeySequence() : shortcuts.first()); + actionCollection->loadLayoutShortcuts(keyboardConfig->layouts, rules); + layoutsTableModel->refresh(); +} + +void KCMKeyboardWidget::updateXkbOptionsUI() +{ + uiWidget->configureKeyboardOptionsChk->setChecked(keyboardConfig->resetOldXkbOptions); +} + +void KCMKeyboardWidget::updateLayoutsUI() { + uiWidget->layoutsGroupBox->setChecked(keyboardConfig->configureLayouts); + uiWidget->showIndicatorChk->setChecked(keyboardConfig->showIndicator); + uiWidget->showSingleChk->setChecked(keyboardConfig->showSingle); + uiWidget->showFlagRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_FLAG); + uiWidget->showLabelRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL); + uiWidget->showLabelOnFlagRadioBtn->setChecked(keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG); + + bool loopingOn = keyboardConfig->configureLayouts && keyboardConfig->layoutLoopCount + != KeyboardConfig::NO_LOOPING; + uiWidget->layoutLoopingCheckBox->setChecked(loopingOn); + uiWidget->layoutLoopingGroupBox->setEnabled(loopingOn); + if( loopingOn ) { + uiWidget->layoutLoopCountSpinBox->setValue(keyboardConfig->layoutLoopCount); + } + else { + uiWidget->layoutLoopCountSpinBox->clear(); + } +} + +void KCMKeyboardWidget::updateHardwareUI() +{ + int idx = uiWidget->keyboardModelComboBox->findData(keyboardConfig->keyboardModel); + if( idx != -1 ) { + uiWidget->keyboardModelComboBox->setCurrentIndex(idx); + } +} + +void KCMKeyboardWidget::populateWithCurrentLayouts() +{ + QList layouts = X11Helper::getLayoutsList(); + foreach(LayoutUnit layoutUnit, layouts) { + keyboardConfig->layouts.append(layoutUnit); + } +} + +void KCMKeyboardWidget::populateWithCurrentXkbOptions() +{ + XkbConfig xkbConfig; + if( X11Helper::getGroupNames(QX11Info::display(), &xkbConfig, X11Helper::ALL) ) { + foreach(QString xkbOption, xkbConfig.options) { + keyboardConfig->xkbOptions.append(xkbOption); + } + } +} diff --git a/kcms/keyboard/kcm_keyboard_widget.h b/kcms/keyboard/kcm_keyboard_widget.h new file mode 100644 index 0000000000..657ddda3bc --- /dev/null +++ b/kcms/keyboard/kcm_keyboard_widget.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KCM_KEYBOARD_WIDGET_H_ +#define KCM_KEYBOARD_WIDGET_H_ + +#include "ui_kcm_keyboard.h" + +#include +#include + +class QWidget; +class KeyboardConfig; +class Rules; +class Flags; +class KComponentData; +class QString; +class QPushButton; +class LayoutsTableModel; +class KCMiscKeyboardWidget; +class KeyboardLayoutActionCollection; + +class KCMKeyboardWidget: public QTabWidget +{ + Q_OBJECT + +public: + KCMKeyboardWidget(Rules* rules, KeyboardConfig* keyboardConfig, + const QVariantList &args, QWidget* parent=0); + virtual ~KCMKeyboardWidget(); + + void updateUI(); + void save(); + + //temp hack + KCMiscKeyboardWidget* getKcmMiscWidget() const { return kcmMiscWidget; } + +Q_SIGNALS: + void changed(bool state); + +private Q_SLOTS: + void addLayout(); + void removeLayout(); + void layoutSelectionChanged(); + void uiChanged(); + void scrollToGroupShortcut(); + void scrollTo3rdLevelShortcut(); + void clearGroupShortcuts(); + void clear3rdLevelShortcuts(); + void updateXkbShortcutsButtons(); + void moveUp(); + void moveDown(); + void configureLayoutsChanged(); + void configureXkbOptionsChanged(); + void previewLayout(); + +private: + Rules *rules; + Flags *flags; + Ui::TabWidget *uiWidget; + KeyboardConfig *keyboardConfig; + KeyboardLayoutActionCollection* actionCollection; + LayoutsTableModel* layoutsTableModel; + KCMiscKeyboardWidget* kcmMiscWidget; + bool uiUpdating; + + void initializeLayoutsUI(); + void initializeXkbOptionsUI(); + void initializeKeyboardModelUI(); + void updateHardwareUI(); + void updateLayoutsUI(); + void updateShortcutsUI(); + void updateXkbOptionsUI(); + void updateSwitcingPolicyUI(); + void updateXkbShortcutButton(const QString& groupName, QPushButton* button); + void clearXkbGroup(const QString& groupName); + void moveSelectedLayouts(int shift); + void populateWithCurrentLayouts(); + void populateWithCurrentXkbOptions(); + void updateLoopCount(); + void handleParameters(const QVariantList &args); +}; + + +#endif /* KCM_KEYBOARD_WIDGET_H_ */ diff --git a/kcms/keyboard/kcm_view_models.cpp b/kcms/keyboard/kcm_view_models.cpp new file mode 100644 index 0000000000..093bca9c4f --- /dev/null +++ b/kcms/keyboard/kcm_view_models.cpp @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "kcm_view_models.h" + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef DRAG_ENABLED +#include +#endif + +#include "keyboard_config.h" +#include "xkb_rules.h" +#include "flags.h" +#include "x11_helper.h" +#include "bindings.h" + +const int LayoutsTableModel::MAP_COLUMN = 0; +const int LayoutsTableModel::LAYOUT_COLUMN = 1; +const int LayoutsTableModel::VARIANT_COLUMN = 2; +const int LayoutsTableModel::DISPLAY_NAME_COLUMN = 3; +const int LayoutsTableModel::SHORTCUT_COLUMN = 4; +static const int COLUMN_COUNT = 5; + +LayoutsTableModel::LayoutsTableModel(Rules* rules_, Flags *flags_, KeyboardConfig* keyboardConfig_, QObject* parent): + QAbstractTableModel(parent), + keyboardConfig(keyboardConfig_), + rules(rules_), + countryFlags(flags_) +{ +} + +void LayoutsTableModel::refresh() +{ + beginResetModel(); + endResetModel(); +} + +int LayoutsTableModel::rowCount(const QModelIndex &/*parent*/) const +{ + return keyboardConfig->layouts.count(); +} + +int LayoutsTableModel::columnCount(const QModelIndex&) const +{ + return COLUMN_COUNT; +} + +Qt::ItemFlags LayoutsTableModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + Qt::ItemFlags flags = QAbstractTableModel::flags(index); + + if( index.column() == DISPLAY_NAME_COLUMN + || index.column() == VARIANT_COLUMN + || index.column() == SHORTCUT_COLUMN ) { + flags |= Qt::ItemIsEditable; + } + +#ifdef DRAG_ENABLED + flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; +#endif + + return flags; +} + +#ifdef DRAG_ENABLED +QStringList LayoutsTableModel::mimeTypes() const +{ + QStringList types; + types << "application/keyboard-layout-item"; + return types; +} + +QMimeData *LayoutsTableModel::mimeData(const QModelIndexList &indexes) const + { + QMimeData *mimeData = new QMimeData(); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + + QSet rows; + foreach (const QModelIndex& index, indexes) { + if (index.isValid()) { + rows << index.row(); + } + } + foreach (int row, rows) { + stream << row; + } + + mimeData->setData("application/keyboard-layout-item", encodedData); + return mimeData; +} +#endif + +QVariant LayoutsTableModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= keyboardConfig->layouts.size()) + return QVariant(); + + const LayoutUnit& layoutUnit = keyboardConfig->layouts.at(index.row()); + + if (role == Qt::DecorationRole) { + switch( index.column() ) { + case DISPLAY_NAME_COLUMN: { +// if( keyboardConfig->isFlagShown() ) { + QIcon icon = countryFlags->getIconWithText(layoutUnit, *keyboardConfig); + return icon.isNull() ? countryFlags->getTransparentPixmap() : icon; +// } + } +//TODO: show the cells are editable +// case VARIANT_COLUMN: { +// case DISPLAY_NAME_COLUMN: { +// int sz = 5; +// QPixmap pm = QPixmap(sz, sz+5); +// pm.fill(Qt::transparent); +// QPainter p(&pm); +// QPoint points[] = { QPoint(0, 0), QPoint(0, sz), QPoint(sz, 0) }; +// p.drawPolygon(points, 3); +// return pm; +// } + break; + } + } + else + if( role == Qt::BackgroundRole ) { + if( keyboardConfig->layoutLoopCount != KeyboardConfig::NO_LOOPING + && index.row() >= keyboardConfig->layoutLoopCount ) { + return QBrush(Qt::lightGray); + } + } + else + if (role == Qt::DisplayRole) { + switch( index.column() ) { + case MAP_COLUMN: + return layoutUnit.layout; + break; + case LAYOUT_COLUMN: { + const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); + return layoutInfo != NULL ? layoutInfo->description : layoutUnit.layout; + } + case VARIANT_COLUMN: { + if( layoutUnit.variant.isEmpty() ) + return QVariant(); + const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); + if( layoutInfo == NULL ) + return QVariant(); + const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant); + return variantInfo != NULL ? variantInfo->description : layoutUnit.variant; + } + break; + case DISPLAY_NAME_COLUMN: +// if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL ) { +// return layoutUnit.getDisplayName(); +// } + break; + case SHORTCUT_COLUMN: { + return layoutUnit.getShortcut().toString(); + } + break; + } + } + else if (role==Qt::EditRole ) { + switch( index.column() ) { + case DISPLAY_NAME_COLUMN: + return layoutUnit.getDisplayName(); + break; + case VARIANT_COLUMN: + return layoutUnit.variant; + break; + case SHORTCUT_COLUMN: + return layoutUnit.getShortcut().toString(); + break; + default:; + } + } + else if( role == Qt::TextAlignmentRole ) { + switch( index.column() ) { + case MAP_COLUMN: + case DISPLAY_NAME_COLUMN: + case SHORTCUT_COLUMN: + return Qt::AlignCenter; + break; + default:; + } + } + return QVariant(); +} + +QVariant LayoutsTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) { + const QString headers[] = {i18nc("layout map name", "Map"), i18n("Layout"), i18n("Variant"), i18n("Label"), i18n("Shortcut")}; + return headers[section]; + } + + return QVariant(); +} + +bool LayoutsTableModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (role != Qt::EditRole + || (index.column() != DISPLAY_NAME_COLUMN && index.column() != VARIANT_COLUMN && index.column() != SHORTCUT_COLUMN) ) + return false; + + if (index.row() >= keyboardConfig->layouts.size()) + return false; + + LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; + + switch( index.column() ) { + case DISPLAY_NAME_COLUMN: { + QString displayText = value.toString().left(3); + layoutUnit.setDisplayName(displayText); + countryFlags->clearCache(); // regenerate the label + } + break; + case VARIANT_COLUMN: { + QString variant = value.toString(); + layoutUnit.variant = variant; + } + break; + case SHORTCUT_COLUMN: { + QString shortcut = value.toString(); + layoutUnit.setShortcut(QKeySequence(shortcut)); + } + break; + } + emit dataChanged(index, index); + + return true; +} + +// +// LabelEditDelegate +// +LabelEditDelegate::LabelEditDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): + QStyledItemDelegate(parent), + keyboardConfig(keyboardConfig_) +{} + +QWidget *LabelEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , + const QModelIndex & index ) const +{ + if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_FLAG ) + return NULL; + + QWidget* widget = QStyledItemDelegate::createEditor(parent, option, index); + QLineEdit* lineEdit = static_cast(widget); + if( lineEdit != NULL ) { + lineEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH); + } + return widget; +} + +//void LabelEditDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const +//{ +// QStyleOptionViewItem option2(option); +//// option2.decorationPosition = QStyleOptionViewItem::Right; +// option2.decorationAlignment = Qt::AlignHCenter | Qt::AlignVCenter; +// QStyledItemDelegate::paint(painter, option2, index); +//} + + +// +// VariantComboDelegate +// +//TODO: reuse this function in kcm_add_layout_dialog.cpp +static void populateComboWithVariants(QComboBox* combo, const QString& layout, const Rules* rules) +{ + combo->clear(); + const LayoutInfo* layoutInfo = rules->getLayoutInfo(layout); + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + combo->addItem(variantInfo->description, variantInfo->name); + } + combo->model()->sort(0); + combo->insertItem(0, i18nc("variant", "Default"), ""); + combo->setCurrentIndex(0); +} + +VariantComboDelegate::VariantComboDelegate(const KeyboardConfig* keyboardConfig_, const Rules* rules_, QObject *parent): + QStyledItemDelegate(parent), + keyboardConfig(keyboardConfig_), + rules(rules_) +{} + +QWidget *VariantComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, + const QModelIndex & index ) const +{ + QComboBox *editor = new QComboBox(parent); + const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; + populateComboWithVariants(editor, layoutUnit.layout, rules); + return editor; +} + +void VariantComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QComboBox *combo = static_cast(editor); + QString variant = index.model()->data(index, Qt::EditRole).toString(); + int itemIndex = combo->findData(variant); + if( itemIndex == -1 ) { + itemIndex = 0; + } + combo->setCurrentIndex(itemIndex); +} + +void VariantComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QComboBox *combo = static_cast(editor); + QString variant = combo->itemData(combo->currentIndex()).toString(); + model->setData(index, variant, Qt::EditRole); +} + +void VariantComboDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +// +// KKeySequenceWidgetDelegate +// +KKeySequenceWidgetDelegate::KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): + QStyledItemDelegate(parent), + keyboardConfig(keyboardConfig_) +{} + +QWidget *KKeySequenceWidgetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /*option*/, + const QModelIndex & index ) const +{ + itemsBeingEdited.insert(index); + + KKeySequenceWidget *editor = new KKeySequenceWidget(parent); + editor->setFocusPolicy(Qt::StrongFocus); + editor->setModifierlessAllowed(false); + + const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; + editor->setKeySequence(layoutUnit.getShortcut()); + + editor->captureKeySequence(); + + return editor; +} + +//void KKeySequenceWidgetDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +//{ +// KKeySequenceWidget *kkeysequencewidget = static_cast(editor); +// QString shortcut = index.model()->data(index, Qt::EditRole).toString(); +// kkeysequencewidget->setKeySequence(QKeySequence(shortcut)); +// kkeysequencewidget->captureKeySequence(); +//// kDebug() << "set editor data"; +//} + +void KKeySequenceWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + KKeySequenceWidget *kkeysequencewidget = static_cast(editor); + QString shortcut = kkeysequencewidget->keySequence().toString(); + model->setData(index, shortcut, Qt::EditRole); + itemsBeingEdited.remove(index); +} + +void KKeySequenceWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + if (itemsBeingEdited.contains(index)) { +// StyledBackgroundPainter::drawBackground(painter,option,index); + } + else { + QStyledItemDelegate::paint(painter,option,index); + } +} +// +// Xkb Options Tree View +// + +int XkbOptionsTreeModel::rowCount(const QModelIndex& parent) const { + if( ! parent.isValid() ) + return rules->optionGroupInfos.count(); + if( ! parent.parent().isValid() ) + return rules->optionGroupInfos[parent.row()]->optionInfos.count(); + return 0; +} + +QVariant XkbOptionsTreeModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + + if (role == Qt::DisplayRole) { + if( ! index.parent().isValid() ) { + return rules->optionGroupInfos[row]->description; + } + else { + int groupRow = index.parent().row(); + const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; + return xkbGroup->optionInfos[row]->description; + } + } + else if (role==Qt::CheckStateRole ) { + if( index.parent().isValid() ) { + int groupRow = index.parent().row(); + const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; + const QString& xkbOptionName = xkbGroup->optionInfos[row]->name; + return keyboardConfig->xkbOptions.indexOf(xkbOptionName) == -1 + ? Qt::Unchecked : Qt::Checked; + } + else { + int groupRow = index.row(); + const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; + foreach(const OptionInfo* optionInfo, xkbGroup->optionInfos) { + if( keyboardConfig->xkbOptions.indexOf(optionInfo->name) != -1 ) + return Qt::PartiallyChecked; + } + return Qt::Unchecked; + } + } + return QVariant(); +} + +bool XkbOptionsTreeModel::setData(const QModelIndex & index, const QVariant & value, int role) { + int groupRow = index.parent().row(); + if( groupRow < 0 ) return false; + + const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; + const OptionInfo* option = xkbGroup->optionInfos[index.row()]; + + if( value.toInt() == Qt::Checked ) { + if( xkbGroup->exclusive ) { + // clear if exclusive (TODO: radiobutton) + int idx = keyboardConfig->xkbOptions.indexOf(QRegExp(xkbGroup->name + ".*")); + if( idx >= 0 ) { + for(int i=0; ioptionInfos.count(); i++) + if( xkbGroup->optionInfos[i]->name == keyboardConfig->xkbOptions[idx] ) { + setData(createIndex(i, index.column(), (quint32)index.internalId()-index.row()+i), Qt::Unchecked, role); + break; + } + // m_kxkbConfig->m_options.removeAt(idx); + // idx = m_kxkbConfig->m_options.indexOf(QRegExp(xkbGroupNm+".*")); + } + } + if( keyboardConfig->xkbOptions.indexOf(option->name) < 0 ) { + keyboardConfig->xkbOptions.append(option->name); + } + } + else { + keyboardConfig->xkbOptions.removeAll(option->name); + } + + emit dataChanged(index, index); + emit dataChanged(index.parent(), index.parent()); + return true; +} + +void XkbOptionsTreeModel::gotoGroup(const QString& groupName, QTreeView* view) { + const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName); + int index = rules->optionGroupInfos.indexOf((OptionGroupInfo*)optionGroupInfo); + if( index != -1 ) { + QModelIndex modelIdx = createIndex(index,0); +// view->selectionModel()->setCurrentIndex(createIndex(index,0), QItemSelectionModel::NoUpdate); + view->setExpanded(modelIdx, true); + view->scrollTo(modelIdx, QAbstractItemView::PositionAtTop); + view->selectionModel()->setCurrentIndex(modelIdx, QItemSelectionModel::Current); + view->setFocus(Qt::OtherFocusReason); + } +// else { +// kDebug() << "can't scroll to group" << group; +// } +} + diff --git a/kcms/keyboard/kcm_view_models.h b/kcms/keyboard/kcm_view_models.h new file mode 100644 index 0000000000..285f90dce5 --- /dev/null +++ b/kcms/keyboard/kcm_view_models.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KCM_VIEW_MODELS_H_ +#define KCM_VIEW_MODELS_H_ + +#include +#include +#include +#include + +class QTreeView; +class KeyboardConfig; +class Rules; +class Flags; +class KeyboardLayoutActionCollection; + +class LayoutsTableModel : public QAbstractTableModel +{ + Q_OBJECT + + public: + LayoutsTableModel(Rules* rules, Flags *flags, KeyboardConfig* keyboardConfig, QObject *parent = 0); + + int columnCount(const QModelIndex&) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); +#ifdef DRAG_ENABLED + Qt::DropActions supportedDropActions() const { + return Qt::MoveAction; + } + QStringList mimeTypes() const; + QMimeData *mimeData(const QModelIndexList &indexes) const; +#endif + void refresh(); + + static const int MAP_COLUMN; + static const int LAYOUT_COLUMN; + static const int VARIANT_COLUMN; + static const int DISPLAY_NAME_COLUMN; + static const int SHORTCUT_COLUMN; + + private: + KeyboardConfig* keyboardConfig; + const Rules *rules; + Flags *countryFlags; +}; + +class LabelEditDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit LabelEditDelegate(const KeyboardConfig* keyboardConfig, QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + +// void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + +private: + const KeyboardConfig* keyboardConfig; +}; + +class VariantComboDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + VariantComboDelegate(const KeyboardConfig* keyboardConfig, const Rules* rules, QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + + void updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, const QModelIndex &index) const; + +private: + const KeyboardConfig* keyboardConfig; + const Rules* rules; +}; + +class KKeySequenceWidgetDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; +// void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + void paint(QPainter* painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const; + +private: + const KeyboardConfig* keyboardConfig; + mutable QSet itemsBeingEdited; +}; + + +class XkbOptionsTreeModel: public QAbstractItemModel +{ +public: + XkbOptionsTreeModel(Rules* rules_, KeyboardConfig* keyboardConfig_, QObject *parent) + : QAbstractItemModel(parent), + keyboardConfig(keyboardConfig_), + rules(rules_) { } + + int columnCount(const QModelIndex& /*parent*/) const { return 1; } + int rowCount(const QModelIndex& parent) const; + QModelIndex parent(const QModelIndex& index) const { + if (!index.isValid() ) + return QModelIndex(); + if( index.internalId() < 100 ) + return QModelIndex(); + return createIndex(((index.internalId() - index.row())/100) - 1, index.column()); + } + QModelIndex index(int row, int column, const QModelIndex& parent) const { + if(!parent.isValid()) return createIndex(row, column); + return createIndex(row, column, (100 * (parent.row()+1)) + row); + } + Qt::ItemFlags flags ( const QModelIndex & index ) const { + if( ! index.isValid() ) + return 0; + + if( !index.parent().isValid() ) + return Qt::ItemIsEnabled; + + return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; + } + + bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); + QVariant data(const QModelIndex& index, int role) const; + void reset() { QAbstractItemModel::reset(); } + void gotoGroup(const QString& group, QTreeView* view); + +private: + KeyboardConfig* keyboardConfig; + Rules *rules; +}; + +#endif /* KCM_VIEW_MODELS_H_ */ diff --git a/kcms/keyboard/kcmmisc.cpp b/kcms/keyboard/kcmmisc.cpp new file mode 100644 index 0000000000..6f787ea372 --- /dev/null +++ b/kcms/keyboard/kcmmisc.cpp @@ -0,0 +1,238 @@ +/* + * kcmmisc.cpp + * + * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca + * + * Layout management, cleanups: + * Copyright (c) 1999 Dirk A. Mueller + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "kcmmisc.h" +#include "ui_kcmmiscwidget.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +KCMiscKeyboardWidget::KCMiscKeyboardWidget(QWidget *parent) + : QWidget(parent), + ui(*new Ui_KeyboardConfigWidget) +{ + ui.setupUi(this); + + ui.delay->setRange(100, 5000, 50); + ui.delay->setSliderEnabled(false); + ui.rate->setRange(0.2, 50, 5, false); + + sliderMax = (int)floor (0.5 + 2*(log(5000.0L)-log(100.0L)) / (log(5000.0L)-log(4999.0L))); + ui.delaySlider->setRange(0, sliderMax); + ui.delaySlider->setSingleStep(sliderMax/100); + ui.delaySlider->setPageStep(sliderMax/10); + ui.delaySlider->setTickInterval(sliderMax/10); + + ui.rateSlider->setRange(20, 5000); + ui.rateSlider->setSingleStep(30); + ui.rateSlider->setPageStep(500); + ui.rateSlider->setTickInterval(498); + + connect(ui.keyboardRepeatButtonGroup, SIGNAL(clicked()), this, SLOT(changed())); + connect(ui.keyboardRepeatButtonGroup, SIGNAL(changed(int)), this, SLOT(keyboardRepeatStateChanged(int))); + connect(ui.delay, SIGNAL(valueChanged(int)), this, SLOT(delaySpinboxChanged(int))); + connect(ui.delaySlider, SIGNAL(valueChanged(int)), this, SLOT(delaySliderChanged(int))); + connect(ui.rate, SIGNAL(valueChanged(double)), this, SLOT(rateSpinboxChanged(double))); + connect(ui.rateSlider, SIGNAL(valueChanged(int)), this, SLOT(rateSliderChanged(int))); + + connect(ui.click, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(ui.numlockButtonGroup, SIGNAL(released(int)), this, SLOT(changed())); + +// Not sure why we need this - if XKB is not found the whole keyboard module won't be compiled +//#if !defined(HAVE_XTEST) && !defined(HAVE_XKB) +// ui.numlockButtonGroup->setDisabled( true ); +//#endif +//#if !defined(HAVE_XKB) && !defined(HAVE_XF86MISC) +// ui.delay->setDisabled( true ); +// ui.rate->setDisabled( true ); +//#endif +} + +KCMiscKeyboardWidget::~KCMiscKeyboardWidget() +{ + delete &ui; +} + +int KCMiscKeyboardWidget::getClick() +{ + return ui.click->value(); +} + +// set the slider and LCD values +void KCMiscKeyboardWidget::setRepeat(TriState keyboardRepeat, int delay_, double rate_) +{ + TriStateHelper::setTriState( ui.keyboardRepeatButtonGroup, keyboardRepeat ); +// ui.repeatBox->setChecked(r == AutoRepeatModeOn); + ui.delay->setValue(delay_); + ui.rate->setValue(rate_); + delaySpinboxChanged(delay_); + rateSpinboxChanged(rate_); +} + +void KCMiscKeyboardWidget::setClickVolume(int v) +{ + ui.click->setValue(v); +} + +TriState TriStateHelper::getTriState(const KButtonGroup* group) +{ + int selected = group->selected(); + return selected < 0 ? STATE_UNCHANGED : getTriState(selected); +} + +void TriStateHelper::setTriState(KButtonGroup* group, TriState state) +{ + group->setSelected( getInt(state) ); +} + +void KCMiscKeyboardWidget::load() +{ + KConfigGroup config(KSharedConfig::openConfig("kcminputrc", KConfig::NoGlobals), "Keyboard"); + + ui.delay->blockSignals(true); + ui.rate->blockSignals(true); + ui.click->blockSignals(true); + + // need to read as string to support old "true/false" parameter + QString key = config.readEntry("KeyboardRepeating", TriStateHelper::getString(STATE_ON)); + if( key == "true" || key == TriStateHelper::getString(STATE_ON)) { + keyboardRepeat = STATE_ON; + } + else if( key == "false" || key == TriStateHelper::getString(STATE_OFF)) { + keyboardRepeat = STATE_OFF; + } + else { + keyboardRepeat = STATE_UNCHANGED; + } + +// keyboardRepeat = (key ? AutoRepeatModeOn : AutoRepeatModeOff); + float delay = config.readEntry( "RepeatDelay", 660 ); + float rate = config.readEntry( "RepeatRate", 25. ); + setRepeat(keyboardRepeat, delay, rate); + + XKeyboardState kbd; + XGetKeyboardControl(QX11Info::display(), &kbd); + + clickVolume = config.readEntry("ClickVolume", kbd.key_click_percent); + setClickVolume(clickVolume); + // setRepeat(kbd.global_auto_repeat, ui.delay->value(), ui.rate->value()); + + numlockState = TriStateHelper::getTriState(config.readEntry( "NumLock", TriStateHelper::getInt(STATE_UNCHANGED) )); + TriStateHelper::setTriState( ui.numlockButtonGroup, numlockState ); + + ui.delay->blockSignals(false); + ui.rate->blockSignals(false); + ui.click->blockSignals(false); +} + +void KCMiscKeyboardWidget::save() +{ + KConfigGroup config(KSharedConfig::openConfig("kcminputrc", KConfig::NoGlobals), "Keyboard"); + + clickVolume = getClick(); + keyboardRepeat = TriStateHelper::getTriState(ui.keyboardRepeatButtonGroup); + numlockState = TriStateHelper::getTriState(ui.numlockButtonGroup); + + config.writeEntry("ClickVolume",clickVolume); + config.writeEntry("KeyboardRepeating", TriStateHelper::getInt(keyboardRepeat)); + config.writeEntry("RepeatRate", ui.rate->value() ); + config.writeEntry("RepeatDelay", ui.delay->value() ); + config.writeEntry("NumLock", TriStateHelper::getInt(numlockState) ); + config.sync(); +} + +void KCMiscKeyboardWidget::defaults() +{ + setClickVolume(50); + setRepeat(STATE_ON, 660, 25); + TriStateHelper::setTriState( ui.numlockButtonGroup, STATE_UNCHANGED ); + emit changed(true); +} + +QString KCMiscKeyboardWidget::quickHelp() const +{ + return QString(); + + /* "

    Keyboard

    This module allows you to choose options" + " for the way in which your keyboard works. The actual effect of" + " setting these options depends upon the features provided by your" + " keyboard hardware and the X server on which KDE is running.

    " + " For example, you may find that changing the key click volume" + " has no effect because this feature is not available on your system." */ +} + +void KCMiscKeyboardWidget::delaySliderChanged (int value) { + double alpha = sliderMax / (log(5000.0L) - log(100.0L)); + double linearValue = exp (value/alpha + log(100.0L)); + + ui.delay->setValue((int)floor(0.5 + linearValue)); + + emit changed(true); +} + +void KCMiscKeyboardWidget::delaySpinboxChanged (int value) { + double alpha = sliderMax / (log(5000.0L) - log(100.0L)); + double logVal = alpha * (log((double)value)-log(100.0L)); + + ui.delaySlider->setValue ((int)floor (0.5 + logVal)); + + emit changed(true); +} + +void KCMiscKeyboardWidget::rateSliderChanged (int value) { + ui.rate->setValue(value/100.0); + + emit changed(true); +} + +void KCMiscKeyboardWidget::rateSpinboxChanged (double value) { + ui.rateSlider->setValue ((int)(value*100)); + + emit changed(true); +} + +void KCMiscKeyboardWidget::changed() +{ + emit changed(true); +} + +void KCMiscKeyboardWidget::keyboardRepeatStateChanged(int selection) +{ + bool enabled = selection == TriStateHelper::getInt(STATE_ON); + ui.keyboardRepeatParamsGroupBox->setEnabled(enabled); + changed(); +} diff --git a/kcms/keyboard/kcmmisc.h b/kcms/keyboard/kcmmisc.h new file mode 100644 index 0000000000..411bdd2b0f --- /dev/null +++ b/kcms/keyboard/kcmmisc.h @@ -0,0 +1,91 @@ +/* + * keyboard.h + * + * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __KCMMISC_H__ +#define __KCMMISC_H__ + +#include +#include + +class Ui_KeyboardConfigWidget; + +enum TriState { + STATE_ON = 0, STATE_OFF = 1, STATE_UNCHANGED = 2 +}; + +class KButtonGroup; +class TriStateHelper { +public: + static void setTriState(KButtonGroup* group, TriState state); + static TriState getTriState(const KButtonGroup* group); + + static TriState getTriState(int state) { return static_cast(state); } + static int getInt(TriState state) { return static_cast(state); } + static const char* getString(TriState state) { + return state == STATE_ON ? "0" : state == STATE_OFF ? "1" : "2"; + } +}; + +class KCMiscKeyboardWidget : public QWidget +{ + Q_OBJECT +public: + KCMiscKeyboardWidget(QWidget *parent); + ~KCMiscKeyboardWidget(); + + void save(); + void load(); + void defaults(); + + QString quickHelp() const; + +private Q_SLOTS: + void changed(); + + void delaySliderChanged (int value); + void delaySpinboxChanged (int value); + void rateSliderChanged (int value); + void rateSpinboxChanged (double value); + void keyboardRepeatStateChanged(int selection); + +Q_SIGNALS: + void changed(bool state); + +private: + void setClickVolume( int ); + void setRepeat( TriState flag, int delay, double rate); + void setRepeatRate( int ); + + int getClick(); + int getRepeatRate(); + + int sliderMax; + int clickVolume; + enum TriState keyboardRepeat; + enum TriState numlockState; + + Ui_KeyboardConfigWidget& ui; +}; + +#endif + diff --git a/kcms/keyboard/kcmmiscwidget.ui b/kcms/keyboard/kcmmiscwidget.ui new file mode 100644 index 0000000000..37fbaf4b9c --- /dev/null +++ b/kcms/keyboard/kcmmiscwidget.ui @@ -0,0 +1,335 @@ + + + KeyboardConfigWidget + + + + 0 + 0 + 577 + 361 + + + + + + + If supported, this option allows you to setup the state of NumLock after KDE startup.<p>You can configure NumLock to be turned on or off, or configure KDE not to set NumLock state. + + + NumLock on KDE Startup + + + + + + true + + + + + + T&urn on + + + + + + + Turn o&ff + + + + + + + Leave unchan&ged + + + + + + + + + + + + + Keyboard Repeat + + + + + + true + + + + + + T&urn on + + + + + + + Turn o&ff + + + + + + + Leave unchan&ged + + + + + + + + + + Qt::Horizontal + + + + 159 + 20 + + + + + + + + + + + false + + + + + + + 0 + 0 + + + + &Delay: + + + delay + + + + + + + If supported, this option allows you to set the delay after which a pressed key will start generating keycodes. The 'Repeat rate' option controls the frequency of these keycodes. + + + 0 + + + 10000 + + + 1000 + + + 1000 + + + 5000 + + + Qt::Horizontal + + + 1000 + + + + + + + If supported, this option allows you to set the delay after which a pressed key will start generating keycodes. The 'Repeat rate' option controls the frequency of these keycodes. + + + ms + + + + + + + + 0 + 0 + + + + &Rate: + + + rate + + + + + + + If supported, this option allows you to set the rate at which keycodes are generated while a key is pressed. + + + 0 + + + 10000 + + + 1000 + + + 1000 + + + 5000 + + + Qt::Horizontal + + + 1000 + + + + + + + If supported, this option allows you to set the rate at which keycodes are generated while a key is pressed. + + + repeats/s + + + + + + + + + + + + + + + + + + Test area: + + + + + + + Allows to test keyboard repeat and click volume (just don't forget to apply the changes). + + + + + + + + + Key Click + + + + + + + + If supported, this option allows you to hear audible clicks from your computer's speakers when you press the keys on your keyboard. This might be useful if your keyboard does not have mechanical keys, or if the sound that the keys make is very soft.<p>You can change the loudness of the key click feedback by dragging the slider button or by clicking the up/down arrows on the spin box. Setting the volume to 0% turns off the key click. + + + Key click &volume: + + + click + + + + + + + 100 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + KDoubleNumInput + QWidget +

    knuminput.h
    + 1 + + + KButtonGroup + QGroupBox +
    kbuttongroup.h
    + 1 +
    + + KIntNumInput + QWidget +
    knuminput.h
    + 1 +
    + + + + diff --git a/kcms/keyboard/keyboard.desktop b/kcms/keyboard/keyboard.desktop new file mode 100644 index 0000000000..4f4e97b610 --- /dev/null +++ b/kcms/keyboard/keyboard.desktop @@ -0,0 +1,75 @@ +[Desktop Entry] +Type=Service +Icon=preferences-desktop-keyboard +X-KDE-ServiceTypes=KDEDModule +X-KDE-Library=keyboard +X-KDE-DBus-ModuleName=keyboard +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=false +X-KDE-Kded-phase=1 +OnlyShowIn=KDE; + +Name=Keyboard Daemon +Name[ar]=مراقب لوحة المفاتيح +Name[ast]=Degorriu de tecláu +Name[bg]=Демон на клавиатурата +Name[bn]=কীবোর্ড ডীমন +Name[bs]=Demon tastature +Name[ca]=Dimoni del teclat +Name[ca@valencia]=Dimoni del teclat +Name[cs]=Démon klávesnice +Name[da]=Tastatur-dæmon +Name[de]=Tastatur-Dienst +Name[el]=Δαίμονας Πληκτρολογίου +Name[en_GB]=Keyboard Dæmon +Name[es]=Demonio de teclado +Name[et]=Klaviatuurideemon +Name[eu]=Teklatuaren daimona +Name[fi]=Näppäimistötaustaprosessi +Name[fr]=Démon du clavier +Name[ga]=Deamhan Méarchláir +Name[gl]=Servizo do teclado +Name[gu]=કીબોર્ડ ડિમન +Name[he]=תהליך רקע של המקלדת +Name[hi]=कुंजीपट डेमन +Name[hr]=Tipkovnički servis +Name[hu]=Billentyűzetszolgáltatás +Name[ia]=Demone de claviero +Name[id]=Jurik Papan Ketik +Name[is]=Lyklaborðspúki +Name[it]=Demone della tastiera +Name[ja]=キーボードデーモン +Name[kk]=Перенетақта қызметі +Name[km]=ដេមិន​​ក្ដារចុច +Name[kn]=ಕೀಲಿಮಣೆ ನೇಪಥಿಕ +Name[ko]=키보드 데몬 +Name[lt]=Klaviatūros tarnyba +Name[lv]=Tastatūras dēmons +Name[mr]=कळफलक डीमन +Name[nb]=Tastatur-nisse +Name[nds]=Tastatuur-Dämoon +Name[nl]=Toetsenbord-daemon +Name[nn]=Tastaturteneste +Name[pa]=ਕੀ-ਬੋਰਡ ਡੈਮਨ +Name[pl]=Demon klawiatury +Name[pt]=Servidor do Teclado +Name[pt_BR]=Daemon de teclado +Name[ro]=Demon de tastatură +Name[ru]=Фоновая служба клавиатуры +Name[si]=යතුරුපුවරු ඩීමනය +Name[sk]=Démon klávesnice +Name[sl]=Ozadnji program za tipkovnico +Name[sr]=Демон тастатуре +Name[sr@ijekavian]=Демон тастатуре +Name[sr@ijekavianlatin]=Demon tastature +Name[sr@latin]=Demon tastature +Name[sv]=Tangentbordsdemon +Name[th]=ดีมอนแป้นพิมพ์ +Name[tr]=Klavye Servisi +Name[ug]=ھەرپتاختا نازارەتچى +Name[uk]=Фонова служба клавіатури +Name[vi]=Trình nền bàn phím +Name[wa]=Démon del taprece +Name[x-test]=xxKeyboard Daemonxx +Name[zh_CN]=键盘守护进程 +Name[zh_TW]=鍵盤伺服程式 diff --git a/kcms/keyboard/keyboard_applet.cpp b/kcms/keyboard/keyboard_applet.cpp new file mode 100644 index 0000000000..85422d8bda --- /dev/null +++ b/kcms/keyboard/keyboard_applet.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "keyboard_applet.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "x11_helper.h" +#include "xkb_rules.h" +#include "keyboard_config.h" +#include "keyboard_dbus.h" +#include "layouts_menu.h" +//#include "utils.h" + + +K_EXPORT_PLASMA_APPLET(keyboard, KeyboardApplet) + +KeyboardApplet::KeyboardApplet(QObject *parent, const QVariantList &args): + Plasma::Applet(parent, args), + xEventNotifier(), + rules(Rules::readRules(Rules::READ_EXTRAS)), + keyboardConfig(new KeyboardConfig()), + layoutsMenu(new LayoutsMenu(*keyboardConfig, *rules, flags)) +{ + if( ! X11Helper::xkbSupported(NULL) ) { + setFailedToLaunch(true, i18n("XKB extension failed to initialize")); + return; + } + + m_svg = new Plasma::Svg(this); + m_svg->setImagePath("widgets/labeltexture"); + m_svg->setContainsMultipleImages(true); + resize(48,48); + + setHasConfigurationInterface(false); + + setAspectRatioMode(Plasma::KeepAspectRatio); + //setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); + setBackgroundHints(DefaultBackground); + connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeChanged())); + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configChanged())); +} + +KeyboardApplet::~KeyboardApplet() +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.disconnect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configChanged())); + + delete layoutsMenu; + delete rules; +} + +void KeyboardApplet::keyboardConfigChanged() +{ + readConfig(); + update(); +} + +void KeyboardApplet::readConfig() +{ +// KConfigGroup config = Plasma::Applet::config("KeyboardLayout"); + keyboardConfig->load(); +// drawFlag = keyboardConfig->readEntry("ShowFlag", true); +} + +void KeyboardApplet::configChanged() +{ + Applet::configChanged(); + readConfig(); +} + +void KeyboardApplet::init() +{ + Applet::init(); + + readConfig(); + connect(&xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + connect(&xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutChanged())); + xEventNotifier.start(); + + layoutChanged(); +} + +void KeyboardApplet::destroy() +{ + xEventNotifier.stop(); + disconnect(&xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutChanged())); + disconnect(&xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + Applet::destroy(); +} + +void KeyboardApplet::layoutChanged() +{ + generatePixmap(); + updateTooltip(); + update(); +} + +void KeyboardApplet::updateTooltip() +{ + LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); + if( layoutUnit.isEmpty() ) + return; + + const QIcon icon(getFlag(layoutUnit.layout)); + Plasma::ToolTipContent data(name(), flags.getLongText(layoutUnit, rules), icon); + Plasma::ToolTipManager::self()->setContent(this, data); +} + +const QIcon KeyboardApplet::getFlag(const QString& layout) +{ + return keyboardConfig->isFlagShown() ? flags.getIcon(layout) : QIcon(); +} + +void KeyboardApplet::paintInterface(QPainter *p, const QStyleOptionGraphicsItem */*option*/, const QRect &contentsRect) +{ + LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); + if( layoutUnit.isEmpty() ) + return; + + const QIcon icon(getFlag(layoutUnit.layout)); + if( ! icon.isNull() ) { + p->save(); + p->setRenderHint(QPainter::SmoothPixmapTransform); + p->setRenderHint(QPainter::Antialiasing); + QPixmap pixmap = icon.pixmap(contentsRect.size()); + p->drawPixmap(contentsRect, pixmap); + p->restore(); + } + if( icon.isNull() || keyboardConfig->isLabelShown() ) { + QRect finalRect(m_pixmap.rect()); + finalRect.moveCenter(contentsRect.center()); + p->drawPixmap(finalRect, m_pixmap); + } +} + +void KeyboardApplet::mousePressEvent ( QGraphicsSceneMouseEvent * event ) +{ + if( event->button() == Qt::LeftButton ) { + X11Helper::switchToNextLayout(); + } + event->ignore(); +} + +void KeyboardApplet::constraintsEvent(Plasma::Constraints constraints) +{ + if (constraints & Plasma::FormFactorConstraint) { + int iconSize; + if (formFactor() == Plasma::Planar || + formFactor() == Plasma::MediaCenter) { + iconSize = IconSize(KIconLoader::Desktop); + } else { + iconSize = IconSize(KIconLoader::Small); + } + setMinimumSize(iconSize, iconSize); + } + if (constraints & Plasma::SizeConstraint) { + generatePixmap(); + } +} + +void KeyboardApplet::generatePixmap() +{ + LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); + QRect contentsRect = KeyboardApplet::contentsRect().toRect(); + QString shortText = Flags::getShortText(layoutUnit, *keyboardConfig); + + QPixmap pixmap(contentsRect.size()); + pixmap.fill(Qt::transparent); + + QFont font = Plasma::Theme::defaultTheme()->font(Plasma::Theme::DesktopFont); + int height = qMin(contentsRect.height(), contentsRect.width()); + int fontSize = shortText.length() == 2 + ? height * 13 / 15 + : height * 5 / 15; + + int smallestReadableSize = KGlobalSettings::smallestReadableFont().pixelSize(); + if( fontSize < smallestReadableSize ) { + fontSize = smallestReadableSize; + } + font.setPixelSize(fontSize); + if( keyboardConfig->isFlagShown() ) { + m_pixmap = Plasma::PaintUtils::shadowText(shortText, font, Qt::black, Qt::white, QPoint(), 3); + } + else { + m_pixmap = Plasma::PaintUtils::texturedText(shortText, font, m_svg); + } +} + +QList KeyboardApplet::contextualActions() +{ + return layoutsMenu->contextualActions(); +} diff --git a/kcms/keyboard/keyboard_applet.h b/kcms/keyboard/keyboard_applet.h new file mode 100644 index 0000000000..2fb9c98fde --- /dev/null +++ b/kcms/keyboard/keyboard_applet.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KEYBOARD_APPLET_H_ +#define KEYBOARD_APPLET_H_ + +#include + +#include + +#include "x11_helper.h" +#include "flags.h" + +class QGraphicsSceneMouseEvent; +class QAction; +class KConfigDialog; +class QActionGroup; +class Rules; +class KeyboardConfig; +class LayoutsMenu; + +class KeyboardApplet : public Plasma::Applet +{ + Q_OBJECT + +public Q_SLOTS: + void init(); + void destroy(); + +private Q_SLOTS: + void configChanged(); + void layoutChanged(); + +public: + KeyboardApplet(QObject *parent, const QVariantList &args); + virtual ~KeyboardApplet(); + + void constraintsEvent(Plasma::Constraints constraints); + void paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect); + +protected: + void mousePressEvent ( QGraphicsSceneMouseEvent *event ); + QList contextualActions(); + void generatePixmap(); +// void createConfigurationInterface(KConfigDialog *parent); + +private Q_SLOTS: + void keyboardConfigChanged(); + +private: + void readConfig(); + const QIcon getFlag(const QString& layout); + void updateTooltip(); + +// bool drawFlag; + Flags flags; + XEventNotifier xEventNotifier; + const Rules* rules; + KeyboardConfig* keyboardConfig; + LayoutsMenu* layoutsMenu; + Plasma::Svg *m_svg; + QPixmap m_pixmap; +}; + +#endif /* KEYBOARD_APPLET_H_ */ diff --git a/kcms/keyboard/keyboard_config.cpp b/kcms/keyboard/keyboard_config.cpp new file mode 100644 index 0000000000..f3ff97ca84 --- /dev/null +++ b/kcms/keyboard/keyboard_config.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "keyboard_config.h" + +#include +#include +#include + + +static const char* SWITCHING_POLICIES[] = {"Global", "Desktop", "WinClass", "Window", NULL }; +static const char* LIST_SEPARATOR = ","; +//static const char* DEFAULT_LAYOUT = "us"; +static const char* DEFAULT_MODEL = "pc104"; + +static const QString CONFIG_FILENAME("kxkbrc"); +static const QString CONFIG_GROUPNAME("Layout"); + +const int KeyboardConfig::NO_LOOPING = -1; + +KeyboardConfig::KeyboardConfig() +{ + setDefaults(); +} + +QString KeyboardConfig::getSwitchingPolicyString(SwitchingPolicy switchingPolicy) { + return SWITCHING_POLICIES[switchingPolicy]; +} + +static int findStringIndex(const char* strings[], const QString& toFind, int defaultIndex) +{ + for(int i=0; strings[i] != NULL; i++) { + if( toFind == strings[i] ) { + return i; + } + } + return defaultIndex; +} + +void KeyboardConfig::setDefaults() +{ + keyboardModel = DEFAULT_MODEL; + resetOldXkbOptions = false; + xkbOptions.clear(); + + // init layouts options + configureLayouts = false; + layouts.clear(); +// layouts.append(LayoutUnit(DEFAULT_LAYOUT)); + layoutLoopCount = NO_LOOPING; + + // switch cotrol options + switchingPolicy = SWITCH_POLICY_GLOBAL; +// stickySwitching = false; +// stickySwitchingDepth = 2; + + // display options + showIndicator = true; + indicatorType = SHOW_LABEL; + showSingle = false; +} + +static +KeyboardConfig::IndicatorType getIndicatorType(bool showFlag, bool showLabel) +{ + if( showFlag ) { + if( showLabel ) + return KeyboardConfig::SHOW_LABEL_ON_FLAG; + else + return KeyboardConfig::SHOW_FLAG; + } + else { + return KeyboardConfig::SHOW_LABEL; + } +} + + +void KeyboardConfig::load() +{ + KConfigGroup config(KSharedConfig::openConfig( CONFIG_FILENAME, KConfig::NoGlobals ), CONFIG_GROUPNAME); + + keyboardModel = config.readEntry("Model", ""); + + resetOldXkbOptions = config.readEntry("ResetOldOptions", false); + QString options = config.readEntry("Options", ""); + xkbOptions = options.split(LIST_SEPARATOR, QString::SkipEmptyParts); + + configureLayouts = config.readEntry("Use", false); + QString layoutsString = config.readEntry("LayoutList", ""); + QStringList layoutStrings = layoutsString.split(LIST_SEPARATOR, QString::SkipEmptyParts); +// if( layoutStrings.isEmpty() ) { +// layoutStrings.append(DEFAULT_LAYOUT); +// } + layouts.clear(); + foreach(const QString& layoutString, layoutStrings) { + layouts.append(LayoutUnit(layoutString)); + } + if( layouts.isEmpty() ) { + configureLayouts = false; + } + + layoutLoopCount = config.readEntry("LayoutLoopCount", NO_LOOPING); + + QString layoutMode = config.readEntry("SwitchMode", "Global"); + switchingPolicy = static_cast(findStringIndex(SWITCHING_POLICIES, layoutMode, SWITCH_POLICY_GLOBAL)); + + showIndicator = config.readEntry("ShowLayoutIndicator", true); + + bool showFlag = config.readEntry("ShowFlag", false); + bool showLabel = config.readEntry("ShowLabel", true); + indicatorType = getIndicatorType(showFlag, showLabel); + + showSingle = config.readEntry("ShowSingle", false); + + QString labelsStr = config.readEntry("DisplayNames", ""); + QStringList labels = labelsStr.split(LIST_SEPARATOR, QString::KeepEmptyParts); + for(int i=0; i KeyboardConfig::getDefaultLayouts() const +{ + QList defaultLayoutList; + int i = 0; + foreach(const LayoutUnit& layoutUnit, layouts) { + defaultLayoutList.append(layoutUnit); + if( layoutLoopCount != KeyboardConfig::NO_LOOPING && i >= layoutLoopCount-1 ) + break; + i++; + } + return defaultLayoutList; +} + +QList KeyboardConfig::getExtraLayouts() const +{ + if( layoutLoopCount == KeyboardConfig::NO_LOOPING ) + return QList(); + + return layouts.mid(layoutLoopCount, layouts.size()); +} diff --git a/kcms/keyboard/keyboard_config.h b/kcms/keyboard/keyboard_config.h new file mode 100644 index 0000000000..b86418de47 --- /dev/null +++ b/kcms/keyboard/keyboard_config.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KEYBOARD_CONFIG_H_ +#define KEYBOARD_CONFIG_H_ + +#include "x11_helper.h" + +#include +#include +#include +#include +#include + +/** + * This class provides configuration options for keyboard module + */ +class KeyboardConfig +{ +public: + static const int MAX_LABEL_LEN = 3; + static const int NO_LOOPING; // = -1; + + enum SwitchingPolicy { + SWITCH_POLICY_GLOBAL = 0, + SWITCH_POLICY_DESKTOP = 1, + SWITCH_POLICY_APPLICATION = 2, + SWITCH_POLICY_WINDOW = 3 + }; + + enum IndicatorType { + SHOW_LABEL = 0, + SHOW_FLAG = 1, + SHOW_LABEL_ON_FLAG = 2 + }; + + QString keyboardModel; + // resetOldXkbOptions is now also "set xkb options" + bool resetOldXkbOptions; + QStringList xkbOptions; + + // init layouts options + bool configureLayouts; + QList layouts; + int layoutLoopCount; + + // switch cotrol options + SwitchingPolicy switchingPolicy; +// bool stickySwitching; +// int stickySwitchingDepth; + + // display options + bool showIndicator; + IndicatorType indicatorType; + bool showSingle; + + KeyboardConfig(); + bool isSpareLayoutsEnabled() const { + return layoutLoopCount != KeyboardConfig::NO_LOOPING; + } + QList getDefaultLayouts() const; + QList getExtraLayouts() const; + bool isFlagShown() const { + return indicatorType == SHOW_FLAG || indicatorType == SHOW_LABEL_ON_FLAG; + } + bool isLabelShown() const { + return indicatorType == SHOW_LABEL || indicatorType == SHOW_LABEL_ON_FLAG; + } + + void setDefaults(); + void load(); + void save(); + + static QString getSwitchingPolicyString(SwitchingPolicy switchingPolicy); +}; + +#endif /* KEYBOARD_CONFIG_H_ */ diff --git a/kcms/keyboard/keyboard_daemon.cpp b/kcms/keyboard/keyboard_daemon.cpp new file mode 100644 index 0000000000..825cca45fb --- /dev/null +++ b/kcms/keyboard/keyboard_daemon.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "keyboard_daemon.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x11_helper.h" +#if 0 +#include "xinput_helper.h" +#endif +#include "xkb_helper.h" +#include "keyboard_dbus.h" +#include "xkb_rules.h" +#include "bindings.h" +#include "keyboard_hardware.h" +#include "layout_tray_icon.h" +#include "layout_memory_persister.h" +#include "layouts_menu.h" + + +K_PLUGIN_FACTORY(KeyboardFactory, registerPlugin();) +K_EXPORT_PLUGIN(KeyboardFactory("keyboard", "kxkb")) + +KeyboardDaemon::KeyboardDaemon(QObject *parent, const QList&) + : KDEDModule(parent), + actionCollection(NULL), + xEventNotifier(NULL), + layoutTrayIcon(NULL), + layoutMemory(keyboardConfig), + rules(Rules::readRules(Rules::READ_EXTRAS)) +{ + if( ! X11Helper::xkbSupported(NULL) ) + return; //TODO: shut down the daemon? + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerService(KEYBOARD_DBUS_SERVICE_NAME); + dbus.registerObject(KEYBOARD_DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals); + dbus.connect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); + + configureKeyboard(); + registerListeners(); + + LayoutMemoryPersister layoutMemoryPersister(layoutMemory); + if( layoutMemoryPersister.restore("kxkb") ) { + if( layoutMemoryPersister.getGlobalLayout().isValid() ) { + X11Helper::setLayout(layoutMemoryPersister.getGlobalLayout()); + } + } +} + +KeyboardDaemon::~KeyboardDaemon() +{ + LayoutMemoryPersister layoutMemoryPersister(layoutMemory); + layoutMemoryPersister.setGlobalLayout(X11Helper::getCurrentLayout()); + layoutMemoryPersister.save("kxkb"); + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.disconnect(QString(), KEYBOARD_DBUS_OBJECT_PATH, KEYBOARD_DBUS_SERVICE_NAME, KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE, this, SLOT(configureKeyboard())); + dbus.unregisterObject(KEYBOARD_DBUS_OBJECT_PATH); + dbus.unregisterService(KEYBOARD_DBUS_SERVICE_NAME); + + unregisterListeners(); + unregisterShortcut(); + + delete xEventNotifier; + delete layoutTrayIcon; + delete rules; +} + +void KeyboardDaemon::configureKeyboard() +{ + kDebug() << "Configuring keyboard"; + init_keyboard_hardware(); + + keyboardConfig.load(); + XkbHelper::initializeKeyboardLayouts(keyboardConfig); + layoutMemory.configChanged(); + + setupTrayIcon(); + + unregisterShortcut(); + registerShortcut(); +} + +void KeyboardDaemon::configureMouse() +{ + QStringList modules; + modules << "mouse"; + QProcess::startDetached("kcminit", modules); +} + +void KeyboardDaemon::setupTrayIcon() +{ + bool show = keyboardConfig.showIndicator + && ( keyboardConfig.showSingle || X11Helper::getLayoutsList().size() > 1 ); + + if( show && ! layoutTrayIcon ) { + layoutTrayIcon = new LayoutTrayIcon(rules, keyboardConfig); + } + else if( ! show && layoutTrayIcon ) { + delete layoutTrayIcon; + layoutTrayIcon = NULL; + } +} + +void KeyboardDaemon::registerShortcut() +{ + if( actionCollection == NULL ) { + actionCollection = new KeyboardLayoutActionCollection(this, false); + + QAction* toggleLayoutAction = actionCollection->getToggeAction(); + connect(toggleLayoutAction, SIGNAL(triggered()), this, SLOT(switchToNextLayout())); + actionCollection->loadLayoutShortcuts(keyboardConfig.layouts, rules); + connect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); + + connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), this, SLOT(globalSettingsChanged(int))); + } +} + +void KeyboardDaemon::unregisterShortcut() +{ + // register KDE keyboard shortcut for switching layouts + if( actionCollection != NULL ) { + disconnect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), this, SLOT(globalSettingsChanged(int))); + + disconnect(actionCollection, SIGNAL(actionTriggered(QAction*)), this, SLOT(setLayout(QAction*))); + disconnect(actionCollection->getToggeAction(), SIGNAL(triggered()), this, SLOT(switchToNextLayout())); + + delete actionCollection; + actionCollection = NULL; + } +} + +void KeyboardDaemon::registerListeners() +{ +#warning XInputEventNotifier needs porting to QAbstractNativeEventFilter +#if 0 + if( xEventNotifier == NULL ) { + xEventNotifier = new XInputEventNotifier(); + } + connect(xEventNotifier, SIGNAL(newPointerDevice()), this, SLOT(configureMouse())); + connect(xEventNotifier, SIGNAL(newKeyboardDevice()), this, SLOT(configureKeyboard())); + connect(xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutMapChanged())); + connect(xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + xEventNotifier->start(); +#endif +} + +void KeyboardDaemon::unregisterListeners() +{ +#warning XInputEventNotifier needs porting to QAbstractNativeEventFilter +#if 0 + if( xEventNotifier != NULL ) { + xEventNotifier->stop(); + disconnect(xEventNotifier, SIGNAL(newPointerDevice()), this, SLOT(configureMouse())); + disconnect(xEventNotifier, SIGNAL(newKeyboardDevice()), this, SLOT(configureKeyboard())); + disconnect(xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + disconnect(xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutMapChanged())); + } +#endif +} + +void KeyboardDaemon::globalSettingsChanged(int category) +{ + if ( category == KGlobalSettings::SETTINGS_SHORTCUTS) { +//TODO: optimize this? seems like we'll get configReload and globalShortcuts from kcm so we'll reconfigure twice + unregisterShortcut(); + registerShortcut(); + } +} + +void KeyboardDaemon::layoutChanged() +{ + //TODO: pass newLayout into layoutTrayIcon? + LayoutUnit newLayout = X11Helper::getCurrentLayout(); + + layoutMemory.layoutChanged(); + if( layoutTrayIcon != NULL ) { + layoutTrayIcon->layoutChanged(); + } + + if( newLayout != currentLayout ) { + currentLayout = newLayout; + emit currentLayoutChanged(newLayout.toString()); + } +} + +void KeyboardDaemon::layoutMapChanged() +{ + keyboardConfig.load(); + layoutMemory.layoutMapChanged(); + emit layoutListChanged(); + if( layoutTrayIcon != NULL ) { + layoutTrayIcon->layoutMapChanged(); + } +} + +void KeyboardDaemon::switchToNextLayout() +{ + kDebug() << "Toggling layout"; + X11Helper::switchToNextLayout(); +} + +bool KeyboardDaemon::setLayout(QAction* action) +{ + if( action == actionCollection->getToggeAction() ) + return false; + + LayoutUnit layoutUnit(action->data().toString()); + return LayoutsMenu::switchToLayout(layoutUnit, keyboardConfig); // need this to be able to switch to spare layouts +// return X11Helper::setLayout(LayoutUnit(action->data().toString())); +} + +bool KeyboardDaemon::setLayout(const QString& layout) +{ + return X11Helper::setLayout(LayoutUnit(layout)); +} + +QString KeyboardDaemon::getCurrentLayout() +{ + return X11Helper::getCurrentLayout().toString(); +} + +QStringList KeyboardDaemon::getLayoutsList() +{ + return X11Helper::getLayoutsListAsString( X11Helper::getLayoutsList() ); +} + +#include "keyboard_daemon.moc" diff --git a/kcms/keyboard/keyboard_daemon.h b/kcms/keyboard/keyboard_daemon.h new file mode 100644 index 0000000000..4edb968bb0 --- /dev/null +++ b/kcms/keyboard/keyboard_daemon.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KEYBOARD_DAEMON_H_ +#define KEYBOARD_DAEMON_H_ + +#include +#include +#include + +#include "layout_memory.h" +#include "keyboard_dbus.h" +#include "bindings.h" + + +class KActionCollection; +class XInputEventNotifier; +class LayoutTrayIcon; +class KeyboardConfig; +class KAction; +class Rules; + +class Q_DECL_EXPORT KeyboardDaemon : public KDEDModule +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.KeyboardLayouts") + + KeyboardConfig keyboardConfig; + KeyboardLayoutActionCollection *actionCollection; + XInputEventNotifier* xEventNotifier; + LayoutTrayIcon* layoutTrayIcon; + LayoutMemory layoutMemory; + LayoutUnit currentLayout; + const Rules* rules; + + void registerListeners(); + void registerShortcut(); + void unregisterListeners(); + void unregisterShortcut(); + void setupTrayIcon(); + +private Q_SLOTS: + void switchToNextLayout(); + void globalSettingsChanged(int category); + void configureKeyboard(); + void configureMouse(); + void layoutChanged(); + void layoutMapChanged(); + bool setLayout(QAction* action); + +public Q_SLOTS: + Q_SCRIPTABLE bool setLayout(const QString& layout); + Q_SCRIPTABLE QString getCurrentLayout(); + Q_SCRIPTABLE QStringList getLayoutsList(); + +Q_SIGNALS: + Q_SCRIPTABLE void currentLayoutChanged(QString layout); + Q_SCRIPTABLE void layoutListChanged(); + +public: + KeyboardDaemon(QObject *parent, const QList&); + virtual ~KeyboardDaemon(); +}; + +#endif /* KEYBOARD_DAEMON_H_ */ diff --git a/kcms/keyboard/keyboard_dbus.h b/kcms/keyboard/keyboard_dbus.h new file mode 100644 index 0000000000..4ea39668d7 --- /dev/null +++ b/kcms/keyboard/keyboard_dbus.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KEYBOARD_DBUS_H_ +#define KEYBOARD_DBUS_H_ + +#define KEYBOARD_DBUS_SERVICE_NAME "org.kde.keyboard" +#define KEYBOARD_DBUS_OBJECT_PATH "/Layouts" +#define KEYBOARD_DBUS_CONFIG_RELOAD_MESSAGE "reloadConfig" + +#endif /* KEYBOARD_DBUS_H_ */ diff --git a/kcms/keyboard/keyboard_hardware.cpp b/kcms/keyboard/keyboard_hardware.cpp new file mode 100644 index 0000000000..dca49b6740 --- /dev/null +++ b/kcms/keyboard/keyboard_hardware.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 +#include +#include + +#include +#include // WTF? - otherwise compiler complains + +#include + +#include + +#include "x11_helper.h" +#include "kcmmisc.h" + +// from numlockx.c +extern "C" void numlockx_change_numlock_state(Display* dpy, int state); + +#include +#include + + +// This code is taken from xset utility from XFree 4.3 (http://www.xfree86.org/) + +static +void set_repeatrate(int delay, double rate) +{ + if( !X11Helper::xkbSupported(NULL) ) { + kError() << "Failed to set keyboard repeat rate: xkb is not supported"; + return; + } + + XkbDescPtr xkb = XkbAllocKeyboard(); + if (xkb) { + Display* dpy = QX11Info::display(); + int res = XkbGetControls(dpy, XkbRepeatKeysMask, xkb); + xkb->ctrls->repeat_delay = delay; + xkb->ctrls->repeat_interval = (int)floor(1000/rate + 0.5); + res = XkbSetControls(dpy, XkbRepeatKeysMask, xkb); + XkbFreeKeyboard(xkb, 0, true); + return; + } +} + +static +int set_volume(int clickVolumePercent, TriState keyboardRepeatMode) +{ + XKeyboardState kbd; + XKeyboardControl kbdc; + + XGetKeyboardControl(QX11Info::display(), &kbd); + + int flags = 0; + if( clickVolumePercent != -1 ) { + flags |= KBKeyClickPercent; + kbdc.key_click_percent = clickVolumePercent; + } + if( keyboardRepeatMode != STATE_UNCHANGED ) { + flags |= KBAutoRepeatMode; + kbdc.auto_repeat_mode = (keyboardRepeatMode==STATE_ON ? AutoRepeatModeOn : AutoRepeatModeOff); + } + + return XChangeKeyboardControl(QX11Info::display(), flags, &kbdc); +} + +void init_keyboard_hardware() +{ + KConfigGroup config(KSharedConfig::openConfig( "kcminputrc" ), "Keyboard"); + + QString keyRepeatStr = config.readEntry("KeyboardRepeating", TriStateHelper::getString(STATE_ON)); + TriState keyRepeat = STATE_UNCHANGED; + if( keyRepeatStr == "true" || keyRepeatStr == TriStateHelper::getString(STATE_ON) ) { + keyRepeat = STATE_ON; + } + else if( keyRepeatStr == "false" || keyRepeatStr == TriStateHelper::getString(STATE_OFF) ) { + keyRepeat = STATE_OFF; + } + + int clickVolumePercent = config.readEntry("ClickVolume", -1); + if( clickVolumePercent != -1 && keyRepeat != STATE_UNCHANGED ) { + set_volume(clickVolumePercent, keyRepeat); + } + + if( keyRepeat == STATE_ON ) { + int delay_ = config.readEntry("RepeatDelay", 250); + double rate_ = config.readEntry("RepeatRate", 30.); + set_repeatrate(delay_, rate_); + } + + + TriState numlockState = TriStateHelper::getTriState( config.readEntry( "NumLock", TriStateHelper::getInt(STATE_UNCHANGED) ) ); + if( numlockState != STATE_UNCHANGED ) { + numlockx_change_numlock_state(QX11Info::display(), numlockState == STATE_ON ); + } +} diff --git a/kcms/keyboard/keyboard_hardware.h b/kcms/keyboard/keyboard_hardware.h new file mode 100644 index 0000000000..e3daa80b91 --- /dev/null +++ b/kcms/keyboard/keyboard_hardware.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 KEYBOARD_HARDWARE_H_ +#define KEYBOARD_HARDWARE_H_ + +void init_keyboard_hardware(); + +#endif /* KEYBOARD_HARDWARE_H_ */ diff --git a/kcms/keyboard/layout_memory.cpp b/kcms/keyboard/layout_memory.cpp new file mode 100644 index 0000000000..9e723612b7 --- /dev/null +++ b/kcms/keyboard/layout_memory.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "layout_memory.h" + +#include +#include + +#include +#include + +#include "x11_helper.h" +#include "xkb_helper.h" + + +LayoutMemory::LayoutMemory(const KeyboardConfig& keyboardConfig_): + prevLayoutList(X11Helper::getLayoutsList()), + keyboardConfig(keyboardConfig_) +{ + registerListeners(); +} + +LayoutMemory::~LayoutMemory() +{ + unregisterListeners(); +} + +void LayoutMemory::configChanged() +{ +// this->layoutMap.clear(); // if needed this will be done on layoutMapChanged event + unregisterListeners(); + registerListeners(); +} + +void LayoutMemory::registerListeners() +{ + if( keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_WINDOW + || keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_APPLICATION ) { + connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(windowChanged(WId))); +// connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), this, SLOT(windowRemoved(WId))); + } + if( keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_DESKTOP ) { + connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(desktopChanged(int))); + } +} + +void LayoutMemory::unregisterListeners() +{ + disconnect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(windowChanged(WId))); + disconnect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(desktopChanged(int))); +// disconnect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), this, SLOT(windowRemoved(WId))); +} + +QString LayoutMemory::getCurrentMapKey() { + switch(keyboardConfig.switchingPolicy) { + case KeyboardConfig::SWITCH_POLICY_WINDOW: { + WId wid = KWindowSystem::self()->activeWindow(); + KWindowInfo winInfo(wid, NET::WMWindowType); + NET::WindowType windowType = winInfo.windowType( NET::NormalMask | NET::DesktopMask | NET::DialogMask ); + kDebug() << "window type" << windowType; + + // we ignore desktop type so that our keybaord layout applet on desktop could change layout properly + if( windowType == NET::Desktop ) + return previousLayoutMapKey; + if( windowType != NET::Unknown && windowType != NET::Normal && windowType != NET::Dialog ) + return QString(); + + return QString::number(wid); + } + case KeyboardConfig::SWITCH_POLICY_APPLICATION: { + WId wid = KWindowSystem::self()->activeWindow(); + KWindowInfo winInfo(wid, NET::WMWindowType, NET::WM2WindowClass); + NET::WindowType windowType = winInfo.windowType( NET::NormalMask | NET::DesktopMask | NET::DialogMask ); + kDebug() << "window type" << windowType; + + // we ignore desktop type so that our keybaord layout applet on desktop could change layout properly + if( windowType == NET::Desktop ) + return previousLayoutMapKey; + if( windowType != NET::Unknown && windowType != NET::Normal && windowType != NET::Dialog ) + return QString(); + + // shall we use pid or window class ??? - class seems better (see e.g. https://bugs.kde.org/show_bug.cgi?id=245507) + // for window class shall we use class.class or class.name? (seem class.class is a bit better - more app-oriented) + kDebug() << "New active window with class.class: " << winInfo.windowClassClass(); + return QString(winInfo.windowClassClass()); +// NETWinInfo winInfoForPid( QX11Info::display(), wid, QX11Info::appRootWindow(), NET::WMPid); +// return QString::number(winInfoForPid.pid()); + } + case KeyboardConfig::SWITCH_POLICY_DESKTOP: + return QString::number(KWindowSystem::self()->currentDesktop()); + default: + return QString(); + } +} + +static +bool isExtraSubset(const QList& allLayouts, const QList& newList) +{ + if( allLayouts.first() != newList.first() ) + return false; + foreach(const LayoutUnit& layoutUnit, newList) { + if( ! allLayouts.contains(layoutUnit) ) + return false; + } + return true; +} + +void LayoutMemory::layoutMapChanged() +{ + QList newLayoutList(X11Helper::getLayoutsList()); + + if( prevLayoutList == newLayoutList ) + return; + + kDebug() << "Layout map change: " << LayoutSet::toString(prevLayoutList) << "-->" << LayoutSet::toString(newLayoutList); + prevLayoutList = newLayoutList; + + //TODO: need more thinking here on how to support external map resetting + if( keyboardConfig.configureLayouts + && keyboardConfig.isSpareLayoutsEnabled() + && isExtraSubset(keyboardConfig.layouts, newLayoutList) ) { + kDebug() << "Layout map change for extra layout"; + layoutChanged(); // to remember new map for active "window" + } + else { +// if( newLayoutList != keyboardConfig.getDefaultLayouts() ) { + // layoutList = newLayoutList; + kDebug() << "Layout map change from external source: clearing layout memory"; + layoutMap.clear(); +// } + } +} + +void LayoutMemory::layoutChanged() +{ + QString layoutMapKey = getCurrentMapKey(); + if( layoutMapKey.isEmpty() ) + return; + + layoutMap[ layoutMapKey ] = X11Helper::getCurrentLayouts(); +} + +void LayoutMemory::setCurrentLayoutFromMap() +{ + QString layoutMapKey = getCurrentMapKey(); + if( layoutMapKey.isEmpty() ) + return; + + if( ! layoutMap.contains(layoutMapKey) ) { +// kDebug() << "new key for layout map" << layoutMapKey; + + if( ! X11Helper::isDefaultLayout() ) { +// kDebug() << "setting default layout for container key" << layoutMapKey; + if( keyboardConfig.configureLayouts && keyboardConfig.isSpareLayoutsEnabled() + && X11Helper::getLayoutsList() != keyboardConfig.getDefaultLayouts() ) { + XkbHelper::initializeKeyboardLayouts(keyboardConfig.getDefaultLayouts()); + } + X11Helper::setDefaultLayout(); + } + } + else { + LayoutSet layoutFromMap = layoutMap[layoutMapKey]; + kDebug() << "Setting layout map item" << layoutFromMap.currentLayout.toString() + << "for container key" << layoutMapKey; + + LayoutSet currentLayouts = X11Helper::getCurrentLayouts(); + if( layoutFromMap.layouts != currentLayouts.layouts ) { + if( keyboardConfig.configureLayouts && keyboardConfig.isSpareLayoutsEnabled() ) { + XkbHelper::initializeKeyboardLayouts(layoutFromMap.layouts); + } + X11Helper::setLayout( layoutFromMap.currentLayout ); + } + else if( layoutFromMap.currentLayout != currentLayouts.currentLayout ) { + X11Helper::setLayout( layoutFromMap.currentLayout ); + } + } + + previousLayoutMapKey = layoutMapKey; +} + +//#include +//#include + +void LayoutMemory::windowChanged(WId /*wId*/) +{ +// KPluginInfo::List plugins = Plasma::Containment::listContainments(); +// foreach(KPluginInfo info, plugins) { +// kDebug() << "applets" << info.name(); +// } + setCurrentLayoutFromMap(); +} + +void LayoutMemory::desktopChanged(int /*desktop*/) +{ + setCurrentLayoutFromMap(); +} diff --git a/kcms/keyboard/layout_memory.h b/kcms/keyboard/layout_memory.h new file mode 100644 index 0000000000..df8568c2bd --- /dev/null +++ b/kcms/keyboard/layout_memory.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 LAYOUT_MEMORY_H_ +#define LAYOUT_MEMORY_H_ + +#include +#include +#include //For WId + +#include "x11_helper.h" +#include "keyboard_config.h" + +class LayoutMemoryPersister; + +class LayoutMemory : public QObject +{ + Q_OBJECT + + // if there's some transient windows coming up we'll need to either ignore it + // or in case of layout switcher popup menu to apply new layout to previous key + QString previousLayoutMapKey; + QList prevLayoutList; + const KeyboardConfig& keyboardConfig; + + void registerListeners(); + void unregisterListeners(); + QString getCurrentMapKey(); + void setCurrentLayoutFromMap(); + +public Q_SLOTS: + void layoutMapChanged(); + void layoutChanged(); + void windowChanged(WId wId); + void desktopChanged(int desktop); + +public: + LayoutMemory(const KeyboardConfig& keyboardConfig); + virtual ~LayoutMemory(); + + void configChanged(); + +protected: + //QVariant does not support long for WId so we'll use QString for key instead + QMap layoutMap; + + friend class LayoutMemoryPersister; +}; + +#endif /* LAYOUT_MEMORY_H_ */ diff --git a/kcms/keyboard/layout_memory_persister.cpp b/kcms/keyboard/layout_memory_persister.cpp new file mode 100644 index 0000000000..8a6118aad9 --- /dev/null +++ b/kcms/keyboard/layout_memory_persister.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 "layout_memory_persister.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "keyboard_config.h" +#include "layout_memory.h" + + +static const char* VERSION = "1.0"; +static const char* DOC_NAME = "LayoutMap"; +static const char* ROOT_NODE = "LayoutMap"; +static const char* VERSION_ATTRIBUTE = "version"; +static const char* SWITCH_MODE_ATTRIBUTE = "SwitchMode"; +static const char* ITEM_NODE = "item"; +static const QString CURRENT_LAYOUT_ATTRIBUTE("currentLayout"); +static const char* OWNER_KEY_ATTRIBUTE = "ownerKey"; +static const char* LAYOUTS_ATTRIBUTE = "layouts"; + +static const char* LIST_SEPARATOR_LM = ","; + +static const char* REL_SESSION_FILE_PATH = "/session/keyboard/layout_memory.xml"; + +QString LayoutMemoryPersister::getLayoutMapAsString() +{ + if( ! canPersist() ) + return ""; + + QDomDocument doc(DOC_NAME); + QDomElement root = doc.createElement(ROOT_NODE); + root.setAttribute(VERSION_ATTRIBUTE, VERSION); + root.setAttribute(SWITCH_MODE_ATTRIBUTE, KeyboardConfig::getSwitchingPolicyString(layoutMemory.keyboardConfig.switchingPolicy)); + doc.appendChild(root); + + if( layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { + if( ! globalLayout.isValid() ) + return ""; + + QDomElement item = doc.createElement(ITEM_NODE); + item.setAttribute(CURRENT_LAYOUT_ATTRIBUTE, globalLayout.toString()); + root.appendChild(item); + } + else { + foreach(const QString& key , layoutMemory.layoutMap.keys()) { + QDomElement item = doc.createElement(ITEM_NODE); + item.setAttribute(OWNER_KEY_ATTRIBUTE, key); + item.setAttribute(CURRENT_LAYOUT_ATTRIBUTE, layoutMemory.layoutMap[key].currentLayout.toString()); + + QString layoutSetString; + foreach(const LayoutUnit& layoutUnit, layoutMemory.layoutMap[key].layouts) { + if( ! layoutSetString.isEmpty() ) { + layoutSetString += LIST_SEPARATOR_LM; + } + layoutSetString += layoutUnit.toString(); + } + item.setAttribute(LAYOUTS_ATTRIBUTE, layoutSetString); + root.appendChild(item); + } + } + + return doc.toString(); +} + +static bool isRestoreSession() +{ + KConfigGroup c(KSharedConfig::openConfig("ksmserverrc", KConfig::NoGlobals), "General"); + kDebug() << "loginMode:" << c.readEntry("loginMode"); + QString loginMode = c.readEntry("loginMode"); + return loginMode != "default" && loginMode != "restoreSavedSession"; // we don't know how to restore saved session - only previous one +} + +bool LayoutMemoryPersister::save(const QString& moduleName) +{ + if( isRestoreSession() ) { + QString relPath = moduleName + REL_SESSION_FILE_PATH; + QFile file(KStandardDirs::locateLocal("data", relPath)); + return saveToFile(file); + } + return false; +} + +bool LayoutMemoryPersister::restore(const QString& moduleName) +{ + if( isRestoreSession() ) { + QString relPath = moduleName + REL_SESSION_FILE_PATH; + QFile file(KStandardDirs::locateLocal("data", relPath)); + return restoreFromFile(file); + } + return false; +} + + +bool LayoutMemoryPersister::saveToFile(const QFile& file_) +{ + QString xml = getLayoutMapAsString(); + if( xml.isEmpty() ) + return false; + + QFile file(file_.fileName()); // so we don't expose the file we open/close to the caller + if( ! file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) ) { + kWarning() << "Failed to open layout memory xml file for writing" << file.fileName(); + return false; + } + + QTextStream out(&file); + out << xml; + out.flush(); + + if( file.error() != QFile::NoError ) { + kWarning() << "Failed to store keyboard layout memory, error" << file.error(); + file.close(); + file.remove(); + return false; + } + else { + kDebug() << "Keyboard layout memory stored into" << file.fileName() << "written" << file.pos(); + return true; + } +} + + +class MapHandler : public QXmlDefaultHandler +{ +public: + MapHandler(const KeyboardConfig::SwitchingPolicy& switchingPolicy_): + verified(false), + switchingPolicy(switchingPolicy_) {} + + bool startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, + const QString &qName, const QXmlAttributes &attributes) { + + if( qName == ROOT_NODE ) { + if( attributes.value(VERSION_ATTRIBUTE) != VERSION ) + return false; + if( attributes.value(SWITCH_MODE_ATTRIBUTE) != KeyboardConfig::getSwitchingPolicyString(switchingPolicy) ) + return false; + + verified = true; + } + if( qName == ITEM_NODE ) { + if( ! verified ) + return false; + + if( switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { + globalLayout = LayoutUnit(attributes.value(CURRENT_LAYOUT_ATTRIBUTE)); + } + else { + QStringList layoutStrings = attributes.value(LAYOUTS_ATTRIBUTE).split(LIST_SEPARATOR_LM); + LayoutSet layoutSet; + foreach(const QString& layoutString, layoutStrings) { + layoutSet.layouts.append(LayoutUnit(layoutString)); + } + layoutSet.currentLayout = LayoutUnit(attributes.value(CURRENT_LAYOUT_ATTRIBUTE)); + QString ownerKey = attributes.value(OWNER_KEY_ATTRIBUTE); + + if( ownerKey.trimmed().isEmpty() || ! layoutSet.isValid() ) + return false; + + layoutMap[ownerKey] = layoutSet; + } + } + return verified; + } + + bool verified; + QMap layoutMap; + LayoutUnit globalLayout; + +private: + const KeyboardConfig::SwitchingPolicy& switchingPolicy; +}; + +template +static +bool containsAll(QList set1, QList set2) +{ + foreach(const T& t, set2) { + if( ! set1.contains(t) ) + return false; + } + return true; +} + +bool LayoutMemoryPersister::restoreFromFile(const QFile& file_) +{ + globalLayout = LayoutUnit(); + + if( ! canPersist() ) + return false; + + QFile file(file_.fileName()); // so we don't expose the file we open/close to the caller + if( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { + kWarning() << "Failed to open layout memory xml file for reading" << file.fileName() << "error:" << file.error(); + return false; + } + + MapHandler mapHandler(layoutMemory.keyboardConfig.switchingPolicy); + + QXmlSimpleReader reader; + reader.setContentHandler(&mapHandler); + reader.setErrorHandler(&mapHandler); + + QXmlInputSource xmlInputSource(&file); + kDebug() << "Restoring keyboard layout map from" << file.fileName(); + + if( ! reader.parse(xmlInputSource) ) { + kWarning() << "Failed to parse the layout memory file" << file.fileName(); + return false; + } + + if( layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_GLOBAL ) { + if( mapHandler.globalLayout.isValid() && layoutMemory.keyboardConfig.layouts.contains(mapHandler.globalLayout)) { + globalLayout = mapHandler.globalLayout; + kDebug() << "Restored global layout" << globalLayout.toString(); + } + } + else { + layoutMemory.layoutMap.clear(); + foreach(const QString& key, mapHandler.layoutMap.keys()) { + if( containsAll(layoutMemory.keyboardConfig.layouts, mapHandler.layoutMap[key].layouts) ) { + layoutMemory.layoutMap.insert(key, mapHandler.layoutMap[key]); + } + } + kDebug() << "Restored layouts for" << layoutMemory.layoutMap.size() << "containers"; + } + return true; +} + +bool LayoutMemoryPersister::canPersist() { + // we can't persist per window - as we're using window id which is not preserved between sessions + bool windowMode = layoutMemory.keyboardConfig.switchingPolicy == KeyboardConfig::SWITCH_POLICY_WINDOW; + if( windowMode ) { + kDebug() << "Not saving session for window mode"; + } + return !windowMode; +} diff --git a/kcms/keyboard/layout_memory_persister.h b/kcms/keyboard/layout_memory_persister.h new file mode 100644 index 0000000000..8c4b3c5f60 --- /dev/null +++ b/kcms/keyboard/layout_memory_persister.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 LAYOUT_MEMORY_PERSISTER_H_ +#define LAYOUT_MEMORY_PERSISTER_H_ + +#include + +#include "x11_helper.h" + +class LayoutMemory; +class QFile; + +class LayoutMemoryPersister { +public: + LayoutMemoryPersister(LayoutMemory& layoutMemory_): + layoutMemory(layoutMemory_) {} + + bool saveToFile(const QFile& file); + bool restoreFromFile(const QFile& file); + + bool save(const QString& moduleName); + bool restore(const QString& moduleName); + + LayoutUnit getGlobalLayout() const { return globalLayout; } + void setGlobalLayout(const LayoutUnit& layout) { globalLayout = layout; } + +private: + LayoutMemory& layoutMemory; + LayoutUnit globalLayout; + + QString getLayoutMapAsString(); + + bool canPersist(); +}; + +#endif /* LAYOUT_MEMORY_PERSISTER_H_ */ diff --git a/kcms/keyboard/layout_tray_icon.cpp b/kcms/keyboard/layout_tray_icon.cpp new file mode 100644 index 0000000000..814c5606c9 --- /dev/null +++ b/kcms/keyboard/layout_tray_icon.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "layout_tray_icon.h" + +//#include +#include +#include +#include + +#include "xkb_rules.h" +#include "x11_helper.h" +#include "xkb_helper.h" +#include "keyboard_config.h" +#include "flags.h" +#include "layouts_menu.h" + + +// +// Layout Tray Icon +// +LayoutTrayIcon::LayoutTrayIcon(const Rules* rules_, const KeyboardConfig& keyboardConfig_): + keyboardConfig(keyboardConfig_), + rules(rules_), + flags(new Flags()), + layoutsMenu(new LayoutsMenu(keyboardConfig_, *rules, *flags)) +{ + m_notifierItem = new KStatusNotifierItem(this); + m_notifierItem->setCategory(KStatusNotifierItem::SystemServices); + m_notifierItem->setStatus(KStatusNotifierItem::Active); + m_notifierItem->setToolTipTitle(i18nc("tooltip title", "Keyboard Layout")); + m_notifierItem->setTitle(i18nc("tooltip title", "Keyboard Layout")); + + KMenu* menu = new KMenu(""); + m_notifierItem->setContextMenu(menu); + m_notifierItem->setStandardActionsEnabled(false); + + layoutMapChanged(); + + m_notifierItem->setStatus(KStatusNotifierItem::Active); + + init(); +} + +LayoutTrayIcon::~LayoutTrayIcon() +{ + destroy(); + delete flags; + delete layoutsMenu; +} + +void LayoutTrayIcon::init() +{ + connect(m_notifierItem, SIGNAL(activateRequested(bool,QPoint)), this, SLOT(toggleLayout())); + connect(m_notifierItem, SIGNAL(scrollRequested(int,Qt::Orientation)), this, SLOT(scrollRequested(int,Qt::Orientation))); + connect(flags, SIGNAL(pixmapChanged()), this, SLOT(layoutChanged())); +} + +void LayoutTrayIcon::destroy() +{ + disconnect(flags, SIGNAL(pixmapChanged()), this, SLOT(layoutChanged())); + disconnect(m_notifierItem, SIGNAL(scrollRequested(int,Qt::Orientation)), this, SLOT(scrollRequested(int,Qt::Orientation))); + disconnect(m_notifierItem, SIGNAL(activateRequested(bool,QPoint)), this, SLOT(toggleLayout())); +} + +void LayoutTrayIcon::layoutMapChanged() +{ + flags->clearCache(); + + QMenu* menu = m_notifierItem->contextMenu(); + menu->clear(); + QList actions = layoutsMenu->contextualActions(); + menu->addActions(actions); + + layoutChanged(); +} + +void LayoutTrayIcon::layoutChanged() +{ + LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); + if( layoutUnit.isEmpty() ) + return; + +// QString shortText = Flags::getShortText(layoutUnit, *keyboardConfig); +// kDebug() << "systray: LayoutChanged" << layoutUnit.toString() << shortText; + QString longText = Flags::getLongText(layoutUnit, rules); + + m_notifierItem->setToolTipSubTitle(longText); + + const QIcon icon(getFlag(layoutUnit.layout)); + m_notifierItem->setToolTipIconByPixmap(icon); + + QIcon textOrIcon = flags->getIconWithText(layoutUnit, keyboardConfig); + m_notifierItem->setIconByPixmap( textOrIcon ); +} + +void LayoutTrayIcon::toggleLayout() +{ + X11Helper::switchToNextLayout(); +} + +void LayoutTrayIcon::scrollRequested(int delta, Qt::Orientation /*orientation*/) +{ + X11Helper::scrollLayouts(delta > 0 ? 1 : -1); +} + +const QIcon LayoutTrayIcon::getFlag(const QString& layout) const +{ + return keyboardConfig.isFlagShown() ? flags->getIcon(layout) : QIcon(); +} diff --git a/kcms/keyboard/layout_tray_icon.h b/kcms/keyboard/layout_tray_icon.h new file mode 100644 index 0000000000..0287e81de8 --- /dev/null +++ b/kcms/keyboard/layout_tray_icon.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 LAYOUT_TRAY_ICON_H_ +#define LAYOUT_TRAY_ICON_H_ + +#include +#include + +#include "flags.h" +#include "x11_helper.h" + +class KeyboardConfig; +class LayoutsMenu; + +/** + * System tray icon to show layouts + */ +class KStatusNotifierItem; +class QActionGroup; +class Rules; +class Flags; +class LayoutTrayIcon : public QObject +{ + Q_OBJECT + +public: + LayoutTrayIcon(const Rules* rules, const KeyboardConfig& keyboardConfig); + ~LayoutTrayIcon(); + + void layoutMapChanged(); + +public Q_SLOTS: + void layoutChanged(); + +private Q_SLOTS: + void toggleLayout(); + void scrollRequested(int, Qt::Orientation); + +private: + void init(); + void destroy(); + const QIcon getFlag(const QString& layout) const; + + const KeyboardConfig& keyboardConfig; + const Rules* rules; + Flags* flags; + KStatusNotifierItem *m_notifierItem; + LayoutsMenu* layoutsMenu; +}; + + +#endif /* LAYOUT_WIDGET_H_ */ diff --git a/kcms/keyboard/layout_widget.cpp b/kcms/keyboard/layout_widget.cpp new file mode 100644 index 0000000000..231c39cc94 --- /dev/null +++ b/kcms/keyboard/layout_widget.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "layout_widget.h" + +//#include +#include + +#include + +#include "xkb_rules.h" +#include "x11_helper.h" +#include "xkb_helper.h" +#include "keyboard_config.h" +#include "flags.h" + + +K_PLUGIN_FACTORY(LayoutWidgetFactory, registerPlugin();) +K_EXPORT_PLUGIN(LayoutWidgetFactory("keyboard_layout_widget")) + + +LayoutWidget::LayoutWidget(QWidget* parent, const QList& /*args*/): + QWidget(parent), + xEventNotifier(nullptr), + keyboardConfig(new KeyboardConfig()), + flags(new Flags()) +{ + if( ! X11Helper::xkbSupported(NULL) ) { +// setFailedToLaunch(true, "XKB extension failed to initialize"); + hide(); + return; + } + + keyboardConfig->load(); + bool show = // keyboardConfig->showIndicator && + ( keyboardConfig->showSingle || X11Helper::getLayoutsList().size() > 1 ); + if( ! show ) { + hide(); + return; + } + + widget = new QPushButton(this); + widget->setFlat(true); + + layoutChanged(); + init(); +} + +LayoutWidget::~LayoutWidget() +{ + destroy(); +} + +void LayoutWidget::init() +{ +#warning XEventNotifier needs porting to QAbstractNativeEventFilter +#if 0 + connect(widget, SIGNAL(clicked(bool)), this, SLOT(toggleLayout())); + connect(xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); + connect(xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutChanged())); + xEventNotifier->start(); +#endif +} + +void LayoutWidget::destroy() +{ +#warning XEventNotifier needs porting to QAbstractNativeEventFilter +#if 0 + xEventNotifier->stop(); + disconnect(xEventNotifier, SIGNAL(layoutMapChanged()), this, SLOT(layoutChanged())); + disconnect(xEventNotifier, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); +#endif +} + +void LayoutWidget::toggleLayout() +{ + X11Helper::switchToNextLayout(); +} + +void LayoutWidget::layoutChanged() +{ + LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); + if( layoutUnit.isEmpty() ) + return; + + QIcon icon; + if( keyboardConfig->isFlagShown() ) { + icon = flags->getIcon(layoutUnit.layout); + } + + QString longText = Flags::getLongText(layoutUnit, NULL); + if( ! icon.isNull() ) { + widget->setIcon(icon); + widget->setText(""); + widget->setToolTip(longText); + } + else { + QString shortText = Flags::getShortText(layoutUnit, *keyboardConfig); + widget->setIcon(icon); + widget->setText(shortText); + widget->setToolTip(longText); +// widget->setShortcut(QKeySequence()); + } +} + +#include "layout_widget.moc" diff --git a/kcms/keyboard/layout_widget.h b/kcms/keyboard/layout_widget.h new file mode 100644 index 0000000000..1054cae86c --- /dev/null +++ b/kcms/keyboard/layout_widget.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 LAYOUT_WIDGET_H_ +#define LAYOUT_WIDGET_H_ + +#include +#include + +#include "flags.h" +#include "x11_helper.h" + +class QPushButton; +class KeyboardConfig; +class LayoutsMenu; +class XEventNotifier; + +/** + * Note: does not listen to configuration changes as currently we only use it in screen lock dialog + */ +class LayoutWidget : public QWidget +{ + Q_OBJECT + +public: + explicit LayoutWidget(QWidget* parent = 0, const QList& args = QList()); + virtual ~LayoutWidget(); + +private Q_SLOTS: + void toggleLayout(); + void layoutChanged(); + // void configChanged(); + +private: + void init(); + void destroy(); + + XEventNotifier* xEventNotifier; + QPushButton* widget; + KeyboardConfig* keyboardConfig; + Flags* flags; +}; + +#endif /* LAYOUT_WIDGET_H_ */ diff --git a/kcms/keyboard/layouts_menu.cpp b/kcms/keyboard/layouts_menu.cpp new file mode 100644 index 0000000000..af58e9bcef --- /dev/null +++ b/kcms/keyboard/layouts_menu.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "layouts_menu.h" + +#include +#include +#include +#include + +#include +#include + +#include "keyboard_config.h" +#include "x11_helper.h" +#include "xkb_helper.h" +#include "flags.h" + + +LayoutsMenu::LayoutsMenu(const KeyboardConfig& keyboardConfig_, const Rules& rules_, Flags& flags_): + keyboardConfig(keyboardConfig_), + rules(rules_), + flags(flags_), + actionGroup(NULL) +{ +} + +LayoutsMenu::~LayoutsMenu() +{ + delete actionGroup; +} + +const QIcon LayoutsMenu::getFlag(const QString& layout) const +{ + return keyboardConfig.isFlagShown() ? flags.getIcon(layout) : QIcon(); +} + +void LayoutsMenu::actionTriggered(QAction* action) +{ + QString data = action->data().toString(); + if( data == "config" ) { + QStringList args; + args << "--args=--tab=layouts"; + args << "kcm_keyboard"; + KToolInvocation::kdeinitExec("kcmshell4", args); + } + else { + LayoutUnit layoutUnit(LayoutUnit(action->data().toString())); + switchToLayout(layoutUnit, keyboardConfig); + } +} + +int LayoutsMenu::switchToLayout(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) +{ + QList layouts = X11Helper::getCurrentLayouts().layouts; + + bool res; + if( layouts.contains(layoutUnit) ) { + res = X11Helper::setLayout(layoutUnit); + } + else if ( keyboardConfig.isSpareLayoutsEnabled() && keyboardConfig.layouts.contains(layoutUnit) ) { + QList layouts(keyboardConfig.getDefaultLayouts()); + layouts.removeLast(); + layouts.append(layoutUnit); + XkbHelper::initializeKeyboardLayouts(layouts); + res = X11Helper::setLayout(layoutUnit); + } + else { + kWarning() << "switchToLayout with unknown layout" << layoutUnit.toString(); + res = -1; + } + return res; +} + +QAction* LayoutsMenu::createAction(const LayoutUnit& layoutUnit) const +{ + QString menuText = Flags::getFullText(layoutUnit, keyboardConfig, &rules); + QAction* action = new QAction(getFlag(layoutUnit.layout), menuText, actionGroup); + action->setData(layoutUnit.toString()); + //FIXME: tooltips don't work on dbusmenus??? +// if( ! layoutUnit.getShortcut().isEmpty() ) { +// action->setToolTip(layoutUnit.getShortcut().toString()); +// } + return action; +} + +QList LayoutsMenu::contextualActions() +{ + if( actionGroup ) { + disconnect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*))); + delete actionGroup; + } + actionGroup = new QActionGroup(this); + + X11Helper::getLayoutsList(); //UGLY: seems to be more reliable with extra call + QList currentLayouts = X11Helper::getLayoutsList(); + foreach(const LayoutUnit& layoutUnit, currentLayouts) { + QAction* action = createAction(layoutUnit); + actionGroup->addAction(action); + } + + if( keyboardConfig.configureLayouts ) { + QList extraLayouts = keyboardConfig.layouts; + foreach(const LayoutUnit& layoutUnit, currentLayouts) { + extraLayouts.removeOne(layoutUnit); + } + if( extraLayouts.size() > 0 ) { + QAction* separator = new QAction(actionGroup); + separator->setSeparator(true); + actionGroup->addAction(separator); + + foreach(const LayoutUnit& layoutUnit, extraLayouts) { + QAction* action = createAction(layoutUnit); + actionGroup->addAction(action); + } + } + } + + QAction* separator = new QAction(actionGroup); + separator->setSeparator(true); + actionGroup->addAction(separator); + QAction* configAction = new QAction(i18n("Configure..."), actionGroup); + actionGroup->addAction(configAction); + configAction->setData("config"); + connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*))); + return actionGroup->actions(); +} diff --git a/kcms/keyboard/layouts_menu.h b/kcms/keyboard/layouts_menu.h new file mode 100644 index 0000000000..db2f3ff584 --- /dev/null +++ b/kcms/keyboard/layouts_menu.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 LAYOUTS_MENU_H_ +#define LAYOUTS_MENU_H_ + +#include +#include + +class QAction; +class KeyboardConfig; +class Flags; +class Rules; +class QActionGroup; +class LayoutUnit; + +class LayoutsMenu : public QObject +{ + Q_OBJECT + +public: + LayoutsMenu(const KeyboardConfig& keyboardConfig, const Rules& rules, Flags& flags); + virtual ~LayoutsMenu(); + + QList contextualActions(); + static int switchToLayout(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig); + +private Q_SLOTS: + void actionTriggered(QAction* action); + +private: + const QIcon getFlag(const QString& layout) const; + QAction* createAction(const LayoutUnit& layoutUnit) const; + + const KeyboardConfig& keyboardConfig; + const Rules& rules; + Flags& flags; + QActionGroup* actionGroup; +}; + +#endif /* LAYOUTS_MENU_H_ */ diff --git a/kcms/keyboard/numlockx.c b/kcms/keyboard/numlockx.c new file mode 100644 index 0000000000..0ac7cfbd9c --- /dev/null +++ b/kcms/keyboard/numlockx.c @@ -0,0 +1,305 @@ +/**************************************************************************** + + NumLockX + + $Id: main.c,v 1.10 2001/04/30 20:55:20 seli Exp $ + + Copyright (C) 2000-2001 Lubos Lunak + Copyright (C) 2001 Oswald Buddenhagen + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +****************************************************************************/ + +#include + +#include + +#include + +#ifdef HAVE_XTEST +#include +#endif + +#ifdef HAVE_XKB +#include +#endif + +#include + +static +Display* dpy; + +/* the XKB stuff is based on code created by Oswald Buddenhagen */ +#ifdef HAVE_XKB +static +int xkb_init() + { + int xkb_opcode, xkb_event, xkb_error; + int xkb_lmaj = XkbMajorVersion; + int xkb_lmin = XkbMinorVersion; + return XkbLibraryVersion( &xkb_lmaj, &xkb_lmin ) + && XkbQueryExtension( dpy, &xkb_opcode, &xkb_event, &xkb_error, + &xkb_lmaj, &xkb_lmin ); + } + +static +unsigned int xkb_mask_modifier( XkbDescPtr xkb, const char *name ) + { + int i; + if( !xkb || !xkb->names ) + return 0; + for( i = 0; + i < XkbNumVirtualMods; + i++ ) + { + char* modStr = XGetAtomName( xkb->dpy, xkb->names->vmods[i] ); + if( modStr != NULL && strcmp(name, modStr) == 0 ) + { + unsigned int mask; + XkbVirtualModsToReal( xkb, 1 << i, &mask ); + return mask; + } + } + return 0; + } + +static +unsigned int xkb_numlock_mask() + { + XkbDescPtr xkb; + if(( xkb = XkbGetKeyboard( dpy, XkbAllComponentsMask, XkbUseCoreKbd )) != NULL ) + { + unsigned int mask = xkb_mask_modifier( xkb, "NumLock" ); + XkbFreeKeyboard( xkb, 0, True ); + return mask; + } + return 0; + } + +static +int xkb_set_on() + { + unsigned int mask; + if( !xkb_init()) + return 0; + mask = xkb_numlock_mask(); + if( mask == 0 ) + return 0; + XkbLockModifiers ( dpy, XkbUseCoreKbd, mask, mask); + return 1; + } + +static +int xkb_set_off() + { + unsigned int mask; + if( !xkb_init()) + return 0; + mask = xkb_numlock_mask(); + if( mask == 0 ) + return 0; + XkbLockModifiers ( dpy, XkbUseCoreKbd, mask, 0); + return 1; + } + +#ifdef NUMLOCKX_STANDALONE +static +int xkb_toggle() + { + unsigned int mask; + unsigned int numlockState; + XkbStateRec xkbState; + if( !xkb_init()) + return 0; + mask = xkb_numlock_mask(); + if( mask == 0 ) + return 0; + XkbGetState( dpy, XkbUseCoreKbd, &xkbState); + numlockState = xkbState.locked_mods & mask; + if (numlockState) + XkbLockModifiers ( dpy, XkbUseCoreKbd, mask, 0); + else + XkbLockModifiers ( dpy, XkbUseCoreKbd, mask, mask); + return 1; + } +#endif + +#endif + +#ifdef HAVE_XTEST +static +int xtest_get_numlock_state() + { + int i; + int numlock_mask = 0; + Window dummy1, dummy2; + int dummy3, dummy4, dummy5, dummy6; + unsigned int mask; + XModifierKeymap* map = XGetModifierMapping( dpy ); + KeyCode numlock_keycode = XKeysymToKeycode( dpy, XK_Num_Lock ); + if( numlock_keycode == NoSymbol ) + return 0; + for( i = 0; + i < 8; + ++i ) + { + if( map->modifiermap[ map->max_keypermod * i ] == numlock_keycode ) + numlock_mask = 1 << i; + } + XQueryPointer( dpy, DefaultRootWindow( dpy ), &dummy1, &dummy2, + &dummy3, &dummy4, &dummy5, &dummy6, &mask ); + XFreeModifiermap( map ); + return mask & numlock_mask; + } + +static +void xtest_change_numlock() + { + XTestFakeKeyEvent( dpy, XKeysymToKeycode( dpy, XK_Num_Lock ), True, CurrentTime ); + XTestFakeKeyEvent( dpy, XKeysymToKeycode( dpy, XK_Num_Lock ), False, CurrentTime ); + } + +static +void xtest_set_on() + { + if( !xtest_get_numlock_state()) + xtest_change_numlock(); + } + +static +void xtest_set_off() + { + if( xtest_get_numlock_state()) + xtest_change_numlock(); + } + +#ifdef NUMLOCKX_STANDALONE +static +void xtest_toggle() + { + xtest_change_numlock(); + } +#endif + +#endif + +static +void numlock_set_on() + { +#ifdef HAVE_XKB + if( xkb_set_on()) + return; +#endif +#ifdef HAVE_XTEST + xtest_set_on(); +#endif + } + +static +void numlock_set_off() + { +#ifdef HAVE_XKB + if( xkb_set_off()) + return; +#endif +#ifdef HAVE_XTEST + xtest_set_off(); +#endif + } + + +#ifndef NUMLOCKX_STANDALONE + +void numlockx_change_numlock_state(Display* dpy_, int state) +{ +#ifndef HAVE_XTEST +#ifdef __GNUC__ + #warning "XTEST extension not found - numlock setting may not work reliably" +#endif +#endif + + dpy = dpy_; + if( state ) { + numlock_set_on(); + } + else { + numlock_set_off(); + } +} + +#else + +static +void numlock_toggle() + { +#ifdef HAVE_XKB + if( xkb_toggle()) + return; +#endif +#ifdef HAVE_XTEST + xtest_toggle(); +#endif + } + +void usage( const char* argv0 ) + { + printf( "NumLockX " VERSION "\n" + "(C) 2000-2001 Lubos Lunak \n" + "(C) 2001 Oswald Buddenhagen \n\n" + "Usage : %s [on|off]\n" + "on - turns NumLock on in X ( default )\n" + "off - turns NumLock off in X\n" + "toggle - toggles the NumLock on and off in X\n" + "\n" + , argv0 ); + } + +int main( int argc, char* argv[] ) + { + if( argc > 2 ) + { + usage( argv[ 0 ] ); + return 1; + } + dpy = XOpenDisplay( NULL ); + if( dpy == NULL ) + { + fprintf( stderr, "Error opening display!\n" ); + return 1; + } + if( argc == 1 ) + numlock_set_on(); + else if( strcmp( argv[ 1 ], "on" ) == 0 ) + numlock_set_on(); + else if( strcmp( argv[ 1 ], "off" ) == 0 ) + numlock_set_off(); + else if( strcmp( argv[ 1 ], "toggle" ) == 0 ) + numlock_toggle(); + else + { + usage( argv[ 0 ] ); + XCloseDisplay( dpy ); + return 2; + } + XCloseDisplay( dpy ); + return 0; + } + +#endif diff --git a/kcms/keyboard/pics/CMakeLists.txt b/kcms/keyboard/pics/CMakeLists.txt new file mode 100644 index 0000000000..6d5b7cae94 --- /dev/null +++ b/kcms/keyboard/pics/CMakeLists.txt @@ -0,0 +1 @@ +install( FILES epo.png DESTINATION ${DATA_INSTALL_DIR}/kcmkeyboard/pics ) diff --git a/kcms/keyboard/pics/epo.png b/kcms/keyboard/pics/epo.png new file mode 100644 index 0000000000000000000000000000000000000000..a8ed2943810dcbdf62c3456b115bae749b6dfe8c GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{Y!2~4zQx41oQq09po*^6@9Je3(KLBz$3p^r= zfl7{mFymBhK53v}pQnpsh{nX^KmY&RGqWYkIohGwA!=|iGFmQAF^JzNAu%Cg$FFy< zHs_x&>VLY)c(Zq*cP4k1@cQ|kjg5{i&P)C}{cb+be@lN$cR|O5oc$KlcUbM;rL$c} zoO`;(atqI2lK&xqJzh@Zlh(ceHSvw^jT0wM{P7`qiNPO9$uyzYA!`~sH%torYjTC3 Y!E3Kt@gFHAkXINyUHx3vIVCg!0Bep~LI3~& literal 0 HcmV?d00001 diff --git a/kcms/keyboard/plasma_applet_keyboard.desktop b/kcms/keyboard/plasma_applet_keyboard.desktop new file mode 100644 index 0000000000..37ca201dde --- /dev/null +++ b/kcms/keyboard/plasma_applet_keyboard.desktop @@ -0,0 +1,165 @@ +[Desktop Entry] +Name=Keyboard Layout +Name[af]=Sleutelbord Uitleg +Name[ar]=تخطيط لوحة المفاتيح +Name[ast]=Disposición del tecláu +Name[be]=Раскладка клавіятуры +Name[be@latin]=Vykład klavijatury +Name[bg]=Клавиатурни подредби +Name[bn]=কীবোর্ড বিন্যাস +Name[bn_IN]=কি-বোর্ড বিন্যাস +Name[br]=Reizhadur ar stokellaoueg +Name[bs]=Raspored tastera +Name[ca]=Disposició del teclat +Name[ca@valencia]=Disposició del teclat +Name[cs]=Rozvržení klávesnice +Name[csb]=Ùstôw klawiaturë +Name[cy]=Cynllun Bysellfwrdd +Name[da]=Tastaturlayout +Name[de]=Tastaturbelegung +Name[el]=Διάταξη πληκτρολογίου +Name[en_GB]=Keyboard Layout +Name[eo]=Klavararanĝo +Name[es]=Disposición del teclado +Name[et]=Klaviatuuri paigutus +Name[eu]=Teklatu-diseinua +Name[fa]=طرح‌بندی صفحه کلید +Name[fi]=Näppäimistön järjestys +Name[fr]=Disposition du clavier +Name[fy]=Toetseboerdyndieling +Name[ga]=Leagan Amach Méarchláir +Name[gl]=Disposición do teclado +Name[gu]=કીબોર્ડ દેખાવ +Name[he]=פריסת מקלדת +Name[hi]=कुंजीपट ख़ाका +Name[hne]=कुंजीपट खाका +Name[hr]=Raspored tipkovnice +Name[hsb]=Tastaturowy layout +Name[hu]=Billentyűzetkiosztás +Name[ia]=Disposition de claviero +Name[id]=Tata Letak Papan Ketik +Name[is]=Lyklaborð +Name[it]=Mappatura della tastiera +Name[ja]=キーボード配列 +Name[ka]=კლავიატურის განლაგება +Name[kk]=Перенетақта сәйкестігі +Name[km]=ប្លង់​ក្ដារចុច +Name[kn]=ಕೀಲಿಮಣೆ ವಿನ್ಯಾಸ +Name[ko]=키보드 레이아웃 +Name[ku]=Rengê Klavyeyê +Name[lt]=Klaviatūros išdėstymas +Name[lv]=Tastatūras izkārtojums +Name[mai]=कीबोर्ड लेआउट +Name[mk]=Распоред на тастатура +Name[ml]=കീബോര്‍ഡ് വിന്യാസം +Name[mr]=कळफलक रचना +Name[nb]=Tastaturoppsett +Name[nds]=Tasttoornen +Name[ne]=कुञ्जीपाटी सजावट +Name[nl]=Toetsenbordindeling +Name[nn]=Taste­oppsett +Name[oc]=Disposicion del clavièr +Name[or]=କିବୋର୍ଡ଼ ବିନ୍ୟାସ +Name[pa]=ਕੀ-ਬੋਰਡ ਲੇਆਉਟ +Name[pl]=Układ klawiatury +Name[pt]=Disposição do Teclado +Name[pt_BR]=Leiaute do teclado +Name[ro]=Aranjament de tastatură +Name[ru]=Раскладка клавиатуры +Name[se]=Boallobeavdehápmi +Name[si]=යතුරුපුවරු ආකෘතිය +Name[sk]=Rozloženie klávesnice +Name[sl]=Razporeditev tipk +Name[sr]=Распоред тастера +Name[sr@ijekavian]=Распоред тастера +Name[sr@ijekavianlatin]=Raspored tastera +Name[sr@latin]=Raspored tastera +Name[sv]=Tangentbordslayout +Name[ta]=விசைப்பலகை உருவரை +Name[te]=కీబోర్డ్ కూర్పు +Name[tg]=Тугмабандии клавиатура +Name[th]=ผังแป้นพิมพ์ +Name[tr]=Klavye Düzeni +Name[ug]=ھەرپتاختا ئورۇنلاشتۇرۇلۇشى +Name[uk]=Розкладка клавіатури +Name[uz]=Tugmalar tartibi +Name[uz@cyrillic]=Тугмалар тартиби +Name[vi]=Bố trí bàn phím +Name[wa]=Adjinçmint del taprece +Name[xh]=Ubeko Lwebhodi yezitshixo +Name[x-test]=xxKeyboard Layoutxx +Name[zh_CN]=键盘布局 +Name[zh_TW]=鍵盤配置 +Comment=View and switch between active keyboard layouts +Comment[ar]=إعرض وبدل بين مخططات لوحة المفاتيح +Comment[ast]=Ver y camudar ente les distribuciones de tecláu actives +Comment[bg]=Преглед и превключване на клавиатурната подредба +Comment[bn]=সক্রিয় কীবোর্ড বিন্যাসগুলি দেখুন এবং অদলবদল করুন +Comment[bs]=Prikaz i prebacivanje između aktivnih rasporeda tastature +Comment[ca]=Vista i commutació entre disposicions actives de teclat +Comment[ca@valencia]=Vista i commutació entre disposicions actives de teclat +Comment[cs]=Zobrazí a přepne mezi aktivními rozloženími klávesnice +Comment[da]=Vis og skift mellem aktive tastaturlayouts +Comment[de]=Aktive Tastaturbelegungen anzeigen und zwischen ihnen umschalten +Comment[el]=Εμφάνιση και εναλλαγή μεταξύ των ενεργών διατάξεων πληκτρολογίου +Comment[en_GB]=View and switch between active keyboard layouts +Comment[es]=Ver y cambiar entre las distribuciones de teclado activas +Comment[et]=Aktiivsete klaviatuuripaigutuste näitamine ja nende vahel lülitamine +Comment[eu]=Ikusi eta aldatu teklatu-diseinu aktibo batetik bestera +Comment[fi]=Katsele ja vaihda aktiivisten näppäinasetteluiden välillä +Comment[fr]=Affiche et change des dispositions actives de clavier +Comment[gl]=Mostra e troca a disposición de teclado activa +Comment[he]=משמש להצגת והחלפה בין פריסות מקלדת +Comment[hr]=Prikaži i prebaci između aktivnih tipkovničkih rasporeda +Comment[hu]=Aktív billentyűzetkiosztások megjelenítése és váltás köztük +Comment[ia]=Monstra e commuta inter dispositiones de claviero active +Comment[is]=Skoða og skipta á milli virkra lyklaborðsframsetninga +Comment[it]=Visualizza e cambia le mappature della tastiera attive +Comment[ja]=アクティブキーボードレイアウトを表示して切り替える +Comment[kk]=Белсенді пернетақталарды көру және біріне ауысу +Comment[km]=មើល ហើយ​ប្ដូរ​ប្លង់​ក្ដារចុច​សកម្ម +Comment[ko]=활성 키보드 레이아웃을 보고 바꾸기 +Comment[lt]=Peržiūrėti ir persijungti tarp aktyvių klaviatūros maketų +Comment[lv]=Skatīt un pārslēgties starp aktīvajiem tastatūras izkārtojumumiem +Comment[mr]=चालू कळफलक रचना बघा व बदला +Comment[nb]=Vis aktive tastaturutforminger og bytt mellom dem +Comment[nds]=Aktiv Tasttoornen ankieken un wesseln +Comment[nl]=Bekijk en schakel tussen actieve toetsenbordindelingen +Comment[nn]=Vis og byt mellom aktive tastaturoppsett +Comment[pa]=ਸਰਗਰਮ ਕੀਬੋਰਡ ਲੇਆਉਟ ਵੇਖੋ ਅਤੇ ਬਦਲੋ +Comment[pl]=Przeglądanie i przełączanie między aktywnymi układami klawiatury +Comment[pt]=Ver e mudar a disposição de teclado activa +Comment[pt_BR]=Visualiza e troca o leiaute de teclado ativo +Comment[ro]=Vizualizează și schimbă între aranjamentele de tastatură active +Comment[ru]=Просмотр и переключение между активными раскладками клавиатуры +Comment[sk]=Zobrazenie a prepínanie medzi aktívnymi rozloženiami klávesnice +Comment[sl]=Oglejte si in preklopite med dejavnimi razporeditvami tipk +Comment[sr]=Приказ и пребацивање између активних распореда тастатуре +Comment[sr@ijekavian]=Приказ и пребацивање између активних распореда тастатуре +Comment[sr@ijekavianlatin]=Prikaz i prebacivanje između aktivnih rasporeda tastature +Comment[sr@latin]=Prikaz i prebacivanje između aktivnih rasporeda tastature +Comment[sv]=Visa och byt mellan aktiva tangentbordslayouter +Comment[th]=ดูและสลับการจัดวางแป้นพิมพ์ที่ใช้งานอยู่ +Comment[tr]=Etkin klavye düzenlerini görüntüle ve geçiş yap +Comment[ug]=ئاكتىپ ھەرپتاختا جايلاشتۇرۇشى ئارىسىدا ئالماشتۇر ۋە كۆرسەت +Comment[uk]=Перегляд і перемикання між активними розкладками клавіатури +Comment[wa]=Vey eyet discandjî etur les adjinçmints del taprece ovrants +Comment[x-test]=xxView and switch between active keyboard layoutsxx +Comment[zh_CN]=查看和切换键盘布局 +Comment[zh_TW]=檢視並在可用的鍵盤佈局中切換 + +Icon=preferences-desktop-keyboard +Type=Service + +X-KDE-ServiceTypes=Plasma/Applet +X-KDE-Library=plasma_applet_keyboard +X-KDE-PluginInfo-Author=Andriy Rysin +X-KDE-PluginInfo-Email=rysin@kde.org +X-KDE-PluginInfo-Name=keyboard_applet +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=System Information +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-Plasma-NotificationArea=true diff --git a/kcms/keyboard/preview/TODO b/kcms/keyboard/preview/TODO new file mode 100644 index 0000000000..784924fe82 --- /dev/null +++ b/kcms/keyboard/preview/TODO @@ -0,0 +1,10 @@ +Important: +* display tooltip for each key with key description from symbol file + +Good to have: +* read keyboard geometry and show it properly instead of default keyboard +* use some common parser to parse symbol and geometry descriptions +* replace symkey2ucs with something more reliable (e.g. XLookupString?) + +Cleanup: +* clean up the code (especially kbpreviewframe.cpp) diff --git a/kcms/keyboard/preview/kbpreviewframe.cpp b/kcms/keyboard/preview/kbpreviewframe.cpp new file mode 100644 index 0000000000..f9cc5a3e58 --- /dev/null +++ b/kcms/keyboard/preview/kbpreviewframe.cpp @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "kbpreviewframe.h" + +#include +#include + +#include +#include + + +static const QColor keyBorderColor("#d4d4d4"); +static const QColor lev12color("#d4d4d4"); +static const QColor lev34color("#FF3300"); +static const int sz=20, kszx=70, kszy=70; + +static const int xOffset[] = {15, 15, 40, 40 }; +static const int yOffset[] = {10, 40, 10, 40 }; +static const QColor color[] = { lev12color, lev12color, lev34color, lev34color }; + + +// TODO: parse geometry files and display keyboard according to current keyboard model + +KbPreviewFrame::KbPreviewFrame(QWidget *parent) : + QFrame(parent) +{ + setFrameStyle( QFrame::Box ); + setFrameShadow(QFrame::Sunken); +} + +void KbPreviewFrame::paintTLDE(QPainter &painter,int &x,int &y) +{ + painter.setPen(keyBorderColor); + painter.drawRect(x, y, kszx, kszy); + + const QList symbols = keyboardLayout.TLDE.symbols; + + for(int level=0; level symbols = keyboardLayout.AE[i].symbols; + + for(int level=0; level")); + x+=tabszx; + + + for(int i=0; i symbols = keyboardLayout.AD[i].symbols; + + painter.setPen(keyBorderColor); + painter.drawRect(x, y,kszx,kszy); + + for(int level=0; level symbols = keyboardLayout.BKSL.symbols; + + for(int level=0; level symbols = keyboardLayout.AC[i].symbols; + + for(int level=0; level symbols = keyboardLayout.AB[i].symbols; + + for(int level=0; level symstr = content.split("xkb_symbols "); + + if( layoutVariant.isEmpty() ) { + keyboardLayout.generateLayout(symstr.at(1), layout); + } + else { + for(int i=1;i +#include + +class KbPreviewFrame : public QFrame +{ + Q_OBJECT + +private: + void paintTLDE(QPainter &painter, int &x, int &y); + void paintAERow(QPainter &painter, int &x, int &y); + void paintADRow(QPainter &painter, int &x, int &y); + void paintACRow(QPainter &painter, int &x, int &y); + void paintABRow(QPainter &painter, int &x, int &y); + void paintBottomRow(QPainter &painter, int &x, int &y); + void paintFnKeys(QPainter &painter, int &x, int &y); + + KeySymHelper symbol; + Aliases alias; + KeyboardLayout keyboardLayout; + +public: + explicit KbPreviewFrame(QWidget *parent = 0); + + void paintEvent(QPaintEvent * event); + void generateKeyboardLayout(const QString &country, const QString &layoutVariant); + QString getLayoutName() const { + return keyboardLayout.getLayoutName(); + } +}; + +#endif // KBPREVIEWFRAME_H diff --git a/kcms/keyboard/preview/keyaliases.cpp b/kcms/keyboard/preview/keyaliases.cpp new file mode 100644 index 0000000000..71d6a00804 --- /dev/null +++ b/kcms/keyboard/preview/keyaliases.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "keyaliases.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +Aliases::Aliases() +{ + QString filename=findaliasdir(); + QFile file(filename); + file.open(QIODevice::ReadOnly | QIODevice::Text); + QString content = file.readAll(); + file.close(); + QListals; + als=content.split("xkb_keycodes"); + for(int i=1;i"); + temp=temp.remove("<"); + temp=temp.remove(";"); + temp=temp.remove("}"); + temp=temp.remove("{"); + QListalskeys; + alskeys=temp.split("alias"); + if(temp.startsWith("qwerty")){ + for(int k=1;k= 3 ) { + // .../usr/lib/X11 -> /usr/share/X11/xkb vs .../usr/X11/lib -> /usr/X11/share/X11/xkb + QString delta = base.endsWith("X11") ? "/../../share/X11" : "/../share/X11"; + QDir baseDir(base + delta); + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + else { + QDir baseDir(base + "/X11"); // .../usr/X11/lib/X11/xkb (old XFree) + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + } + } + + if( xkbParentDir.isEmpty() ) { + xkbParentDir = "/usr/share/X11"; + } + aliasdir=QString("%1/xkb/keycodes/aliases").arg(xkbParentDir); + return(aliasdir); +} diff --git a/kcms/keyboard/preview/keyaliases.h b/kcms/keyboard/preview/keyaliases.h new file mode 100644 index 0000000000..3769e4eb29 --- /dev/null +++ b/kcms/keyboard/preview/keyaliases.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 ALIASES_H +#define ALIASES_H + +#include + +class Aliases +{ +private: + QMapqwerty; + QMapazerty; + QMapqwertz; + QString findaliasdir(); +public: + Aliases(); + QString getAlias(const QString &type, const QString &name); +}; + +#endif // ALIASES_H diff --git a/kcms/keyboard/preview/keyboardlayout.cpp b/kcms/keyboard/preview/keyboardlayout.cpp new file mode 100644 index 0000000000..9be0483cd5 --- /dev/null +++ b/kcms/keyboard/preview/keyboardlayout.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "keyboardlayout.h" +#include "keysymbols.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +//TODO: replace this with grammar parser (e.g. antlr) + + +KeyboardLayout::KeyboardLayout() +{ +} + +void KeyboardLayout::generateLayout(QString a,const QString& cname) +{ + includeSymbol(a,cname); + int i=a.indexOf("name[Group1]="); + i+=13; + + QString n=a.mid(i); + n=n.simplified(); + i=n.indexOf("\"",1); + layoutName=n.left(i); + layoutName.remove("\""); + layoutName.simplified(); + i=n.indexOf("key"); + n=n.mid(i); + + QList st; + st=n.split("key"); + + KeySymbols dum; + QString r,y; + + for(int k=0;ktobeinclude; + tobeinclude=a.split("include"); + + QString r; + for(int o=1;o incfile; + incfile=incsym.split("("); + for(int i=0;i symstrlist; + + symstrlist=content.split("xkb_symbols "); + for(int u=1;u= 3 ) { + // .../usr/lib/X11 -> /usr/share/X11/xkb vs .../usr/X11/lib -> /usr/X11/share/X11/xkb + QString delta = base.endsWith("X11") ? "/../../share/X11" : "/../share/X11"; + QDir baseDir(base + delta); + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + else { + QDir baseDir(base + "/X11"); // .../usr/X11/lib/X11/xkb (old XFree) + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + } + } + + if( xkbParentDir.isEmpty() ) { + xkbParentDir = "/usr/share/X11"; + } + + return QString("%1/xkb/symbols/").arg(xkbParentDir); +} diff --git a/kcms/keyboard/preview/keyboardlayout.h b/kcms/keyboard/preview/keyboardlayout.h new file mode 100644 index 0000000000..2d0c0883ca --- /dev/null +++ b/kcms/keyboard/preview/keyboardlayout.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 KEYBOARDLAYOUT_H +#define KEYBOARDLAYOUT_H + +#include "keysymbols.h" +#include "keyaliases.h" + +#include + +class KeyboardLayout +{ + QString layoutName; + Aliases alias; + +public: + KeyboardLayout(); + + KeySymbols TLDE; + KeySymbols BKSL; + KeySymbols AE[12]; + KeySymbols AD[12]; + KeySymbols AC[11]; + KeySymbols AB[11]; + + void generateLayout(QString a, const QString &cname); + QString findSymbolBaseDir(); + void includeSymbol(QString a, const QString &cname); + QString getLayoutName() const { + return layoutName; + } +}; + +#endif // KEYBOARDLAYOUT_H diff --git a/kcms/keyboard/preview/keyboardpainter.cpp b/kcms/keyboard/preview/keyboardpainter.cpp new file mode 100644 index 0000000000..268fcb0d0e --- /dev/null +++ b/kcms/keyboard/preview/keyboardpainter.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "keyboardpainter.h" + +#include +#include +#include + +#include + + +KeyboardPainter::KeyboardPainter(): + kbframe(new KbPreviewFrame(this)), + exitButton(new QPushButton(i18n("Close"),this)) +{ + kbframe->setFixedSize( 1030, 490 ); + exitButton->setFixedSize(120, 30); + + QVBoxLayout* vLayout = new QVBoxLayout( this ); + vLayout->addWidget(kbframe); + vLayout->addWidget(exitButton); + + connect(exitButton, SIGNAL(clicked()), this, SLOT(close())); + + setWindowTitle(kbframe->getLayoutName()); +} + +void KeyboardPainter::generateKeyboardLayout(const QString& layout, const QString& variant) +{ + kbframe->generateKeyboardLayout(layout, variant); +} + +KeyboardPainter::~KeyboardPainter() +{ + delete kbframe; + delete exitButton; +} diff --git a/kcms/keyboard/preview/keyboardpainter.h b/kcms/keyboard/preview/keyboardpainter.h new file mode 100644 index 0000000000..dde7b38099 --- /dev/null +++ b/kcms/keyboard/preview/keyboardpainter.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 KEYBOARDPAINTER_H +#define KEYBOARDPAINTER_H + +#include "kbpreviewframe.h" + +#include + +class QPushButton; + +class KeyboardPainter : public QDialog +{ + Q_OBJECT + +public: + explicit KeyboardPainter(); + ~KeyboardPainter(); + + void generateKeyboardLayout(const QString& layout, const QString& variant); + +private: + KbPreviewFrame *kbframe; + QPushButton *exitButton; +}; + +#endif // KEYBOARDPAINTER_H diff --git a/kcms/keyboard/preview/keysym2ucs.cpp b/kcms/keyboard/preview/keysym2ucs.cpp new file mode 100644 index 0000000000..37afb082b6 --- /dev/null +++ b/kcms/keyboard/preview/keysym2ucs.cpp @@ -0,0 +1,899 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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. + */ + +/* $XFree86$ + * This module converts keysym values into the corresponding ISO 10646-1 + * (UCS, Unicode) values. + * + * The array keysymtab[] contains pairs of X11 keysym values for graphical + * characters and the corresponding Unicode value. The function + * keysym2ucs() maps a keysym onto a Unicode value using a binary search, + * therefore keysymtab[] must remain SORTED by keysym value. + * + * The keysym -> UTF-8 conversion will hopefully one day be provided + * by Xlib via XmbLookupString() and should ideally not have to be + * done in X applications. But we are not there yet. + * + * We allow to represent any UCS character in the range U+00000000 to + * U+00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. + * This admittedly does not cover the entire 31-bit space of UCS, but + * it does cover all of the characters up to U+10FFFF, which can be + * represented by UTF-16, and more, and it is very unlikely that higher + * UCS codes will ever be assigned by ISO. So to get Unicode character + * U+ABCD you can directly use keysym 0x1000abcd. + * + * NOTE: The comments in the table below contain the actual character + * encoded in UTF-8, so for viewing and editing best use an editor in + * UTF-8 mode. + * + * Author: Markus G. Kuhn , University of Cambridge, June 1999 + * + * Special thanks to Richard Verhoeven for preparing + * an initial draft of the mapping table. + */ + +#include + +struct codepair { + unsigned short keysym; + unsigned short ucs; +} keysymtab[] = { + { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ + { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ + { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ + { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ + { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ + { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ + { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ + { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ + { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ + { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ + { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ + { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ + { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ + { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ + { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ + { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ + { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ + { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ + { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ + { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ + { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ + { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ + { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ + { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ + { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ + { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ + { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ + { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ + { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ + { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ + { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ + { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ + { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ + { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ + { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ + { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ + { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ + { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ + { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ + { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ + { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ + { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ + { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ + { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ + { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ + { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ + { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ + { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ + { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ + { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ + { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ + { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ + { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ + { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ + { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ + { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ + { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ + { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ + { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ + { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ + { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ + { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ + { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ + { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ + { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ + { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ + { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ + { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ + { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ + { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ + { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ + { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ + { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ + { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ + { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ + { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ + { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ + { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ + { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ + { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ + { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ + { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ + { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ + { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ + { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ + { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ + { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ + { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ + { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ + { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ + { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ + { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ + { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ + { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ + { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ + { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ + { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ + { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ + { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ + { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ + { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ + { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ + { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ + { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ + { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ + { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ + { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ + { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ + { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ + { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ + { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ + { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ + { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ + { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ + { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ + { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ + { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ + { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ + { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ + { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ + { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ + { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ + { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ + { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ + { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ + { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ + { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ + { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ + { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ + { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ + { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ + { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ + { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ + { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ + { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ + { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ + { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ + { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ + { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ + { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ + { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ + { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ + { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ + { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ + { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ + { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ + { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ + { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ + { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ + { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ + { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ + { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ + { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ + { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ + { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ + { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ + { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ + { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ + { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ + { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ + { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ + { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ + { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ + { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ + { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ + { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ + { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ + { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ + { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ + { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ + { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ + { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ + { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ + { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ + { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ + { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ + { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ + { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ + { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ + { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ + { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ + { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ + { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ + { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ + { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ + { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ + { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ + { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ + { 0x06ad, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ + { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ + { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ + { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ + { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ + { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ + { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ + { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ + { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ + { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ + { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ + { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ + { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ + { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ + { 0x06bd, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ + { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ + { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ + { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ + { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ + { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ + { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ + { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ + { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ + { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ + { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ + { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ + { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ + { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ + { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ + { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ + { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ + { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ + { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ + { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ + { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ + { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ + { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ + { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ + { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ + { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ + { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ + { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ + { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ + { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ + { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ + { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ + { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ + { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ + { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ + { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ + { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ + { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ + { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ + { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ + { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ + { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ + { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ + { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ + { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ + { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ + { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ + { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ + { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ + { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ + { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ + { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ + { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ + { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ + { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ + { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ + { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ + { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ + { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ + { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ + { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ + { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ + { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ + { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ + { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ + { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ + { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ + { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ + { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ + { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ + { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ + { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ + { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ + { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ + { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ + { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ + { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ + { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ + { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ + { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ + { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ + { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ + { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ + { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ + { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ + { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ + { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ + { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ + { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ + { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ + { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ + { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ + { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ + { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ + { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ + { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ + { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ + { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ + { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ + { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ + { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ + { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ + { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ + { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ + { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ + { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ + { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ + { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ + { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ + { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ + { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ + { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ + { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ + { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ + { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ + { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ + { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ + { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ + { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ + { 0x08a1, 0x23b7 }, /* leftradical ⎷ RADICAL SYMBOL BOTTOM */ + { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ + { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ + { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ + { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ LEFT SQUARE BRACKET UPPER CORNER */ + { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ LEFT SQUARE BRACKET LOWER CORNER */ + { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ RIGHT SQUARE BRACKET UPPER CORNER */ + { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ RIGHT SQUARE BRACKET LOWER CORNER */ + { 0x08ab, 0x239b }, /* topleftparens ⎛ LEFT PARENTHESIS UPPER HOOK */ + { 0x08ac, 0x239d }, /* botleftparens ⎝ LEFT PARENTHESIS LOWER HOOK */ + { 0x08ad, 0x239e }, /* toprightparens ⎞ RIGHT PARENTHESIS UPPER HOOK */ + { 0x08ae, 0x23a0 }, /* botrightparens ⎠ RIGHT PARENTHESIS LOWER HOOK */ + { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ LEFT CURLY BRACKET MIDDLE PIECE */ + { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ RIGHT CURLY BRACKET MIDDLE PIECE */ +/* 0x08b1 topleftsummation ? ??? */ +/* 0x08b2 botleftsummation ? ??? */ +/* 0x08b3 topvertsummationconnector ? ??? */ +/* 0x08b4 botvertsummationconnector ? ??? */ +/* 0x08b5 toprightsummation ? ??? */ +/* 0x08b6 botrightsummation ? ??? */ +/* 0x08b7 rightmiddlesummation ? ??? */ + { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ + { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ + { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ + { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ + { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ + { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ + { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ + { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ + { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ + { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ + { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ + { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ + { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ + { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ + { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ + { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ + { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ + { 0x08dd, 0x222a }, /* union ∪ UNION */ + { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ + { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ + { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ + { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ + { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ + { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ + { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ + { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ + { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ + { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ + { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ + { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ + { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ + { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ + { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ + { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ + { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ + { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ + { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ + { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ + { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ + { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 */ + { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 */ + { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ + { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 */ + { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 */ + { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ + { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ + { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ + { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ + { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ + { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ + { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ + { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ + { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ + { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ + { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ + { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ + { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ + { 0x0aaa, 0x2013 }, /* endash – EN DASH */ + { 0x0aac, 0x2423 }, /* signifblank ␣ OPEN BOX */ + { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ + { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ + { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ + { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ + { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ + { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ + { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ + { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ + { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ + { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ + { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ + { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ + { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ + { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ + { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ +/* 0x0abf marker ? ??? */ + { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ + { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ + { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ + { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ + { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ + { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ +/* 0x0acb trademarkincircle ? ??? */ + { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ + { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ + { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ + { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ + { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ + { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ + { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ + { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ + { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ +/* 0x0ad5 permille ? ??? */ + { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ + { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ + { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ +/* 0x0ada hexagram ? ??? */ + { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ + { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ + { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ + { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ + { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ + { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ + { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ + { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ + { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ + { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ + { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ + { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ + { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ + { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ + { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ + { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ + { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ + { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ + { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ + { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ + { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ + { 0x0af1, 0x2020 }, /* dagger † DAGGER */ + { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ + { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ + { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ + { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ + { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ + { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ + { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ + { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ + { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ + { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ + { 0x0afc, 0x2038 }, /* caret ‸ CARET */ + { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ + { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ +/* 0x0aff cursor ? ??? */ + { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ + { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ + { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ + { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ + { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ + { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ + { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ + { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ + { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ + { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ + { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ + { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ + { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ + { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ + { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ + { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ + { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ + { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ + { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ + { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ + { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ + { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ + { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ + { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ + { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ + { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ + { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ + { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ + { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ + { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ + { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ + { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ + { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ + { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ + { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ + { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ + { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ + { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ + { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ + { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ + { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ + { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ + { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ + { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ + { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ + { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ + { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ + { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ + { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ + { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ + { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ + { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ + { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ + { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ + { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ + { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ + { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ + { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ + { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ + { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ + { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ + { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ + { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ + { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ + { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ + { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ + { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ + { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ + { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ + { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ + { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ + { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ + { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ + { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ + { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ + { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ + { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ + { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ + { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ + { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ + { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ + { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ + { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ + { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ + { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ + { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ + { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ + { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ + { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ + { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ + { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ + { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ + { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ + { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ + { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ + { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ + { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ + { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ + { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ + { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ + { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ + { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ + { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ + { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ + { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ + { 0x0dde, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ + { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ + { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ + { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ + { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ + { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ + { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ + { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ + { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ + { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ + { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ + { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ + { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ + { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ + { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ + { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ + { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ + { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ + { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ + { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ + { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ + { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ + { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ + { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ + { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ + { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ + { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ + { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ + { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ + { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ + { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ + { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ + { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ + { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ + { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ + { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ + { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ + { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ + { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ + { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ + { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ + { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ + { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ + { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ + { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ + { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ + { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ + { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ + { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ + { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ + { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ + { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ + { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ + { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ + { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ + { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ + { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ + { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ + { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ + { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ + { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ + { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ + { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ + { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ + { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ + { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ + { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ + { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ + { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ + { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ + { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ + { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ + { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ + { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ + { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ + { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ + { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ + { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ + { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ + { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ + { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ + { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ + { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ + { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ + { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ + { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ + { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ + { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ + { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ + { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ + { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ + { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ + { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ + { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ + { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ + { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ + { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ + { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ + { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ + { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ + { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ + { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ + { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ + { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ + { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ + { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ + { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ + { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ + { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ + { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ + { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ + { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ + { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ + { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ + { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ + { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ + { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ + { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ + { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ + { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ + { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ + + /* Combining symbols */ + { 0xfe50, 0x0300 }, /* dead_grave */ + { 0xfe51, 0x0301 }, /* dead_acute" */ + { 0xfe52, 0x0302 }, /* dead_circumflex" */ + { 0xfe53, 0x0303 }, /* dead_tilde" */ + { 0xfe54, 0x0304 }, /* dead_macron" */ + { 0xfe55, 0x0306 }, /* dead_breve" */ + { 0xfe56, 0x0307 }, /* dead_abovedot" */ + { 0xfe57, 0x0308 }, /* dead_diaeresis" */ + { 0xfe58, 0x030A }, /* dead_abovering" */ + { 0xfe59, 0x030B }, /* dead_doubleacute" */ + { 0xfe5a, 0x030C }, /* dead_caron" */ + { 0xfe5b, 0x0327 }, /* dead_cedilla" */ + { 0xfe5c, 0x0328 }, /* dead_ogonek" */ + { 0xfe60, 0x0323 }, /* dead_belowdot */ + + /* Special function keys. */ + + { 0xff08, 0x0008 }, /* XK_BackSpace */ + { 0xff09, 0x0009 }, /* XK_Tab */ + { 0xff0a, 0x000a }, /* XK_Linefeed */ + { 0xff0d, 0x000d }, /* XK_Return */ + { 0xff13, 0x0013 }, /* XK_Pause */ + { 0xff1b, 0x001b }, /* XK_Escape */ + { 0xff50, 0x0001 }, /* XK_Home */ + { 0xff51, 0x001c }, /* XK_Left */ + { 0xff52, 0x001e }, /* XK_Up */ + { 0xff53, 0x001d }, /* XK_Right */ + { 0xff54, 0x001f }, /* XK_Down */ + { 0xff55, 0x000b }, /* XK_Prior */ + { 0xff56, 0x000c }, /* XK_Next */ + { 0xff57, 0x0004 }, /* XK_End */ + { 0xff6a, 0x0005 }, /* XK_Help */ + { 0xffff, 0x007f }, /* XK_Delete */ +}; + +long keysym2ucs(KeySym keysym) +{ + int min = 0; + int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; + int mid; + + /* first check for Latin-1 characters (1:1 mapping) */ + if ((keysym >= 0x0020 && keysym <= 0x007e) || + (keysym >= 0x00a0 && keysym <= 0x00ff)) + return keysym; + + /* also check for directly encoded 24-bit UCS characters */ + if ((keysym & 0xff000000) == 0x01000000) + return keysym & 0x00ffffff; + + /* binary search in table */ + while (max >= min) { + mid = (min + max) / 2; + if (keysymtab[mid].keysym < keysym) + min = mid + 1; + else if (keysymtab[mid].keysym > keysym) + max = mid - 1; + else { + /* found it */ + return keysymtab[mid].ucs; + } + } + + /* no matching Unicode value found */ + return -1; +} diff --git a/kcms/keyboard/preview/keysym2ucs.h b/kcms/keyboard/preview/keysym2ucs.h new file mode 100644 index 0000000000..6e50c76452 --- /dev/null +++ b/kcms/keyboard/preview/keysym2ucs.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 Andriy Rysin (arysin@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 KEYSYM2UCS_H +#define KEYSYM2UCS_H + +#include +#include + +extern long keysym2ucs(KeySym keysym); + +#endif diff --git a/kcms/keyboard/preview/keysymbols.cpp b/kcms/keyboard/preview/keysymbols.cpp new file mode 100644 index 0000000000..cea16aeb33 --- /dev/null +++ b/kcms/keyboard/preview/keysymbols.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "keysymbols.h" + +#include +#include + + +static const int MAX_GROUPS_SUPPORTED = 4; + +KeySymbols::KeySymbols() +{ +} + +void KeySymbols::setKey(const QString& a) +{ + int i=a.indexOf("<"); + i++; + keyname=a.mid(i,4); + keyname.remove(" "); + i=a.indexOf("["); + i++; + + QString str=a.mid(i); + i=str.indexOf("]"); + + QString st=str.left(i); + st=st.remove(" "); + //QStringList klst; + symbols=st.split(","); + + if( symbols.size() > MAX_GROUPS_SUPPORTED ) { + symbols = symbols.mid(0, MAX_GROUPS_SUPPORTED); + } + + for(int k=0;k +#include + +class KeySymbols +{ +public: + KeySymbols(); + + QString keyname; + QList symbols; + + void setKey(const QString& opton); +}; + +#endif // KEYSYMBOLS_H diff --git a/kcms/keyboard/preview/keysymhelper.cpp b/kcms/keyboard/preview/keysymhelper.cpp new file mode 100644 index 0000000000..67beb80db5 --- /dev/null +++ b/kcms/keyboard/preview/keysymhelper.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "keysymhelper.h" +#include "keysym2ucs.h" + +#include +#include + +#include + +#include + + +KeySymHelper::KeySymHelper() +{ + nill = 0; +} + +QString KeySymHelper::getKeySymbol(const QString& opton) +{ + if( keySymbolMap.contains(opton) ) + return keySymbolMap[opton]; + + const char* str = opton.toAscii().data(); + +#if 0 + //TODO: figure out how to use this so we don't need our own symkey2ucs mapping + int res = Xutf8LookupString(XIC ic, XKeyPressedEvent *event, char *buffer_return, int bytes_buffer, KeySym *keysym_return, Status *status_return); + +#else + + KeySym keysym = XStringToKeysym(str); + long ucs = keysym2ucs(keysym); + +// if( ucs == -1 && (keysym >= 0xFE50 && keysym <= 0xFE5F) ) { +// ucs = 0x0300 + (keysym & 0x000F); +// kWarning() << "Got dead symbol" << QString("0x%1").arg(keysym, 0, 16) << "named" << opton << "will use" << QString("0x%1").arg(ucs, 0, 16) << "as UCS"; +// } + + if( ucs == -1 ) { + nill++; + kWarning() << "No mapping from keysym:" << QString("0x%1").arg(keysym, 0, 16) << "named:" << opton << "to UCS"; + } + + QString ucsStr = QString(QChar((int)ucs)); + + // Combining Diacritical Marks + if( ucs >= 0x0300 && ucs <= 0x036F ) { + ucsStr = " " + ucsStr + " "; + } + +// kWarning() << "--" << opton << "keysym: " << keysym << QString("0x%1").arg(keysym, 0, 16) << "keysym2string" << XKeysymToString(keysym) +// << "---" << QString("0x%1").arg(ucs, 0, 16) << ucsStr; + + keySymbolMap[opton] = ucsStr; + + return ucsStr; + +#endif + +} + diff --git a/kcms/keyboard/preview/keysymhelper.h b/kcms/keyboard/preview/keysymhelper.h new file mode 100644 index 0000000000..763e872ebc --- /dev/null +++ b/kcms/keyboard/preview/keysymhelper.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 KEYSYMHELPER_H +#define KEYSYMHELPER_H + +#include +#include + +class KeySymHelper +{ +public: + KeySymHelper(); + + QString getKeySymbol(const QString &opton); + bool isFailed() const { + return nill >= 120; + } + +private: + QMap keySymbolMap; + int nill; +}; + +#endif // KEYSYMHELPER_H diff --git a/kcms/keyboard/tests/CMakeLists.txt b/kcms/keyboard/tests/CMakeLists.txt new file mode 100644 index 0000000000..7f05ed7a6e --- /dev/null +++ b/kcms/keyboard/tests/CMakeLists.txt @@ -0,0 +1,55 @@ +macro(KEYBOARD_DAEMON_UNIT_TESTS _testname) + kde4_add_unit_test(${_testname}_test TESTNAME kcm-keyboard-${_testname} NOGUI ${_testname}_test.cpp ../${_testname}.cpp) + target_link_libraries(${_testname}_test + Qt5::Concurrent + Qt5::Widgets + Qt5::X11Extras + Qt5::Xml + Qt5::Test + KF5::I18n + KF5::KDE4Support + ${X11_Xkbfile_LIB} + ${X11_LIBRARIES} +) +endmacro(KEYBOARD_DAEMON_UNIT_TESTS) + +keyboard_daemon_unit_tests(xkb_rules) +keyboard_daemon_unit_tests(iso_codes) + +kde4_add_unit_test(flags_test TESTNAME kcm-keyboard-flags_test NOGUI flags_test.cpp ../flags.cpp ../x11_helper.cpp ../keyboard_config.cpp ../xkb_rules.cpp) +target_link_libraries(flags_test + Qt5::Concurrent + Qt5::X11Extras + Qt5::Xml + Qt5::Test + KF5::I18n + KF5::Plasma + KF5::KDE4Support + ${X11_Xkbfile_LIB} + ${X11_LIBRARIES} +) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.1.1.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.1.1.xml COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.bad.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.bad.xml COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config/base.xml ${CMAKE_CURRENT_BINARY_DIR}/config/base.xml COPYONLY) + +if( X11_XTest_FOUND ) + kde4_add_unit_test(keyboard_daemon_test TESTNAME kcm-keyboard-keyboard_daemon_test NOGUI keyboard_daemon_test.cpp ../keyboard_daemon.cpp ../layout_memory.cpp ../layout_memory_persister.cpp ../flags.cpp ../x11_helper.cpp ../xkb_helper.cpp ../xinput_helper.cpp ../layout_tray_icon.cpp ../keyboard_config.cpp ../xkb_rules.cpp ../keyboard_hardware.cpp ../bindings.cpp ../layouts_menu.cpp ../numlockx.c) + target_link_libraries(keyboard_daemon_test + Qt5::Concurrent + Qt5::X11Extras + Qt5::Xml + Qt5::Test + KF5::ConfigCore + KF5::CoreAddons + KF5::DBusAddons + KF5::Plasma + KF5::KDE4Support + ${X11_Xkbfile_LIB} + ${X11_XTest_LIB} + ${X11_LIBRARIES} +) + if(XiGetDevicePresence_FOUND) + target_link_libraries(keyboard_daemon_test ${X11_Xinput_LIB}) + endif() +endif() diff --git a/kcms/keyboard/tests/config/base.1.1.xml b/kcms/keyboard/tests/config/base.1.1.xml new file mode 100644 index 0000000000..97206a0b7b --- /dev/null +++ b/kcms/keyboard/tests/config/base.1.1.xml @@ -0,0 +1,68 @@ + + + + + + + pc101 + Generic 101-key PC + Generic + + + + + + + us + USA + USA + eng + + + + + chr + Cherokee + chr + + + chr + Cherokee2 + + + + bad + Bad Variant Missing configItem tag + chr + + + + + + tw + + zh + Taiwanese + + fox + + + + + + + + + grp + Key(s) to change layout + + + + + + \ No newline at end of file diff --git a/kcms/keyboard/tests/config/base.bad.xml b/kcms/keyboard/tests/config/base.bad.xml new file mode 100644 index 0000000000..75bacdd2d4 --- /dev/null +++ b/kcms/keyboard/tests/config/base.bad.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/kcms/keyboard/tests/config/base.xml b/kcms/keyboard/tests/config/base.xml new file mode 100644 index 0000000000..ddab0561c1 --- /dev/null +++ b/kcms/keyboard/tests/config/base.xml @@ -0,0 +1,48 @@ + + + + + + + pc101 + Generic 101-key PC + Generic + + + + + + + us + USA + USA + eng + + + + + chr + Cherokee + chr + + + + + + + + + + grp + Key(s) to change layout + + + + + + \ No newline at end of file diff --git a/kcms/keyboard/tests/flags_test.cpp b/kcms/keyboard/tests/flags_test.cpp new file mode 100644 index 0000000000..59f73716dc --- /dev/null +++ b/kcms/keyboard/tests/flags_test.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 +#include +#include + +#include "../flags.h" +#include "../xkb_rules.h" +#include "../keyboard_config.h" + + +static QImage image(const QIcon& icon) { + return icon.pixmap(QSize(16,16), QIcon::Normal, QIcon::On).toImage(); +} + +class FlagsTest : public QObject +{ + Q_OBJECT + + Flags* flags; + const Rules* rules; + +private Q_SLOTS: + void initTestCase() { + flags = new Flags(); + rules = NULL; + } + + void cleanupTestCase() { + delete flags; + delete rules; + } + + void testRules() { + QVERIFY( flags != NULL ); + + QVERIFY( ! flags->getTransparentPixmap().isNull() ); + + const QIcon iconUs(flags->getIcon("us")); + QVERIFY( ! iconUs.isNull() ); + QVERIFY( flags->getIcon("--").isNull() ); + + KeyboardConfig keyboardConfig; + LayoutUnit layoutUnit("us"); + LayoutUnit layoutUnit1("us", "intl"); + layoutUnit1.setDisplayName("usi"); + LayoutUnit layoutUnit2("us", "other"); + + keyboardConfig.indicatorType = KeyboardConfig::SHOW_FLAG; + const QIcon iconUsFlag = flags->getIconWithText(layoutUnit, keyboardConfig); + QVERIFY( ! iconUsFlag.isNull() ); + QCOMPARE( image(iconUsFlag), image(iconUs) ); + + keyboardConfig.indicatorType = KeyboardConfig::SHOW_LABEL; + const QIcon iconUsText = flags->getIconWithText(layoutUnit, keyboardConfig); + QVERIFY( ! iconUsText.isNull() ); + QVERIFY( image(iconUsText) != image(iconUs) ); + + keyboardConfig.layouts.append(layoutUnit1); + QCOMPARE( flags->getShortText(layoutUnit, keyboardConfig), QString("us") ); + QCOMPARE( flags->getShortText(layoutUnit1, keyboardConfig), QString("usi") ); + QCOMPARE( flags->getShortText(layoutUnit2, keyboardConfig), QString("us") ); + + const Rules* rules = Rules::readRules(Rules::NO_EXTRAS); + QCOMPARE( flags->getLongText(layoutUnit, rules), QString("English (US)") ); + QVERIFY( flags->getLongText(layoutUnit1, rules).startsWith("English (US, international with dead keys)") ); + QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("other") ); + + rules = NULL; // when no rules found + QCOMPARE( flags->getLongText(layoutUnit1, rules), QString("us - intl") ); + + flags->clearCache(); + } + +// void loadRulesBenchmark() { +// QBENCHMARK { +// Flags* flags = new Flags(); +// delete flags; +// } +// } + +}; + +// need GUI for xkb protocol in xkb_rules.cpp +QTEST_KDEMAIN( FlagsTest, GUI ) + +#include "flags_test.moc" diff --git a/kcms/keyboard/tests/iso_codes_test.cpp b/kcms/keyboard/tests/iso_codes_test.cpp new file mode 100644 index 0000000000..886f5662b0 --- /dev/null +++ b/kcms/keyboard/tests/iso_codes_test.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 +#include +#include + +#include "../iso_codes.h" + + +class IsoCodesTest : public QObject +{ + Q_OBJECT + + IsoCodes* isoCodes; + +private Q_SLOTS: + void initTestCase() { +// isoCodes = new IsoCodes(IsoCodes::iso_639); + isoCodes = new IsoCodes(IsoCodes::iso_639_3); + } + + void cleanupTestCase() { + delete isoCodes; + } + + void testIsoCodes() { + QVERIFY( isoCodes != NULL ); + QVERIFY( ! isoCodes->getEntryList().isEmpty() ); +// const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_2T_code, "eng"); + const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_3_id, "eng"); + QVERIFY( isoEntry != NULL ); + QVERIFY( ! isoEntry->empty() ); +// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_2T_code), QString("eng") ); +// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_2B_code), QString("eng") ); +// QCOMPARE( isoEntry->value(IsoCodes::attr_iso_639_1_code), QString("en") ); + QCOMPARE( isoEntry->value("name"), QString("English") ); +// QCOMPARE( isoEntry->value("status"), QString("Active") ); + } + + void testIso639_3_Codes() { + QVERIFY( isoCodes != NULL ); + QVERIFY( ! isoCodes->getEntryList().isEmpty() ); + const IsoCodeEntry* isoEntry = isoCodes->getEntry(IsoCodes::attr_iso_639_3_id, "ant"); + QVERIFY( isoEntry != NULL ); + QVERIFY( ! isoEntry->empty() ); + QVERIFY( isoEntry->value("name") != QString("ant") ); + QCOMPARE( isoEntry->value("name"), QString("Antakarinya") ); + } + + void loadIsoCodesBenchmark() { + QBENCHMARK { + IsoCodes* isoCodes = new IsoCodes(IsoCodes::iso_639_3); + delete isoCodes; + } + } + +}; + +//TODO: something lighter than KDEMAIN ? +QTEST_KDEMAIN( IsoCodesTest, NoGUI ) + +#include "iso_codes_test.moc" diff --git a/kcms/keyboard/tests/keyboard_daemon_test.cpp b/kcms/keyboard/tests/keyboard_daemon_test.cpp new file mode 100644 index 0000000000..8879daf9a9 --- /dev/null +++ b/kcms/keyboard/tests/keyboard_daemon_test.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 +//#include + +#include +#include + +#include "../flags.h" +#include "../xkb_rules.h" +#include "../keyboard_config.h" +#include "../keyboard_daemon.h" + + +class KeyboardDaemonTest : public QObject +{ + Q_OBJECT + + KeyboardDaemon* keyboardDaemon; +// KApplication* kapplication; + +private Q_SLOTS: + void initTestCase() { +// kapplication = new KApplication(); +// const KAboutData* kAboutData = new KAboutData(i18n("a").toAscii(), i18n("a").toAscii(), KLocalizedString(), i18n("a").toAscii()); +// KCmdLineArgs::init(kAboutData); + keyboardDaemon = new KeyboardDaemon(this, QList()); + } + + void cleanupTestCase() { + delete keyboardDaemon; +// delete kapplication; + } + + void testDaemon() { + QVERIFY( keyboardDaemon != NULL ); + +// QVERIFY( ! flags->getTransparentPixmap().isNull() ); +// +// const QIcon iconUs(flags->getIcon("us")); +// QVERIFY( ! iconUs.isNull() ); +// QVERIFY( flags->getIcon("--").isNull() ); +// +// KeyboardConfig keyboardConfig; +// LayoutUnit layoutUnit("us"); +// LayoutUnit layoutUnit1("us", "intl"); +// layoutUnit1.setDisplayName("usi"); +// LayoutUnit layoutUnit2("us", "other"); +// +// keyboardConfig.showFlag = true; +// const QIcon iconUsFlag = flags->getIconWithText(layoutUnit, keyboardConfig); +// QVERIFY( ! iconUsFlag.isNull() ); +// QCOMPARE( image(iconUsFlag), image(iconUs) ); +// +// keyboardConfig.showFlag = false; +// const QIcon iconUsText = flags->getIconWithText(layoutUnit, keyboardConfig); +// QVERIFY( ! iconUsText.isNull() ); +// QVERIFY( image(iconUsText) != image(iconUs) ); +// +// keyboardConfig.layouts.append(layoutUnit1); +// QCOMPARE( flags->getShortText(layoutUnit, keyboardConfig), QString("us") ); +// QCOMPARE( flags->getShortText(layoutUnit1, keyboardConfig), QString("usi") ); +// QCOMPARE( flags->getShortText(layoutUnit2, keyboardConfig), QString("us") ); +// +// const Rules* rules = Rules::readRules(); +// QCOMPARE( flags->getLongText(layoutUnit, rules), QString("USA") ); +// QVERIFY( flags->getLongText(layoutUnit1, rules).startsWith("USA - International") ); +// QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("USA - other") ); +// +// flags->clearCache(); + } + +// void loadRulesBenchmark() { +// QBENCHMARK { +// Flags* flags = new Flags(); +// delete flags; +// } +// } + +}; + +// need GUI for xkb protocol in xkb_rules.cpp +QTEST_KDEMAIN( KeyboardDaemonTest, GUI ) + +#include "keyboard_daemon_test.moc" diff --git a/kcms/keyboard/tests/layout_memory_persister_test.cpp b/kcms/keyboard/tests/layout_memory_persister_test.cpp new file mode 100644 index 0000000000..0dd0c74c8b --- /dev/null +++ b/kcms/keyboard/tests/layout_memory_persister_test.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 +#include +#include + +#include "../layout_memory_persister.h" +#include "../layout_memory.h" +#include "../keyboard_config.h" + + +class TestLayoutMemory: public LayoutMemory { +public: + TestLayoutMemory(const KeyboardConfig& keyboardConfig): + LayoutMemory(keyboardConfig) {} + QMap& getLayoutMap() { return layoutMap; } +}; + +class LayoutMemoryPersisterTest : public QObject +{ + Q_OBJECT + + QString path; + KeyboardConfig keyboardConfig; + TestLayoutMemory* layoutMemory; + LayoutMemoryPersister* layoutMemoryPersister; + + const LayoutUnit layoutUnit1; + const LayoutUnit layoutUnit2; + const LayoutUnit layoutUnit3; + + +public: + LayoutMemoryPersisterTest(): + layoutUnit1("xx"), + layoutUnit2("yy", "var1"), + layoutUnit3("zz", "var2") + {} + +private Q_SLOTS: + void initTestCase() { + path = "keyboard_memory_test.xml"; + QFile(path).remove(); + + layoutMemory = new TestLayoutMemory(keyboardConfig); + layoutMemoryPersister = new LayoutMemoryPersister(*layoutMemory); + +// QFile(path).remove(); + } + + void cleanupTestCase() { + delete layoutMemoryPersister; + delete layoutMemory; + } + + void testSaveNA() { + QFile file(path); + + keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_WINDOW; + QVERIFY( ! layoutMemoryPersister->saveToFile(file) ); + QVERIFY(QFile(path).size() == 0); + + QVERIFY( ! layoutMemoryPersister->restoreFromFile(file) ); + } + + void testSaveGlobal() { + QFile file(path); + + keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_GLOBAL; + layoutMemoryPersister->setGlobalLayout(layoutUnit1); + QVERIFY( layoutMemoryPersister->saveToFile(file) ); + QVERIFY(QFile(path).size() > 0); +// file.close(); + + keyboardConfig.layouts.clear(); + + QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); + QVERIFY( !layoutMemoryPersister->getGlobalLayout().isValid() ); + +// file.close(); + keyboardConfig.layouts << layoutUnit1; + QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); + QVERIFY( layoutUnit1.isValid() ); + QVERIFY( layoutMemoryPersister->getGlobalLayout().isValid() ); + QCOMPARE( layoutMemoryPersister->getGlobalLayout(), layoutUnit1); + } + + void testSaveByApp() { + QFile file(path); + + keyboardConfig.switchingPolicy = KeyboardConfig::SWITCH_POLICY_APPLICATION; + + layoutMemoryPersister->setGlobalLayout(LayoutUnit()); + layoutMemory->getLayoutMap().clear(); + + keyboardConfig.layouts.clear(); + keyboardConfig.layouts << layoutUnit1 << layoutUnit2; + + LayoutSet layoutSet1; + layoutSet1.layouts << layoutUnit1 << layoutUnit2; + layoutSet1.currentLayout = layoutUnit1; + layoutMemory->getLayoutMap().insert(QString("app1"), layoutSet1); + + LayoutSet layoutSet2; + layoutSet2.layouts << layoutUnit2 << layoutUnit1 << layoutUnit3; + layoutSet2.currentLayout = layoutUnit2; + layoutMemory->getLayoutMap().insert(QString("app2"), layoutSet2); + + QVERIFY( layoutMemoryPersister->saveToFile(file) ); + QVERIFY(QFile(path).size() > 0); + file.close(); + + layoutMemory->getLayoutMap().clear(); + QVERIFY( ! layoutMemory->getLayoutMap().value("app1").isValid() ); + QVERIFY( ! layoutMemory->getLayoutMap().value("app2").isValid() ); + + QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); + QVERIFY( ! layoutMemoryPersister->getGlobalLayout().isValid() ); + QCOMPARE( layoutMemory->getLayoutMap().value("app1"), layoutSet1 ); + QVERIFY( ! layoutMemory->getLayoutMap().value("app2").isValid() ); + + keyboardConfig.layouts << layoutUnit3; + + file.close(); + QVERIFY( layoutMemoryPersister->restoreFromFile(file) ); + QVERIFY( ! layoutMemoryPersister->getGlobalLayout().isValid() ); + QCOMPARE( layoutMemory->getLayoutMap().value("app1"), layoutSet1 ); + QCOMPARE( layoutMemory->getLayoutMap().value("app2"), layoutSet2 ); + } + +// void layoutMemroyPersisterBenchmark() { +// QBENCHMARK { +// //TODO: generate big map +// layoutMemoryPersister->save(); +// layoutMemoryPersister->restore(); +// } +// } + +}; + +// need GUI for xkb protocol +QTEST_KDEMAIN( LayoutMemoryPersisterTest, GUI ) + +#include "layout_memory_persister_test.moc" diff --git a/kcms/keyboard/tests/xkb_rules_test.cpp b/kcms/keyboard/tests/xkb_rules_test.cpp new file mode 100644 index 0000000000..daef508c76 --- /dev/null +++ b/kcms/keyboard/tests/xkb_rules_test.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2011 Andriy Rysin (rysin@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 +#include +#include + +#include "../xkb_rules.h" + +#include +#include + +static const Rules::ExtrasFlag readExtras = Rules::NO_EXTRAS; + +class RulesTest : public QObject +{ + Q_OBJECT + + Rules* rules; + +private Q_SLOTS: + void initTestCase() { + rules = Rules::readRules(readExtras); + } + + void cleanupTestCase() { + delete rules; + } + + void testRules() { + QVERIFY( rules != NULL ); + QVERIFY( rules->modelInfos.size() > 0 ); + QVERIFY( rules->layoutInfos.size() > 0 ); + QVERIFY( rules->optionGroupInfos.size() > 0 ); + } + + void testModel() { + foreach(const ModelInfo* modelInfo, rules->modelInfos) { + QVERIFY( modelInfo != NULL); + QVERIFY( modelInfo->name.length() > 0 ); + QVERIFY( modelInfo->description.length() > 0 ); +// QVERIFY( ! modelInfo->vendor.isEmpty() ); + } + } + + void testLayouts() { + foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { + QVERIFY( layoutInfo != NULL); + QVERIFY( ! layoutInfo->name.isEmpty() ); +// const char* desc = layoutInfo->name.toUtf8() ; +// qDebug() << layoutInfo->name; + QVERIFY( ! layoutInfo->description.isEmpty() ); + + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + QVERIFY( variantInfo != NULL ); + QVERIFY( ! variantInfo->name.isEmpty() ); + QVERIFY( ! variantInfo->description.isEmpty() ); + } + foreach(const QString& language, layoutInfo->languages) { + QVERIFY( ! language.isEmpty() ); + } + } + } + + void testOptionGroups() { + foreach(const OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { + QVERIFY( optionGroupInfo != NULL); + QVERIFY( ! optionGroupInfo->name.isEmpty() ); + QVERIFY( ! optionGroupInfo->description.isEmpty() ); + // optionGroupInfo->exclusive + + foreach(const OptionInfo* optionInfo, optionGroupInfo->optionInfos) { + QVERIFY( optionInfo != NULL ); + QVERIFY( ! optionInfo->name.isEmpty() ); + QVERIFY( ! optionInfo->description.isEmpty() ); + } + } + } + + void testExtras() { + Rules* rulesWithExtras = Rules::readRules(Rules::READ_EXTRAS); + QVERIFY2(rulesWithExtras->layoutInfos.size() > rules->layoutInfos.size(), "Rules with extras should have more layouts"); + + foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { + QVERIFY( ! layoutInfo->fromExtras ); + } + + bool foundFromExtras = false, foundNonExtras = false; + foreach(const LayoutInfo* layoutInfo, rulesWithExtras->layoutInfos) { + if( layoutInfo->fromExtras ) foundFromExtras = true; + if( ! layoutInfo->fromExtras ) foundNonExtras = true; + layoutInfo->languages.size(); // make sure we can access all merged objects + layoutInfo->variantInfos.size(); // make sure we can access all merged objects + } + QVERIFY( foundNonExtras ); + QVERIFY( foundFromExtras ); + } + + void testWriteNewXml() { + QDomDocument doc("xkbConfigRegistry"); + QDomElement root = doc.createElement("xkbConfigRegistry"); + root.setAttribute("version", "2.0"); + doc.appendChild(root); + + QDomElement modelList = doc.createElement("modelList"); + root.appendChild(modelList); + foreach(const ModelInfo* modelInfo, rules->modelInfos) { + QDomElement model = doc.createElement("model"); + model.setAttribute("name", modelInfo->name); + model.setAttribute("description", modelInfo->description); + model.setAttribute("vendor", modelInfo->vendor); + modelList.appendChild(model); + } + + QDomElement layoutList = doc.createElement("layoutList"); + foreach(const LayoutInfo* layoutInfo, rules->layoutInfos) { + QDomElement layout = doc.createElement("layout"); + layout.setAttribute("name", layoutInfo->name); + layout.setAttribute("description", layoutInfo->description); + + QDomElement langList = doc.createElement("languageList"); + foreach(const QString& lang, layoutInfo->languages) { + QDomElement langNode = doc.createElement("lang"); + langNode.setAttribute("iso639Id", lang); + langList.appendChild(langNode); + } + if( langList.hasChildNodes() ) { + layout.appendChild(langList); + } + + QDomElement variantList = doc.createElement("variantList"); + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + QDomElement variant = doc.createElement("variant"); + variant.setAttribute("name", variantInfo->name); + variant.setAttribute("description", variantInfo->description); + + QDomElement langList = doc.createElement("languageList"); + foreach(const QString& lang, variantInfo->languages) { + QDomElement langNode = doc.createElement("lang"); + langNode.setAttribute("iso639Id", lang); + langList.appendChild(langNode); + } + if( langList.hasChildNodes() ) { + variant.appendChild(langList); + } + + variantList.appendChild(variant); + } + if( variantList.hasChildNodes() ) { + layout.appendChild(variantList); + } + + layoutList.appendChild(layout); + } + root.appendChild(layoutList); + + QDomElement optionGroupList = doc.createElement("optionList"); + foreach(const OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { + QDomElement optionGroup = doc.createElement("optionGroup"); + optionGroup.setAttribute("name", optionGroupInfo->name); + optionGroup.setAttribute("description", optionGroupInfo->description); + optionGroup.setAttribute("exclusive", optionGroupInfo->exclusive); + + foreach(const OptionInfo* optionGroupInfo, optionGroupInfo->optionInfos) { + QDomElement option = doc.createElement("option"); + option.setAttribute("name", optionGroupInfo->name); + option.setAttribute("description", optionGroupInfo->description); + optionGroup.appendChild(option); + } + + optionGroupList.appendChild(optionGroup); + } + root.appendChild(optionGroupList); + + QFile file("base2.xml"); + if( ! file.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text) ) { + kWarning() << "Failed to open layout memory xml file for writing" << file.fileName(); + QFAIL("failed"); + } + + QTextStream out(&file); + out << doc.toString(); + } + + void testRulesVersion() { + QVERIFY(!rules->version.isEmpty()); + + Rules* rules10 = new Rules(); + Rules::readRules(rules10, QString("config/base.xml"), false); + QCOMPARE(rules10->version, QString("1.0")); + delete rules10; + + Rules* rules11 = new Rules(); + Rules::readRules(rules11, QString("config/base.1.1.xml"), false); + QCOMPARE(rules11->version, QString("1.1")); + + foreach(const LayoutInfo* layoutInfo, rules11->layoutInfos) { + QVERIFY( layoutInfo != NULL); + QVERIFY( ! layoutInfo->name.isEmpty() ); + QVERIFY( ! layoutInfo->description.isEmpty() ); + + foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { + QVERIFY( variantInfo != NULL ); + QVERIFY( ! variantInfo->name.isEmpty() ); + QVERIFY( ! variantInfo->description.isEmpty() ); + } + } + + delete rules11; + } + + void loadRulesBenchmark() { + QBENCHMARK { + Rules* rules = Rules::readRules(readExtras); + delete rules; + } + } + +}; + +// need kde libs for config-workspace.h used in xkb_rules.cpp +// need GUI for xkb protocol +QTEST_KDEMAIN( RulesTest, GUI ) + +#include "xkb_rules_test.moc" diff --git a/kcms/keyboard/x11_helper.cpp b/kcms/keyboard/x11_helper.cpp new file mode 100644 index 0000000000..84f5592e5d --- /dev/null +++ b/kcms/keyboard/x11_helper.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "x11_helper.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + + +// more information about the limit https://bugs.freedesktop.org/show_bug.cgi?id=19501 +int X11Helper::MAX_GROUP_COUNT = 4; +int X11Helper::ARTIFICIAL_GROUP_LIMIT_COUNT = 8; + +const char* X11Helper::LEFT_VARIANT_STR = "("; +const char* X11Helper::RIGHT_VARIANT_STR = ")"; + +bool X11Helper::xkbSupported(int* xkbOpcode) +{ + // Verify the Xlib has matching XKB extension. + + int major = XkbMajorVersion; + int minor = XkbMinorVersion; + + if (!XkbLibraryVersion(&major, &minor)) + { + kWarning() << "Xlib XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion; + return false; + } + + // Verify the X server has matching XKB extension. + + int opcode_rtrn; + int error_rtrn; + int xkb_opcode; + if( ! XkbQueryExtension(QX11Info::display(), &opcode_rtrn, &xkb_opcode, &error_rtrn, &major, &minor)) { + kWarning() << "X server XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion; + return false; + } + + if( xkbOpcode != NULL ) { + *xkbOpcode = xkb_opcode; + } + + return true; +} + +void X11Helper::switchToNextLayout() +{ + int size = getLayoutsList().size(); //TODO: could optimize a bit as we don't need the layouts - just count + int group = (X11Helper::getGroup() + 1) % size; + X11Helper::setGroup(group); +} + +void X11Helper::scrollLayouts(int delta) +{ + int size = getLayoutsList().size(); //TODO: could optimize a bit as we don't need the layouts - just count + int group = X11Helper::getGroup() + delta; + group = group < 0 ? size - ((-group) % size) : group % size; + + X11Helper::setGroup(group); +} + +QStringList X11Helper::getLayoutsListAsString(const QList& layoutsList) +{ + QStringList stringList; + foreach(const LayoutUnit& layoutUnit, layoutsList) { + stringList << layoutUnit.toString(); + } + return stringList; +} + +bool X11Helper::setLayout(const LayoutUnit& layout) +{ + QList currentLayouts = getLayoutsList(); + int idx = currentLayouts.indexOf(layout); + if( idx == -1 || idx >= X11Helper::MAX_GROUP_COUNT ) { + kWarning() << "Layout" << layout.toString() << "is not found in current layout list" + << getLayoutsListAsString(currentLayouts); + return false; + } + + return X11Helper::setGroup((unsigned int)idx); +} + +bool X11Helper::setDefaultLayout() { + return X11Helper::setGroup(0); +} + +bool X11Helper::isDefaultLayout() { + return X11Helper::getGroup() == 0; +} + +LayoutUnit X11Helper::getCurrentLayout() +{ + QList currentLayouts = getLayoutsList(); + unsigned int group = X11Helper::getGroup(); + if( group < (unsigned int)currentLayouts.size() ) + return currentLayouts[group]; + + kWarning() << "Current group number" << group << "is outside of current layout list" << + getLayoutsListAsString(currentLayouts); + return LayoutUnit(); +} + +LayoutSet X11Helper::getCurrentLayouts() +{ + LayoutSet layoutSet; + + QList currentLayouts = getLayoutsList(); + layoutSet.layouts = currentLayouts; + + unsigned int group = X11Helper::getGroup(); + if( group < (unsigned int)currentLayouts.size() ) { + layoutSet.currentLayout = currentLayouts[group]; + } + else { + kWarning() << "Current group number" << group << "is outside of current layout list" << getLayoutsListAsString(currentLayouts); + layoutSet.currentLayout = LayoutUnit(); + } + + return layoutSet; +} + + +//static QString addNum(const QString& str, int n) +//{ +// QString format("%1%2"); +// if( str.length() >= 3 ) return format.arg(str.left(2)).arg(n); +// return format.arg(str).arg(n); +//} + +QList X11Helper::getLayoutsList() +{ + XkbConfig xkbConfig; + QList layouts; + if( X11Helper::getGroupNames(QX11Info::display(), &xkbConfig, X11Helper::LAYOUTS_ONLY) ) { + for(int i=0; i 0) || (real_prop_type != XA_STRING) || (fmt != 8)) { + if (prop_data) + XFree(prop_data); + kWarning() << "Failed to fetch layouts from server:" << "Wrong property format"; + return false; + } + +// qDebug() << "prop_data:" << nitems << prop_data; + QStringList names; + for(char* p=prop_data; p-prop_data < (long)nitems && p != NULL; p += strlen(p)+1) { + names.append( p ); +// kDebug() << " " << p; + } + + if( names.count() < 4 ) { //{ rules, model, layouts, variants, options } + XFree(prop_data); + return false; + } + + if( fetchType == ALL || fetchType == LAYOUTS_ONLY ) { + QStringList layouts = names[2].split(OPTIONS_SEPARATOR); + QStringList variants = names[3].split(OPTIONS_SEPARATOR); + + for(int ii=0; iilayouts << (layouts[ii] != NULL ? layouts[ii] : ""); + xkbConfig->variants << (ii < variants.count() && variants[ii] != NULL ? variants[ii] : ""); + } + kDebug() << "Fetched layout groups from X server:" + << "\tlayouts:" << xkbConfig->layouts + << "\tvariants:" << xkbConfig->variants; + } + + if( fetchType == ALL || fetchType == MODEL_ONLY ) { + xkbConfig->keyboardModel = (names[1] != NULL ? names[1] : ""); + kDebug() << "Fetched keyboard model from X server:" << xkbConfig->keyboardModel; + } + + if( fetchType == ALL ) { + if( names.count() >= 5 ) { + QString options = (names[4] != NULL ? names[4] : ""); + xkbConfig->options = options.split(OPTIONS_SEPARATOR); + kDebug() << "Fetched xkbOptions from X server:" << options; + } + } + + XFree(prop_data); + return true; +} + +#if 0 +XEventNotifier::XEventNotifier(QWidget* parent): + QWidget(parent), + xkbOpcode(-1) +{ + if( KApplication::kApplication() == NULL ) { + kWarning() << "Layout Widget won't work properly without KApplication instance"; + } +} + +void XEventNotifier::start() +{ + if( KApplication::kApplication() != NULL && X11Helper::xkbSupported(&xkbOpcode) ) { + registerForXkbEvents(QX11Info::display()); + + // start the event loop + KApplication::kApplication()->installX11EventFilter(this); + } +} + +void XEventNotifier::stop() +{ + if( KApplication::kApplication() != NULL ) { + //TODO: unregister + // XEventNotifier::unregisterForXkbEvents(QX11Info::display()); + + // stop the event loop + KApplication::kApplication()->removeX11EventFilter(this); + } +} + +bool XEventNotifier::isXkbEvent(XEvent* event) +{ + return event->type == xkbOpcode; +} + +bool XEventNotifier::processOtherEvents(XEvent* /*event*/) +{ + return true; +} + +bool XEventNotifier::processXkbEvents(XEvent* event) +{ + if( XEventNotifier::isGroupSwitchEvent(event) ) { + emit(layoutChanged()); + } + else if( XEventNotifier::isLayoutSwitchEvent(event) ) { + emit(layoutMapChanged()); + } + return true; +} + +bool XEventNotifier::x11Event(XEvent * event) +{ + // qApp->x11ProcessEvent ( event ); + if( isXkbEvent(event) ) { + processXkbEvents(event); + } + else { + processOtherEvents(event); + } + return QWidget::x11Event(event); +} + +bool XEventNotifier::isGroupSwitchEvent(XEvent* event) +{ + XkbEvent *xkbEvent = (XkbEvent*) event; +#define GROUP_CHANGE_MASK \ + ( XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask ) + + return xkbEvent->any.xkb_type == XkbStateNotify && (xkbEvent->state.changed & GROUP_CHANGE_MASK); +} + +bool XEventNotifier::isLayoutSwitchEvent(XEvent* event) +{ + XkbEvent *xkbEvent = (XkbEvent*) event; + + return //( (xkbEvent->any.xkb_type == XkbMapNotify) && (xkbEvent->map.changed & XkbKeySymsMask) ) || +/* || ( (xkbEvent->any.xkb_type == XkbNamesNotify) && (xkbEvent->names.changed & XkbGroupNamesMask) || )*/ + (xkbEvent->any.xkb_type == XkbNewKeyboardNotify); +} + +int XEventNotifier::registerForXkbEvents(Display* display) +{ + int eventMask = XkbNewKeyboardNotifyMask | XkbStateNotifyMask; + if( ! XkbSelectEvents(display, XkbUseCoreKbd, eventMask, eventMask) ) { + kWarning() << "Couldn't select desired XKB events"; + return false; + } + return true; +} +#endif + + +static const char* LAYOUT_VARIANT_SEPARATOR_PREFIX = "("; +static const char* LAYOUT_VARIANT_SEPARATOR_SUFFIX = ")"; + +static QString& stripVariantName(QString& variant) +{ + if( variant.endsWith(LAYOUT_VARIANT_SEPARATOR_SUFFIX) ) { + int suffixLen = strlen(LAYOUT_VARIANT_SEPARATOR_SUFFIX); + return variant.remove(variant.length()-suffixLen, suffixLen); + } + return variant; +} + +LayoutUnit::LayoutUnit(const QString& fullLayoutName) +{ + QStringList lv = fullLayoutName.split(LAYOUT_VARIANT_SEPARATOR_PREFIX); + layout = lv[0]; + variant = lv.size() > 1 ? stripVariantName(lv[1]) : ""; +} + +QString LayoutUnit::toString() const +{ + if( variant.isEmpty() ) + return layout; + + return layout + LAYOUT_VARIANT_SEPARATOR_PREFIX+variant+LAYOUT_VARIANT_SEPARATOR_SUFFIX; +} + +const int LayoutUnit::MAX_LABEL_LENGTH = 3; diff --git a/kcms/keyboard/x11_helper.h b/kcms/keyboard/x11_helper.h new file mode 100644 index 0000000000..b393e5eff1 --- /dev/null +++ b/kcms/keyboard/x11_helper.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 X11_HELPER_H_ +#define X11_HELPER_H_ + +#include +#include +#include +#include +#include + +#warning XEventNotifier needs porting to QAbstractNativeEventFilter +#if 0 +class XEventNotifier : public QWidget { + Q_OBJECT + +Q_SIGNALS: + void layoutChanged(); + void layoutMapChanged(); + +public: + XEventNotifier(QWidget* parent=NULL); + virtual ~XEventNotifier() {} + + virtual void start(); + virtual void stop(); + +protected: + bool x11Event(XEvent * e); + virtual bool processOtherEvents(XEvent* e); + virtual bool processXkbEvents(XEvent* e); + +private: + int registerForXkbEvents(Display* display); + bool isXkbEvent(XEvent* event); + bool isGroupSwitchEvent(XEvent* event); + bool isLayoutSwitchEvent(XEvent* event); + + int xkbOpcode; +}; +#endif + +struct XkbConfig { + QString keyboardModel; + QStringList layouts; + QStringList variants; + QStringList options; + + bool isValid() { return ! layouts.empty(); } +}; + + +struct LayoutUnit { + static const int MAX_LABEL_LENGTH; + + //TODO: move these to private? + QString layout; + QString variant; + + LayoutUnit() {} + explicit LayoutUnit(const QString& fullLayoutName); + LayoutUnit(const QString& layout_, const QString& variant_) { + layout = layout_; + variant = variant_; + } + /*explicit*/ LayoutUnit(const LayoutUnit& layoutUnit) { + layout = layoutUnit.layout; + variant = layoutUnit.variant; + displayName = layoutUnit.displayName; + shortcut = layoutUnit.shortcut; + } + + QString getRawDisplayName() const { return displayName; } + QString getDisplayName() const { return !displayName.isEmpty() ? displayName : layout; } + void setDisplayName(const QString& name) { displayName = name; } + + void setShortcut(const QKeySequence& shortcut) { this->shortcut = shortcut; } + QKeySequence getShortcut() const { return shortcut; } + + bool isEmpty() const { return layout.isEmpty(); } + bool isValid() const { return ! isEmpty(); } + bool operator==(const LayoutUnit& layoutItem) const { + return layout==layoutItem.layout && variant==layoutItem.variant; + } + bool operator!=(const LayoutUnit& layoutItem) const { + return ! (*this == layoutItem); + } + QString toString() const; + +private: + QString displayName; + QKeySequence shortcut; +}; + +struct LayoutSet { + QList layouts; + LayoutUnit currentLayout; + + LayoutSet() {} + + LayoutSet(const LayoutSet& currentLayouts) { + this->layouts = currentLayouts.layouts; + this->currentLayout = currentLayouts.currentLayout; + } + + bool isValid() const { + return currentLayout.isValid() && layouts.contains(currentLayout); + } + + bool operator == (const LayoutSet& currentLayouts) const { + return this->layouts == currentLayouts.layouts + && this->currentLayout == currentLayouts.currentLayout; + } + + LayoutSet& operator = (const LayoutSet& currentLayouts) { + this->layouts = currentLayouts.layouts; + this->currentLayout = currentLayouts.currentLayout; + return *this; + } + + QString toString() const { + QString str(currentLayout.toString()); + str += ": "; + foreach(const LayoutUnit& layoutUnit, layouts) { + str += layoutUnit.toString() + " "; + } + return str; + } + + static QString toString(const QList& layoutUnits) { + QString str; + foreach(const LayoutUnit& layoutUnit, layoutUnits) { + str += layoutUnit.toString() + ","; + } + return str; + } +}; + +class X11Helper +{ +public: + static int MAX_GROUP_COUNT; + static int ARTIFICIAL_GROUP_LIMIT_COUNT; + + static const char* LEFT_VARIANT_STR; + static const char* RIGHT_VARIANT_STR; + + static bool xkbSupported(int* xkbOpcode); + + static void switchToNextLayout(); + static void scrollLayouts(int delta); + static bool isDefaultLayout(); + static bool setDefaultLayout(); + static bool setLayout(const LayoutUnit& layout); + static LayoutUnit getCurrentLayout(); + static LayoutSet getCurrentLayouts(); + static QList getLayoutsList(); + static QStringList getLayoutsListAsString(const QList& layoutsList); + + enum FetchType { ALL, LAYOUTS_ONLY, MODEL_ONLY }; + static bool getGroupNames(Display* dpy, XkbConfig* xkbConfig, FetchType fetchType); + +private: + static unsigned int getGroup(); + static bool setGroup(unsigned int group); +}; + +#endif /* X11_HELPER_H_ */ diff --git a/kcms/keyboard/xinput_helper.cpp b/kcms/keyboard/xinput_helper.cpp new file mode 100644 index 0000000000..b138855aa0 --- /dev/null +++ b/kcms/keyboard/xinput_helper.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "xinput_helper.h" + +#include +#include + +#include + +#include +#include +#include + +#ifdef HAVE_XINPUT_AND_DEVICE_NOTIFY +#include +#endif + +#include + +#include "x11_helper.h" + +#include + +static int DEVICE_NONE = 0; +static int DEVICE_KEYBOARD = 1; +static int DEVICE_POINTER = 2; + +XInputEventNotifier::XInputEventNotifier(QWidget* parent): + XEventNotifier(parent), + xinputEventType(-1) +{ +} + +void XInputEventNotifier::start() +{ + if( KApplication::kApplication() != NULL ) { + registerForNewDeviceEvent(QX11Info::display()); + } + + XEventNotifier::start(); +} + +void XInputEventNotifier::stop() +{ + XEventNotifier::stop(); + + if( KApplication::kApplication() != NULL ) { + // XEventNotifier::unregisterForNewDeviceEvent(QX11Info::display()); + } +} + +bool XInputEventNotifier::processOtherEvents(XEvent* event) +{ + int newDeviceType = getNewDeviceEventType(event); + if( newDeviceType == DEVICE_KEYBOARD ) { + emit(newKeyboardDevice()); + } + else if( newDeviceType == DEVICE_POINTER ) { + emit(newPointerDevice()); + emit(newKeyboardDevice()); // arghhh, looks like X resets xkb map even when only pointer device is connected + } + return true; +} + + +#ifdef HAVE_XINPUT_AND_DEVICE_NOTIFY + +extern "C" { + extern int _XiGetDevicePresenceNotifyEvent(Display *); +} + +// This is ugly but allows to skip multiple execution of setxkbmap +// for all keyboard devices that don't care about layouts +static bool isRealKeyboard(const char* deviceName) +{ + return strstr(deviceName, "Video Bus") == NULL + && strstr(deviceName, "Sleep Button") == NULL + && strstr(deviceName, "Power Button") == NULL + && strstr(deviceName, "WMI hotkeys") == NULL; +} + +int XInputEventNotifier::getNewDeviceEventType(XEvent* event) +{ + int newDeviceType = DEVICE_NONE; + + if( xinputEventType != -1 && event->type == xinputEventType ) { + XDevicePresenceNotifyEvent *xdpne = (XDevicePresenceNotifyEvent*) event; + if( xdpne->devchange == DeviceEnabled ) { + int ndevices; + XDeviceInfo *devices = XListInputDevices(xdpne->display, &ndevices); + if( devices != NULL ) { +// kDebug() << "New device id:" << xdpne->deviceid; + for(int i=0; ideviceid ) { + if( devices[i].use == IsXKeyboard || devices[i].use == IsXExtensionKeyboard ) { + if( isRealKeyboard(devices[i].name) ) { + newDeviceType = DEVICE_KEYBOARD; + kDebug() << "new keyboard device, id:" << devices[i].id << "name:" << devices[i].name << "used as:" << devices[i].use; + break; + } + } + if( devices[i].use == IsXPointer || devices[i].use == IsXExtensionPointer ) { + newDeviceType = DEVICE_POINTER; + kDebug() << "new pointer device, id:" << devices[i].id << "name:" << devices[i].name << "used as:" << devices[i].use; + break; + } + } + } + XFreeDeviceList(devices); + } + } + } + return newDeviceType; +} + +int XInputEventNotifier::registerForNewDeviceEvent(Display* display) +{ + int xitype; + XEventClass xiclass; + + DevicePresence(display, xitype, xiclass); + XSelectExtensionEvent(display, DefaultRootWindow(display), &xiclass, 1); + kDebug() << "Registered for new device events from XInput, class" << xitype; + xinputEventType = xitype; + return xitype; +} + +#else + +#ifdef __GNUC__ +#warning "Keyboard daemon is compiled without XInput, keyboard settings will be reset when new keyboard device is plugged in!" +#endif + +int XInputEventNotifier::registerForNewDeviceEvent(Display* /*display*/) +{ + kWarning() << "Keyboard kded daemon is compiled without XInput, xkb configuration will be reset when new keyboard device is plugged in!"; + return -1; +} + +int XInputEventNotifier::getNewDeviceEventType(XEvent* /*event*/) +{ + return DEVICE_NONE; +} + +#endif diff --git a/kcms/keyboard/xinput_helper.h b/kcms/keyboard/xinput_helper.h new file mode 100644 index 0000000000..92f1eb65b2 --- /dev/null +++ b/kcms/keyboard/xinput_helper.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 XINPUT_HELPER_H_ +#define XINPUT_HELPER_H_ + +#include "x11_helper.h" + + +class XInputEventNotifier: public XEventNotifier { + Q_OBJECT + +public: + XInputEventNotifier(QWidget* parent=NULL); + + void start(); + void stop(); + + int registerForNewDeviceEvent(Display* dpy); + +Q_SIGNALS: + void newKeyboardDevice(); + void newPointerDevice(); + +protected: + bool processOtherEvents(XEvent* event); + +private: + int getNewDeviceEventType(XEvent* event); + + int xinputEventType; +}; + +#endif /* XINPUT_HELPER_H_ */ diff --git a/kcms/keyboard/xkb_helper.cpp b/kcms/keyboard/xkb_helper.cpp new file mode 100644 index 0000000000..10969878a6 --- /dev/null +++ b/kcms/keyboard/xkb_helper.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "xkb_helper.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "keyboard_config.h" + + +static const char* SETXKBMAP_EXEC = "setxkbmap"; +static const char* XMODMAP_EXEC = "xmodmap"; + +static bool setxkbmapNotFound = false; +static QString setxkbmapExe; + +static bool xmodmapNotFound = false; +static QString xmodmapExe; + +static const QString COMMAND_OPTIONS_SEPARATOR(","); + +static +QString getSetxkbmapExe() +{ + if( setxkbmapNotFound ) + return ""; + + if( setxkbmapExe.isEmpty() ) { + setxkbmapExe = KGlobal::dirs()->findExe(SETXKBMAP_EXEC); + if( setxkbmapExe.isEmpty() ) { + setxkbmapNotFound = true; + kError() << "Can't find" << SETXKBMAP_EXEC << "- keyboard layouts won't be configured"; + return ""; + } + } + return setxkbmapExe; +} + +static +void executeXmodmap(const QString& configFileName) +{ + if( xmodmapNotFound ) + return; + + if( QFile(configFileName).exists() ) { + if( xmodmapExe.isEmpty() ) { + xmodmapExe = KGlobal::dirs()->findExe(XMODMAP_EXEC); + if( xmodmapExe.isEmpty() ) { + xmodmapNotFound = true; + kError() << "Can't find" << XMODMAP_EXEC << "- xmodmap files won't be run"; + return; + } + } + + KProcess xmodmapProcess; + xmodmapProcess << xmodmapExe; + xmodmapProcess << configFileName; + kDebug() << "Executing" << xmodmapProcess.program().join(" "); + if( xmodmapProcess.execute() != 0 ) { + kError() << "Failed to execute " << xmodmapProcess.program(); + } + } +} + +static +void restoreXmodmap() +{ + // TODO: is just home .Xmodmap enough or should system be involved too? + // QString configFileName = QDir("/etc/X11/xinit").filePath(".Xmodmap"); + // executeXmodmap(configFileName); + QString configFileName = QDir::home().filePath(".Xmodmap"); + executeXmodmap(configFileName); +} + +//TODO: make private +bool XkbHelper::runConfigLayoutCommand(const QStringList& setxkbmapCommandArguments) +{ + QTime timer; + timer.start(); + + KProcess setxkbmapProcess; + setxkbmapProcess << getSetxkbmapExe() << setxkbmapCommandArguments; + int res = setxkbmapProcess.execute(); + + if( res == 0 ) { // restore Xmodmap mapping reset by setxkbmap + kDebug() << "Executed successfully in " << timer.elapsed() << "ms" << setxkbmapProcess.program().join(" "); + restoreXmodmap(); + kDebug() << "\t and with xmodmap" << timer.elapsed() << "ms"; + return true; + } + else { + kError() << "Failed to run" << setxkbmapProcess.program().join(" ") << "return code:" << res; + } + return false; +} + +bool XkbHelper::initializeKeyboardLayouts(const QList& layoutUnits) +{ + QStringList layouts; + QStringList variants; + foreach (const LayoutUnit& layoutUnit, layoutUnits) { + layouts.append(layoutUnit.layout); + variants.append(layoutUnit.variant); + } + + QStringList setxkbmapCommandArguments; + setxkbmapCommandArguments.append("-layout"); + setxkbmapCommandArguments.append(layouts.join(COMMAND_OPTIONS_SEPARATOR)); + if( ! variants.join("").isEmpty() ) { + setxkbmapCommandArguments.append("-variant"); + setxkbmapCommandArguments.append(variants.join(COMMAND_OPTIONS_SEPARATOR)); + } + + return runConfigLayoutCommand(setxkbmapCommandArguments); +} + +bool XkbHelper::initializeKeyboardLayouts(KeyboardConfig& config) +{ + QStringList setxkbmapCommandArguments; + if( ! config.keyboardModel.isEmpty() ) { + XkbConfig xkbConfig; + X11Helper::getGroupNames(QX11Info::display(), &xkbConfig, X11Helper::MODEL_ONLY); + if( xkbConfig.keyboardModel != config.keyboardModel ) { + setxkbmapCommandArguments.append("-model"); + setxkbmapCommandArguments.append(config.keyboardModel); + } + } + if( config.configureLayouts ) { + QStringList layouts; + QStringList variants; + QList defaultLayouts = config.getDefaultLayouts(); + foreach (const LayoutUnit& layoutUnit, defaultLayouts) { + layouts.append(layoutUnit.layout); + variants.append(layoutUnit.variant); + } + + setxkbmapCommandArguments.append("-layout"); + setxkbmapCommandArguments.append(layouts.join(COMMAND_OPTIONS_SEPARATOR)); + if( ! variants.join("").isEmpty() ) { + setxkbmapCommandArguments.append("-variant"); + setxkbmapCommandArguments.append(variants.join(COMMAND_OPTIONS_SEPARATOR)); + } + } + if( config.resetOldXkbOptions ) { + setxkbmapCommandArguments.append("-option"); + } + if( ! config.xkbOptions.isEmpty() ) { + setxkbmapCommandArguments.append("-option"); + setxkbmapCommandArguments.append(config.xkbOptions.join(COMMAND_OPTIONS_SEPARATOR)); + } + + if( ! setxkbmapCommandArguments.isEmpty() ) { + return runConfigLayoutCommand(setxkbmapCommandArguments); + if( config.configureLayouts ) { + X11Helper::setDefaultLayout(); + } + } + return false; +} diff --git a/kcms/keyboard/xkb_helper.h b/kcms/keyboard/xkb_helper.h new file mode 100644 index 0000000000..5e4f94d2c3 --- /dev/null +++ b/kcms/keyboard/xkb_helper.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 XKB_HELPER_H_ +#define XKB_HELPER_H_ + +template class QList; +class LayoutUnit; +class QStringList; +class KeyboardConfig; + +class XkbHelper { +public: + static bool initializeKeyboardLayouts(KeyboardConfig& config); + static bool initializeKeyboardLayouts(const QList& layouts); + static bool runConfigLayoutCommand(const QStringList& setxkbmapCommandArguments); +}; + +#endif /* XKB_HELPER_H_ */ diff --git a/kcms/keyboard/xkb_rules.cpp b/kcms/keyboard/xkb_rules.cpp new file mode 100644 index 0000000000..a1840f898f --- /dev/null +++ b/kcms/keyboard/xkb_rules.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 "xkb_rules.h" +#include "config-workspace.h" + +#include +#include +#include + +#include +#include +#include // for Qt::escape +#include +#include + +//#include +//#include + +#include "x11_helper.h" + +// for findXkbRuleFile +#include +#include +#include +#include +#include +#include +#include + + +class RulesHandler : public QXmlDefaultHandler +{ +public: + RulesHandler(Rules* rules_, bool fromExtras_): + rules(rules_), + fromExtras(fromExtras_){} + + bool startElement(const QString &namespaceURI, const QString &localName, + const QString &qName, const QXmlAttributes &attributes); + bool endElement(const QString &namespaceURI, const QString &localName, + const QString &qName); + bool characters(const QString &str); +// bool fatalError(const QXmlParseException &exception); +// QString errorString() const; + +private: +// QString getString(const QString& text); + + QStringList path; + Rules* rules; + const bool fromExtras; +}; + +static QString translate_xml_item(const QString& itemText) +{ + return i18n(Qt::escape(itemText).toUtf8()); + // return QString::fromUtf8(dgettext("xkeyboard-config", itemText.toAscii())); +} + +static QString translate_description(ConfigItem* item) +{ + return item->description.isEmpty() + ? item->name : translate_xml_item(item->description); +} + +static bool notEmpty(const ConfigItem* item) +{ + return ! item->name.isEmpty(); +} + +template +void removeEmptyItems(QList& list) +{ +#ifdef __GNUC__ +#if __GNUC__ == 4 && (__GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ < 3) || (__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ < 4) +#warning Compiling with a workaround for GCC < 4.8.3 || GCC < 4.7.4 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800 + Q_FOREACH(T* x, list) { + ConfigItem *y = static_cast(x); + if (y->name.isEmpty()) { + list.removeAll(x); + } + } +#else + QtConcurrent::blockingFilter(list, notEmpty); +#endif +#endif +} + +static +void postProcess(Rules* rules) +{ + //TODO remove elements with empty names to safeguard us + removeEmptyItems(rules->layoutInfos); + removeEmptyItems(rules->modelInfos); + removeEmptyItems(rules->optionGroupInfos); + +// setlocale(LC_ALL, ""); +// bindtextdomain("xkeyboard-config", LOCALE_DIR); + foreach(ModelInfo* modelInfo, rules->modelInfos) { + modelInfo->vendor = translate_xml_item(modelInfo->vendor); + modelInfo->description = translate_description(modelInfo); + } + + foreach(LayoutInfo* layoutInfo, rules->layoutInfos) { + layoutInfo->description = translate_description(layoutInfo); + + removeEmptyItems(layoutInfo->variantInfos); + foreach(VariantInfo* variantInfo, layoutInfo->variantInfos) { + variantInfo->description = translate_description(variantInfo); + } + } + foreach(OptionGroupInfo* optionGroupInfo, rules->optionGroupInfos) { + optionGroupInfo->description = translate_description(optionGroupInfo); + + removeEmptyItems(optionGroupInfo->optionInfos); + foreach(OptionInfo* optionInfo, optionGroupInfo->optionInfos) { + optionInfo->description = translate_description(optionInfo); + } + } +} + + +Rules::Rules(): + version("1.0") +{ +} + +QString Rules::getRulesName() +{ + XkbRF_VarDefsRec vd; + char *tmp = NULL; + + if (XkbRF_GetNamesProp(QX11Info::display(), &tmp, &vd) && tmp != NULL ) { + // qDebug() << "namesprop" << tmp ; + const QString name(tmp); + XFree(tmp); + return name; + } + + return QString::null; +} + +static QString findXkbRulesFile() +{ + QString rulesFile; + QString rulesName = Rules::getRulesName(); + + if ( ! rulesName.isNull() ) { + QString xkbParentDir; + + QString base(XLIBDIR); + if( base.count('/') >= 3 ) { + // .../usr/lib/X11 -> /usr/share/X11/xkb vs .../usr/X11/lib -> /usr/X11/share/X11/xkb + QString delta = base.endsWith("X11") ? "/../../share/X11" : "/../share/X11"; + QDir baseDir(base + delta); + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + else { + QDir baseDir(base + "/X11"); // .../usr/X11/lib/X11/xkb (old XFree) + if( baseDir.exists() ) { + xkbParentDir = baseDir.absolutePath(); + } + } + } + + if( xkbParentDir.isEmpty() ) { + xkbParentDir = "/usr/share/X11"; + } + + rulesFile = QString("%1/xkb/rules/%2.xml").arg(xkbParentDir, rulesName); + } + + return rulesFile; +} + +static +void mergeRules(Rules* rules, Rules* extraRules) +{ + rules->modelInfos.append( extraRules->modelInfos ); + rules->optionGroupInfos.append( extraRules->optionGroupInfos ); // need to iterate and merge? + + QList layoutsToAdd; + foreach(LayoutInfo* extraLayoutInfo, extraRules->layoutInfos) { + LayoutInfo* layoutInfo = findByName(rules->layoutInfos, extraLayoutInfo->name); + if( layoutInfo != NULL ) { + layoutInfo->variantInfos.append( extraLayoutInfo->variantInfos ); + layoutInfo->languages.append( extraLayoutInfo->languages ); + } + else { + layoutsToAdd.append(extraLayoutInfo); + } + } + rules->layoutInfos.append(layoutsToAdd); + kDebug() << "Merged from extra rules:" << extraRules->layoutInfos.size() << "layouts," << extraRules->modelInfos.size() << "models," << extraRules->optionGroupInfos.size() << "option groups"; + + // base rules now own the objects - remove them from extra rules so that it does not try to delete them + extraRules->layoutInfos.clear(); + extraRules->modelInfos.clear(); + extraRules->optionGroupInfos.clear(); +} + + +const char Rules::XKB_OPTION_GROUP_SEPARATOR = ':'; + +Rules* Rules::readRules(ExtrasFlag extrasFlag) +{ + Rules* rules = new Rules(); + QString rulesFile = findXkbRulesFile(); + if( ! readRules(rules, rulesFile, false) ) { + delete rules; + return NULL; + } + if( extrasFlag == Rules::READ_EXTRAS ) { + QRegExp regex("\\.xml$"); + Rules* rulesExtra = new Rules(); + QString extraRulesFile = rulesFile.replace(regex, ".extras.xml"); + if( readRules(rulesExtra, extraRulesFile, true) ) { // not fatal if it fails + mergeRules(rules, rulesExtra); + } + delete rulesExtra; + } + return rules; +} + + +Rules* Rules::readRules(Rules* rules, const QString& filename, bool fromExtras) +{ + QFile file(filename); + if( !file.open(QFile::ReadOnly | QFile::Text) ) { + kError() << "Cannot open the rules file" << file.fileName(); + return NULL; + } + + RulesHandler rulesHandler(rules, fromExtras); + + QXmlSimpleReader reader; + reader.setContentHandler(&rulesHandler); + reader.setErrorHandler(&rulesHandler); + + QXmlInputSource xmlInputSource(&file); + + kDebug() << "Parsing xkb rules from" << file.fileName(); + + if( ! reader.parse(xmlInputSource) ) { + kError() << "Failed to parse the rules file" << file.fileName(); + delete rules; + return NULL; + } + + postProcess(rules); + + return rules; +} + +bool RulesHandler::startElement(const QString &/*namespaceURI*/, const QString &/*localName*/, + const QString &qName, const QXmlAttributes &attributes) +{ + path << QString(qName); + + QString strPath = path.join("/"); + if( strPath.endsWith("layoutList/layout/configItem") ) { + rules->layoutInfos << new LayoutInfo(fromExtras); + } + else if( strPath.endsWith("layoutList/layout/variantList/variant") ) { + rules->layoutInfos.last()->variantInfos << new VariantInfo(fromExtras); + } + else if( strPath.endsWith("modelList/model") ) { + rules->modelInfos << new ModelInfo(); + } + else if( strPath.endsWith("optionList/group") ) { + rules->optionGroupInfos << new OptionGroupInfo(); + rules->optionGroupInfos.last()->exclusive = (attributes.value("allowMultipleSelection") != "true"); + } + else if( strPath.endsWith("optionList/group/option") ) { + rules->optionGroupInfos.last()->optionInfos << new OptionInfo(); + } + else if( strPath == ("xkbConfigRegistry") && ! attributes.value("version").isEmpty() ) { + rules->version = attributes.value("version"); + kDebug() << "xkbConfigRegistry version" << rules->version; + } + return true; +} + +bool RulesHandler::endElement(const QString &/*namespaceURI*/, const QString &/*localName*/, const QString &/*qName*/) +{ + path.removeLast(); + return true; +} + +bool RulesHandler::characters(const QString &str) +{ + if( !str.trimmed().isEmpty() ) { + QString strPath = path.join("/"); + if( strPath.endsWith("layoutList/layout/configItem/name") ) { + if( rules->layoutInfos.last() != NULL ) { + rules->layoutInfos.last()->name = str.trimmed(); +// qDebug() << "name:" << str; + } + // skipping invalid entry + } + else if( strPath.endsWith("layoutList/layout/configItem/description") ) { + rules->layoutInfos.last()->description = str.trimmed(); +// qDebug() << "descr:" << str; + } + else if( strPath.endsWith("layoutList/layout/configItem/languageList/iso639Id") ) { + rules->layoutInfos.last()->languages << str.trimmed(); +// qDebug() << "\tlang:" << str; + } + else if( strPath.endsWith("layoutList/layout/variantList/variant/configItem/name") ) { + rules->layoutInfos.last()->variantInfos.last()->name = str.trimmed(); +// qDebug() << "\tvariant name:" << str; + } + else if( strPath.endsWith("layoutList/layout/variantList/variant/configItem/description") ) { + rules->layoutInfos.last()->variantInfos.last()->description = str.trimmed(); +// qDebug() << "\tvariant descr:" << str; + } + else if( strPath.endsWith("layoutList/layout/variantList/variant/configItem/languageList/iso639Id") ) { + rules->layoutInfos.last()->variantInfos.last()->languages << str.trimmed(); +// qDebug() << "\tvlang:" << str; + } + else if( strPath.endsWith("modelList/model/configItem/name") ) { + rules->modelInfos.last()->name = str.trimmed(); +// qDebug() << "name:" << str; + } + else if( strPath.endsWith("modelList/model/configItem/description") ) { + rules->modelInfos.last()->description = str.trimmed(); +// qDebug() << "\tdescr:" << str; + } + else if( strPath.endsWith("modelList/model/configItem/vendor") ) { + rules->modelInfos.last()->vendor = str.trimmed(); +// qDebug() << "\tvendor:" << str; + } + else if( strPath.endsWith("optionList/group/configItem/name") ) { + rules->optionGroupInfos.last()->name = str.trimmed(); +// qDebug() << "name:" << str; + } + else if( strPath.endsWith("optionList/group/configItem/description") ) { + rules->optionGroupInfos.last()->description = str.trimmed(); +// qDebug() << "\tdescr:" << str; + } + else if( strPath.endsWith("optionList/group/option/configItem/name") ) { + rules->optionGroupInfos.last()->optionInfos.last()->name = str.trimmed(); +// qDebug() << "name:" << str; + } + else if( strPath.endsWith("optionList/group/option/configItem/description") ) { + rules->optionGroupInfos.last()->optionInfos.last()->description = str.trimmed(); +// qDebug() << "\tdescr:" << str; + } + } + return true; +} + +bool LayoutInfo::isLanguageSupportedByLayout(const QString& lang) const +{ + if( languages.contains(lang) || isLanguageSupportedByVariants(lang) ) + return true; + +// // return yes if no languages found in layout or its variants +// if( languages.empty() ) { +// foreach(const VariantInfo* info, variantInfos) { +// if( ! info->languages.empty() ) +// return false; +// } +// return true; +// } + + return false; +} + +bool LayoutInfo::isLanguageSupportedByVariants(const QString& lang) const +{ + foreach(const VariantInfo* info, variantInfos) { + if( info->languages.contains(lang) ) + return true; + } + return false; +} + +bool LayoutInfo::isLanguageSupportedByDefaultVariant(const QString& lang) const +{ + if( languages.contains(lang) ) + return true; + + if( languages.empty() && isLanguageSupportedByVariants(lang) ) + return true; + + return false; +} + +bool LayoutInfo::isLanguageSupportedByVariant(const VariantInfo* variantInfo, const QString& lang) const +{ + if( variantInfo->languages.contains(lang) ) + return true; + + // if variant has no languages try to "inherit" them from layout + if( variantInfo->languages.empty() && languages.contains(lang) ) + return true; + + return false; +} diff --git a/kcms/keyboard/xkb_rules.h b/kcms/keyboard/xkb_rules.h new file mode 100644 index 0000000000..2be856246c --- /dev/null +++ b/kcms/keyboard/xkb_rules.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2010 Andriy Rysin (rysin@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 XKB_RULES_H_ +#define XKB_RULES_H_ + +#include +#include +#include + + +struct ConfigItem { + QString name; + QString description; +}; + +template +inline T* findByName(QList list, QString name) { + foreach(T* info, list) { + if( info->name == name ) + return info; + } + return NULL; +} + +struct VariantInfo: public ConfigItem { + QList languages; + const bool fromExtras; + + VariantInfo(bool fromExtras_): + fromExtras(fromExtras_) {} +}; + +struct LayoutInfo: public ConfigItem { + QList variantInfos; + QList languages; + const bool fromExtras; + +// LayoutInfo() {} + LayoutInfo(bool fromExtras_): + fromExtras(fromExtras_) {} + ~LayoutInfo() { foreach(VariantInfo* variantInfo, variantInfos) delete variantInfo; } + + VariantInfo* getVariantInfo(const QString& variantName) const { + return findByName(variantInfos, variantName); + } + + bool isLanguageSupportedByLayout(const QString& lang) const; + bool isLanguageSupportedByDefaultVariant(const QString& lang) const; + bool isLanguageSupportedByVariants(const QString& lang) const; + bool isLanguageSupportedByVariant(const VariantInfo* variantInfo, const QString& lang) const; +}; + +struct ModelInfo: public ConfigItem { + QString vendor; +}; + +struct OptionInfo: public ConfigItem { +}; + +struct OptionGroupInfo: public ConfigItem { + QList optionInfos; + bool exclusive; + + ~OptionGroupInfo() { foreach(OptionInfo* opt, optionInfos) delete opt; } + + const OptionInfo* getOptionInfo(const QString& optionName) const { + return findByName(optionInfos, optionName); + } +}; + +struct Rules { + enum ExtrasFlag { NO_EXTRAS, READ_EXTRAS }; + + static const char XKB_OPTION_GROUP_SEPARATOR; + + QList layoutInfos; + QList modelInfos; + QList optionGroupInfos; + QString version; + + Rules(); + + ~Rules() { + foreach(LayoutInfo* layoutInfo, layoutInfos) delete layoutInfo; + foreach(ModelInfo* modelInfo, modelInfos) delete modelInfo; + foreach(OptionGroupInfo* optionGroupInfo, optionGroupInfos) delete optionGroupInfo; + } + + const LayoutInfo* getLayoutInfo(const QString& layoutName) const { + return findByName(layoutInfos, layoutName); + } + + const OptionGroupInfo* getOptionGroupInfo(const QString& optionGroupName) const { + return findByName(optionGroupInfos, optionGroupName); + } + + static Rules* readRules(ExtrasFlag extrasFlag); + static Rules* readRules(Rules* rules, const QString& filename, bool fromExtras); + static QString getRulesName(); +}; + +#endif /* XKB_RULES_H_ */ diff --git a/kcms/keys/CMakeLists.txt b/kcms/keys/CMakeLists.txt new file mode 100644 index 0000000000..f9c4d6dead --- /dev/null +++ b/kcms/keys/CMakeLists.txt @@ -0,0 +1,53 @@ +########### next target ############### + +set(kcm_keys_PART_SRCS + kglobalshortcutseditor.cpp + globalshortcuts.cpp + select_scheme_dialog.cpp + kglobalaccel_interface.cpp + kglobalaccel_component_interface.cpp + export_scheme_dialog.cpp + ) + +qt5_wrap_ui( kcm_keys_PART_SRCS + export_scheme_dialog.ui + kglobalshortcutseditor.ui + select_scheme_dialog.ui ) + +set(kglobalaccel_xml ${KGLOBALACCEL_DBUS_INTERFACES_DIR}/kf5_org.kde.KGlobalAccel.xml) +set_source_files_properties(${kglobalaccel_xml} PROPERTIES INCLUDE "kglobalshortcutinfo.h") +qt5_add_dbus_interface(kdeui_LIB_SRCS ${kglobalaccel_xml} kglobalaccel_interface ) + +set(kglobalaccel_component_xml ${KGLOBALACCEL_DBUS_INTERFACES_DIR}/kf5_org.kde.kglobalaccel.Component.xml) +set_source_files_properties(${kglobalaccel_component_xml} PROPERTIES INCLUDE "kglobalshortcutinfo.h") +qt5_add_dbus_interface(kdeui_LIB_SRCS ${kglobalaccel_component_xml} kglobalaccel_component_interface ) + +add_library(kcm_keys MODULE ${kcm_keys_PART_SRCS}) +target_link_libraries(kcm_keys + Qt5::DBus + KF5::KCMUtils + KF5::GlobalAccel + KF5::I18n + KF5::IconThemes + KF5::KIOWidgets + KF5::XmlGui + KF5::KDE4Support +) + +install(TARGETS kcm_keys DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES keys.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES + schemes/kde3.kksrc + schemes/kde4.kksrc + schemes/mac4.kksrc + schemes/unix3.kksrc + schemes/win3.kksrc + schemes/win4.kksrc + schemes/wm3.kksrc + DESTINATION ${DATA_INSTALL_DIR}/kcmkeys ) + + diff --git a/kcms/keys/ChangeLog b/kcms/keys/ChangeLog new file mode 100644 index 0000000000..67c21160db --- /dev/null +++ b/kcms/keys/ChangeLog @@ -0,0 +1,29 @@ +2005-09-30 Benjamin Meyer + * Removed Command Shortcuts, it is already in kmenuedit + +1999-08-19 Duncan Haldane + * removed left-over commented out code from change + decribed below, and adjusted help doc names to + index-1.html + +1999-02-28 Duncan Haldane + * commented out those unnecessary debug calls. + in keyconfig.cpp + +1998-12-19 Duncan Haldane + * Converted global.cpp, global.h to keyconfig.cpp, + keyconfig.h, that can now be used to configure both + the standard keys and the global keys + in the same sophisticated manner as + global.cpp did for just the global keys. + * converted main.cpp to use keyconfig.cpp rather than + global.cpp and standard.cpp for standard and globall + key configuration. KGlobalConfig and KStdConfig disappear. + (KGlobalConfig is renamed to KKeyConfig) + * appropriate changes to Makefile.am. + * standard key binding are now #include'd from + stdbindings.cpp + * standard.cpp, standard.h are left here for now. + The entries that used to use them in main.cpp and + Makefile.am are just commented out for now. + diff --git a/kcms/keys/Messages.sh b/kcms/keys/Messages.sh new file mode 100644 index 0000000000..78a9c48f26 --- /dev/null +++ b/kcms/keys/Messages.sh @@ -0,0 +1,7 @@ +#! /usr/bin/env bash +# customkeys=`grep "^.include .\.\." keyconfig.cpp | sed -e "s#.*\"\(.*\)\"#\1#"` +# $XGETTEXT *.cpp $customkeys -o $podir/kcmkeys.pot +$EXTRACTRC *.ui >> rc.cpp +$XGETTEXT *.cpp -o $podir/kcmkeys.pot +rm -f rc.cpp + diff --git a/kcms/keys/README b/kcms/keys/README new file mode 100644 index 0000000000..14e09f73ea --- /dev/null +++ b/kcms/keys/README @@ -0,0 +1,7 @@ +CHANGES V0.2 +- Global keys stored by default in ~/.kde/share/config/kdeglobals + [Global Keys] group +- KKeyDialog checks new key choices against exising bindings for the widget +and against entries in .kderc [Global Keys] +- kcmkeys now has two standard kcontrol pages - one for standard desktop +accelerators and one for global keybindings. diff --git a/kcms/keys/export_scheme_dialog.cpp b/kcms/keys/export_scheme_dialog.cpp new file mode 100644 index 0000000000..b43fbce65b --- /dev/null +++ b/kcms/keys/export_scheme_dialog.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2009 Michael Jansen + * + * 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 "export_scheme_dialog.h" + +#include +#include + + +ExportSchemeDialog::ExportSchemeDialog(QStringList components, QWidget *parent) + : KDialog(parent), + ui(), + mComponents(components) + { + QWidget *w = new QWidget(this); + ui.setupUi(w); + setMainWidget(w); + + // We allow to check more than one button + mButtons.setExclusive(false); + + // A grid layout for the buttons + QGridLayout *vb = new QGridLayout(this); + + int item=0; + Q_FOREACH(QString component, mComponents) + { + QCheckBox *cb = new QCheckBox(component); + vb->addWidget(cb, item / 2, item % 2); + mButtons.addButton(cb, item); + ++item; + } + + ui.components->setLayout(vb); + } + + +ExportSchemeDialog::~ExportSchemeDialog() + {} + + +QStringList ExportSchemeDialog::selectedComponents() const + { + QStringList rc; + Q_FOREACH(QAbstractButton const *button, mButtons.buttons()) + { + if (button->isChecked()) + { + // Remove the '&' added by KAcceleratorManager magically + rc.append(KLocalizedString::removeAcceleratorMarker(button->text())); + } + } + return rc; + } + + +#include "moc_export_scheme_dialog.cpp" diff --git a/kcms/keys/export_scheme_dialog.h b/kcms/keys/export_scheme_dialog.h new file mode 100644 index 0000000000..8cc8c66342 --- /dev/null +++ b/kcms/keys/export_scheme_dialog.h @@ -0,0 +1,59 @@ +#ifndef EXPORT_SCHEME_DIALOG_H +#define EXPORT_SCHEME_DIALOG_H +/** + * Copyright (C) 2009 Michael Jansen + * + * 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 "ui_export_scheme_dialog.h" + +#include +#include + +/** + * @author Michael Jansen + */ +class ExportSchemeDialog : public KDialog + { + Q_OBJECT + +public: + + ExportSchemeDialog (QStringList components, QWidget *parent=NULL); + + virtual ~ExportSchemeDialog(); + + // Get the list of currently selected components + QStringList selectedComponents() const; + +private: + + Ui::ExportSchemeDialog ui; + + // list of components to choose from + QStringList mComponents; + + // list of buttons for the components + QButtonGroup mButtons; + + }; // ExportSchemeDialog + + + + +#endif /* EXPORT_SCHEME_DIALOG_H */ + diff --git a/kcms/keys/export_scheme_dialog.ui b/kcms/keys/export_scheme_dialog.ui new file mode 100644 index 0000000000..4e8651ee60 --- /dev/null +++ b/kcms/keys/export_scheme_dialog.ui @@ -0,0 +1,35 @@ + + + ExportSchemeDialog + + + + 0 + 0 + 400 + 300 + + + + + + + Select the Components to Export + + + Qt::AlignCenter + + + + + + + Components + + + + + + + + diff --git a/kcms/keys/globalshortcuts.cpp b/kcms/keys/globalshortcuts.cpp new file mode 100644 index 0000000000..89e671848d --- /dev/null +++ b/kcms/keys/globalshortcuts.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2007 Andreas Pakulat + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "globalshortcuts.h" + +#include "kglobalshortcutseditor.h" + +#include +#include +#include + + +#include + + +K_PLUGIN_FACTORY(GlobalShortcutsModuleFactory, registerPlugin();) +K_EXPORT_PLUGIN(GlobalShortcutsModuleFactory("kcmkeys")) + + +GlobalShortcutsModule::GlobalShortcutsModule(QWidget *parent, const QVariantList &args) + : KCModule(parent, args), + editor(0) +{ + KCModule::setButtons(KCModule::Buttons(KCModule::Default | KCModule::Apply | KCModule::Help)); + + + // Create the kglobaleditor + editor = new KGlobalShortcutsEditor(this, KShortcutsEditor::GlobalAction); + connect(editor, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); + + // Layout the hole bunch + QVBoxLayout *global = new QVBoxLayout; + global->addWidget(editor); + setLayout(global); +} + +GlobalShortcutsModule::~GlobalShortcutsModule() +{} + + +void GlobalShortcutsModule::load() +{ + editor->load(); +} + + +void GlobalShortcutsModule::defaults() +{ + switch (KMessageBox::questionYesNoCancel( + this, + i18n("You are about to reset all shortcuts to their default values."), + i18n("Reset to defaults"), + KGuiItem(i18n("Current Component")), + KGuiItem(i18n("All Components")))) + { + case KMessageBox::Yes: + editor->defaults(KGlobalShortcutsEditor::CurrentComponent); + break; + + case KMessageBox::No: + editor->defaults(KGlobalShortcutsEditor::AllComponents); + break; + + default: + return; + } +} + + +void GlobalShortcutsModule::save() +{ + editor->save(); +} + + +#include "globalshortcuts.moc" diff --git a/kcms/keys/globalshortcuts.h b/kcms/keys/globalshortcuts.h new file mode 100644 index 0000000000..428c0335d3 --- /dev/null +++ b/kcms/keys/globalshortcuts.h @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Andreas Pakulat + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 SHORTCUTS_MODULE_H +#define SHORTCUTS_MODULE_H + +#include +#include + +class KGlobalShortcutsEditor; + +class GlobalShortcutsModule : public KCModule +{ + Q_OBJECT +public: + GlobalShortcutsModule(QWidget *parent, const QVariantList &args); + ~GlobalShortcutsModule(); + + virtual void save(); + virtual void load(); + virtual void defaults(); + +private: + KGlobalShortcutsEditor *editor; +}; + + +#endif diff --git a/kcms/keys/keys.desktop b/kcms/keys/keys.desktop new file mode 100644 index 0000000000..76d1b622f4 --- /dev/null +++ b/kcms/keys/keys.desktop @@ -0,0 +1,229 @@ +[Desktop Entry] +Exec=kcmshell5 keys +Icon=preferences-desktop-keyboard-shortcut +Type=Service +X-KDE-ServiceTypes=KCModule +X-DocPath=kcontrol/keys/index.html + +X-KDE-Library=kcm_keys +X-KDE-ParentApp=kcontrol + +X-KDE-System-Settings-Parent-Category=shortcuts-and-gestures +X-KDE-Weight=160 + +Name=Global Keyboard Shortcuts +Name[ar]=اختصارات لوحة المفاتيح العمومية +Name[ast]=Accesos rápidos de tecláu globales +Name[be@latin]=Paŭsiudnyja klavijaturnyja skaroty +Name[bg]=Общи бързи клавиши +Name[bn]=গ্লোবাল কীবোর্ড শর্টকাট +Name[bn_IN]=কি-বোর্ডের সার্বজনীন শর্ট-কাট +Name[bs]=Globalne prečice sa tastature +Name[ca]=Dreceres de teclat globals +Name[ca@valencia]=Dreceres de teclat globals +Name[cs]=Globální klávesové zkratky +Name[csb]=Globalné klawiszowé skrodzënë +Name[da]=Globale tastaturgenveje +Name[de]=Globale Kurzbefehle +Name[el]=Καθολικές συντομεύσεις πληκτρολογίου +Name[en_GB]=Global Keyboard Shortcuts +Name[eo]=Ĝeneralaj Klavkombinoj +Name[es]=Accesos rápidos de teclado globales +Name[et]=Globaalsed kiirklahvid +Name[eu]=Laster-tekla orokorrak +Name[fa]=میان‌برهای صفحه‌ کلید سراسری +Name[fi]=Työpöydänlaajuiset pikanäppäimet +Name[fr]=Raccourcis globaux de clavier +Name[fy]=Globale fluchkeppelings +Name[ga]=Aicearraí Comhchoiteanna Méarchláir +Name[gl]=Atallos de teclado globais +Name[gu]=વૈશ્વીક કીબોર્ડ ટૂંકાણો +Name[he]=קיצורי מקשים גלובליים +Name[hi]=वैश्विक कुंजीपट शॉर्टकट +Name[hne]=वैस्विक कुंजीपट सार्टकट +Name[hr]=Globalni prečaci tipkovnice +Name[hsb]=Globalne tastaturowe skrótšenki +Name[hu]=Globális billentyűparancsok +Name[ia]=Vias breve global de claviero +Name[id]=Jalan Pintas Papan Ketik Global +Name[is]=Víðværir flýtilyklar +Name[it]=Scorciatoie globali della tastiera +Name[ja]=グローバルキーボードショートカット +Name[kk]=Жалпы жүйелік перне тіркесімдер +Name[km]=ផ្លូវកាត់​ក្ដារចុច​​សកល +Name[kn]=ಸಾರ್ವತ್ರಿಕ ಕೀಲಿಮಣೆ ಶೀಘ್ರಮಾರ್ಗಗಳು (ಶಾರ್ಟ್ ಕಟ್) +Name[ko]=전역 키보드 단축키 +Name[ku]=Kurteriyên Klavyeyê yên Giştî +Name[lt]=Globalieji spartieji klavišai +Name[lv]=Globālie tastatūras īsceļi +Name[mai]=वैश्विक कुंजीपटल शार्टकट +Name[mk]=Глобални кратенки на тастатурата +Name[ml]=ആഗോളമായ കീബോര്‍ഡിലെ കുറക്കുവഴികള്‍ +Name[mr]=जागतिक कळफलक शॉर्टकट +Name[nb]=Globale hurtigtaster +Name[nds]=Globaal Tastkombinatschonen +Name[nl]=Globale sneltoetsen +Name[nn]=Globale snøgg­tastar +Name[or]=ଜାଗତିକ କିବୋର୍ଡ଼ ସଂକ୍ଷିପ୍ତ ପଥ +Name[pa]=ਗਲੋਬਲ ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ +Name[pl]=Globalne skróty klawiszowe +Name[pt]=Atalhos Globais do Teclado +Name[pt_BR]=Atalhos de teclado globais +Name[ro]=Acceleratori de tastatură globali +Name[ru]=Глобальные комбинации клавиш +Name[si]=ගෝලීය යතුරුපුවරු කෙටිමං +Name[sk]=Globálne klávesové skratky +Name[sl]=Splošne tipkovne bližnjice +Name[sr]=Глобалне пречице са тастатуре +Name[sr@ijekavian]=Глобалне пречице са тастатуре +Name[sr@ijekavianlatin]=Globalne prečice sa tastature +Name[sr@latin]=Globalne prečice sa tastature +Name[sv]=Globala snabbtangenter +Name[ta]=பொது விசைப்பலகை குறுக்குவழிகள் +Name[te]=గ్లౌబల్ కీబోర్‍డ్ లఘువులు +Name[tg]=Глобальные комбинации клавиш +Name[th]=ปุ่มพิมพ์ลัดใช้งานส่วนรวม +Name[tr]=Genel Klavye Kısayolları +Name[ug]=ئومۇمىيەت ھەرپتاختا تېزلەتمىسى +Name[uk]=Загальні клавіатурні скорочення +Name[vi]=Phím tắt toàn hệ thống +Name[wa]=Rascourtis del taprece po ttavå +Name[x-test]=xxGlobal Keyboard Shortcutsxx +Name[zh_CN]=全局键盘快捷键 +Name[zh_TW]=全域鍵盤捷徑 + +Comment=Configuration of keybindings +Comment[af]=Opstelling van sleutel bindinge +Comment[ar]=إعداد ارتباطات المفاتيح +Comment[ast]=Configuración de les asociaciones de les tecles +Comment[be]=Настаўленні клавішных скаротаў +Comment[be@latin]=Nałady dla poviaziaŭ klavišaŭ z roznymi aperacyjami +Comment[bg]=Настройки на бързи клавиши +Comment[bn]=কী-বাইন্ডিং কনফিগারেশন +Comment[bn_IN]=কি-বাইন্ডিং কনফিগারেশন +Comment[br]=Kefluniañ ereoù stokell +Comment[bs]=Postava prečica sa tastature +Comment[ca]=Configuració dels lligams de tecles +Comment[ca@valencia]=Configuració dels lligams de tecles +Comment[cs]=Nastavení klávesových zkratek +Comment[csb]=Nastôw klawiszowëch skrodzënów +Comment[cy]=Furfweddiad o rwymiadau bysell +Comment[da]=Indstilling af tastebindinger +Comment[de]=Einrichtung von Tastenzuordnungen +Comment[el]=Διαμόρφωση συνδυασμών πλήκτρων +Comment[en_GB]=Configuration of keybindings +Comment[eo]=Agordo de klavkombinoj +Comment[es]=Configuración de las asociaciones de las teclas +Comment[et]=Kiirklahvide seadistamine +Comment[eu]=Laster-teklen konfigurazioa +Comment[fa]=پیکربندی مقیدسازیهای کلید +Comment[fi]=Näppäinsidosten asetukset +Comment[fr]=Configuration des combinaisons de touches +Comment[fy]=Ynstellings foar fluchtoetsen +Comment[ga]=Cumraíocht ceangal eochracha +Comment[gl]=Configuración dos atallos de teclado +Comment[gu]=કીજોડાણોનું રૂપરેખાંકન +Comment[he]=הגדרות מיפוי מקשים +Comment[hi]=की-बाइंडिंग का कॉन्फ़िगरेशन +Comment[hne]=की-बाइंडिंग के कान्फिगरेसन +Comment[hr]=Konfiguriranje prečaca tipkovnice +Comment[hsb]=Připrawjenje přirjadowanjow tastow +Comment[hu]=A billentyűparancsok beállításai +Comment[ia]=Configuration de keybindings (ligamines de claves) +Comment[id]=Konfigurasi pengikat tombol +Comment[is]=Stillingar altækra flýtihnappa +Comment[it]=Configurazione delle associazioni di tasti +Comment[ja]=キーバインディングの設定 +Comment[ka]=კლავიშთა წყვილების კონფიგურაცია +Comment[kk]=Перне тіркесімдерді баптау +Comment[km]=ការ​កំណត់​រចនាសម្ព័ន្ធ​ការ​ចង​គ្រាប់ចុច +Comment[kn]=ಕೀಲಿ ನಿಬಂಧಗಳ (ಬೈಂಡಿಂಗ್ಸ್) ಸಂರಚನೆ +Comment[ko]=키 바인딩 설정 +Comment[ku]=Veavakirina bicîkirina bişkojkan +Comment[lt]=Klavišų siečių derinimas +Comment[lv]=Taustiņsasaistes konfigurēšana +Comment[mai]=की-बाइंडिंग क' कान्फिगरेशन +Comment[mk]=Конфигурација на врски меѓу копчиња и акции +Comment[ml]=കീബൈന്‍ഡിങ്സിനുള്ള ക്രമീകരണം +Comment[mr]=कीबाइंडिंगची संयोजना +Comment[ms]=Konfigurasi untuk pengikatan kekunci +Comment[nb]=Oppsett av hurtigtaster +Comment[nds]=Instellen vun Tastkombinatschonen +Comment[ne]=कुञ्जी बाइन्डिङहरूको कन्फिगरेसन +Comment[nl]=Instellingen voor sneltoetsen +Comment[nn]=Oppsett av snøggtastar +Comment[or]=କିବନ୍ଧନଗୁଡ଼ିକର ସଂରଚନା +Comment[pa]=ਕੀ-ਬਾਇਡਿੰਗ ਦੀ ਸੰਰਚਨਾ +Comment[pl]=Konfiguracja powiązań klawiszowych +Comment[pt]=Configuração das teclas +Comment[pt_BR]=Configuração dos atalhos de teclado +Comment[ro]=Configurează asocierile de taste +Comment[ru]=Настройка глобальных комбинаций клавиш +Comment[se]=Jođánisboaluid heiveheapmi +Comment[si]=යතුරු බැඳුම් වල සැකසුම +Comment[sk]=Nastavenie globálnych klávesových skratiek +Comment[sl]=Nastavitve tipkovnih bližnjic +Comment[sr]=Постава пречица са тастатуре +Comment[sr@ijekavian]=Постава пречица са тастатуре +Comment[sr@ijekavianlatin]=Postava prečica sa tastature +Comment[sr@latin]=Postava prečica sa tastature +Comment[sv]=Anpassa kortkommandon +Comment[ta]=விசைசேர்வுகளுக்கான வடிவமைப்பு +Comment[te]=కీ భందనముల యొక్క ఆకృతీకరణ +Comment[tg]=Танзимоти тугмаҳои якҷояшуда +Comment[th]=ปรับแต่งปุ่มพิมพ์ลัดต่าง ๆ +Comment[tr]=Tuş bağıntılarının yapılandırılması +Comment[ug]=كۇنۇپكا باغلاش سەپلىمە +Comment[uk]=Налаштування прив'язок клавіш +Comment[uz]=Tugmalar birikmasini moslash +Comment[uz@cyrillic]=Тугмалар бирикмасини мослаш +Comment[vi]=Cấu hình các tổ hợp phím +Comment[wa]=Apontiaedje des rascourtis di tapes +Comment[xh]=Uqwalaselo lwezibopheleo zesitshixo +Comment[x-test]=xxConfiguration of keybindingsxx +Comment[zh_CN]=键绑定配置 +Comment[zh_TW]=按鍵關聯設定 + +X-KDE-Keywords=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts +X-KDE-Keywords[bs]=Tipke, Globalni vezovi tipki, Šema tipki, Veze tipki, Prečice, Prečice za aplikacije, globalne Prečice +X-KDE-Keywords[ca]=Tecles,Assignació de tecles globals,Esquema de tecles,Assignació de tecles,dreceres,dreceres d'aplicació,dreceres globals +X-KDE-Keywords[ca@valencia]=Tecles,Assignació de tecles globals,Esquema de tecles,Assignació de tecles,dreceres,dreceres d'aplicació,dreceres globals +X-KDE-Keywords[da]=Taster,globale tastebindinger,tasteskema,tastebindinger,genveje,programgenveje,globale genveje +X-KDE-Keywords[de]=Tasten,Tastenzuordnung,Tastenkürzel,Kurzbefehle,Tastenschema,Tastaturlayout +X-KDE-Keywords[el]=Πλήκτρα,δεσμεύσεις καθολικών πλήκτρων, σχήμα πλήκτρων, δεσμεύσεις πλήκτρων,συντομεύσεις,συντομεύσεις εφαρμογών,καθολικές συντομεύσεις +X-KDE-Keywords[es]=Teclas,Asociaciones globales de teclas,Esquema de teclas,Asociaciones de teclas,accesos rápidos,accesos rápidos de aplicaciones,accesos rápidos globales +X-KDE-Keywords[et]=klahvid,globaalsed kiirklahvid,klaviatuuriskeem,klahviseosed,kiirklahvid,rakenduse kiirklahvid,globaalsed kiirklahvid +X-KDE-Keywords[eu]=tekla,laster-tekla orokor,tekla-eskema,laster-tekla,lasterbide,aplikazioen laster-teklak +X-KDE-Keywords[fi]=näppäimet,globaalit näppäinsidokset,yleiset näppäinsidokset,työpöydänlaajuiset näppäinsidokset,globaalit pikanäppäimet,työpöydänlaajuiset pikanäppäimet,globaalit näppäinyhdistelmät,työpöydänlaajuiset näppäinyhdistelmät,näppäimistön yleispikavalinnat,näppäimistön globaalit pikavalinnat,näppäinsidokset,pikanäppäimet,näppäimistön pikavalinnat, näppäinyhdistelmät,näppäinoikotiet,sovellusten pikanäppäimet,sovellusten näppäinyhdistelmät,sovellusten näppäinoikotiet +X-KDE-Keywords[fr]=Touches, Association globale des touches, Schéma des touches, Association de touches, Raccourci des applications, Raccourcis globaux +X-KDE-Keywords[ga]=Eochracha,Ceangail chomhchoiteanna eochracha,Scéim eochracha,Ceangail eochracha,aicearraí,aicearraí feidhmchláir,aicearraí comhchoiteanna +X-KDE-Keywords[gl]=tecla, atallo, asociación, esquema de teclas, atallo de teclado, asociación de teclas, atallo a programa, atallos globais +X-KDE-Keywords[hu]=Billentyűk,Globális gyorsbillentyűk,Billentyűséma,Gyorsbillentyűk,alkalmazás gyorsbillentyűk,globális gyorsbillentyűk +X-KDE-Keywords[ia]=Claves,ligamines de clave global,schema de clave,ligamines de clave,vias breve,vias breve de application,vias breve global +X-KDE-Keywords[it]=tasti,scorciatoie globali di tastiera,schema di tasti,scorciatoie,scorciatoie delle applicazioni,scorciatoie globali +X-KDE-Keywords[kk]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts +X-KDE-Keywords[km]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts +X-KDE-Keywords[ko]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,키,전역 키 바인딩,키 바인딩,단축키,프로그램 단축키 +X-KDE-Keywords[mr]=कीज, ग्लोबल की बाईंडिंगज, की स्कीम, की बाईंडिंगज, शॉर्टकटस, अप्लिकेशन शॉर्टकटस, ग्लोबल शॉर्टकटस +X-KDE-Keywords[nb]=Taster,Globale tastebindingeer,Tastaturutforming,Tastebindinger,snarveier,programsnarveier,globale snarveier +X-KDE-Keywords[nds]=Tasten,Globaal Tasttowiesen,Tasttowiesen,Tastkombinatschonen,Programm-Tastkombinatschonen,Globaal Tastkombinatschonen +X-KDE-Keywords[nl]=toetsen,globale toetsbindingen,toetsenschema,toetsbindingen,sneltoetsen,sneltoetsen van toepassing,globale sneltoetsen +X-KDE-Keywords[pl]=Klawisze,Globalne powiązania klawiszy,Motyw klawiszy,Powiązania klawiszy,skróty,skróty programów,globalne skróty +X-KDE-Keywords[pt]=Teclas,combinações de teclas,global,esquema de teclas,atalhos de teclado,atalhos,atalhos das aplicações +X-KDE-Keywords[pt_BR]=Teclas,combinações de teclas global,esquema de teclas,atalhos de teclado,atalhos,atalhos dos aplicativos, atalhos globais +X-KDE-Keywords[ru]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,клавиши,глобальные привязки клавиш,схема,привязки клавиш,комбинации клавиш,комбинации клавиш в приложениях,глобальные привязки клавиш +X-KDE-Keywords[sk]=Klávesy,Globálne klávesové skratky,Klávesová schéma,Klávesové skratky,skratky,skratky aplikácie,globálne skratky +X-KDE-Keywords[sl]=tipke,splošne tipkovne bližnjice,tipkovna shema,shema tipk,tipkovne bližnjice,vezave tipk,bližnjice,programske bližnjice,splošne bližnjice +X-KDE-Keywords[sr]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,тастери,глобалне свезе тастера,шема тастера,свезе тастера,пречице,пречице програма,глобалне пречице +X-KDE-Keywords[sr@ijekavian]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,тастери,глобалне свезе тастера,шема тастера,свезе тастера,пречице,пречице програма,глобалне пречице +X-KDE-Keywords[sr@ijekavianlatin]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,tasteri,globalne sveze tastera,šema tastera,sveze tastera,prečice,prečice programa,globalne prečice +X-KDE-Keywords[sr@latin]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,tasteri,globalne sveze tastera,šema tastera,sveze tastera,prečice,prečice programa,globalne prečice +X-KDE-Keywords[sv]=Tangenter,Globala tangentbindingar,Tangentschema,Tangentbindingar,genvägar,programgenvägar,globala genvägar +X-KDE-Keywords[tr]=Tuşlar,Genel kısayollar,Klavye şeması,Klavye Kısayolları,kısayollar,uygulama kısayolları,genel kısayollar, kısayol tuşları +X-KDE-Keywords[uk]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,клавіатура,скорочення,клавіатурні скорочення,схема,загальні клавіатурні скорочення,клавіатурні скорочення програми,загальні скорочення +X-KDE-Keywords[vi]=Phím,tổ hợp phím toàn cục,phối hợp phím,tổ hợp phím,gõ tắt,gõ tắt cho ứng dụng +X-KDE-Keywords[x-test]=xxKeys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcutsxx +X-KDE-Keywords[zh_CN]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts,按键,全局键绑定,按键方案,按键绑定,快捷键,应用程序,全局快捷键 +X-KDE-Keywords[zh_TW]=Keys,Global key bindings,Key scheme,Key bindings,shortcuts,application shortcuts,global shortcuts + +Categories=Qt;KDE;X-KDE-settings-accessibility; diff --git a/kcms/keys/kglobalshortcutseditor.cpp b/kcms/keys/kglobalshortcutseditor.cpp new file mode 100644 index 0000000000..d52396dceb --- /dev/null +++ b/kcms/keys/kglobalshortcutseditor.cpp @@ -0,0 +1,673 @@ +/* + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "kglobalshortcutseditor.h" + +#include "ui_kglobalshortcutseditor.h" +#include "export_scheme_dialog.h" +#include "select_scheme_dialog.h" +#include "globalshortcuts.h" +#include "kglobalaccel_interface.h" +#include "kglobalaccel_component_interface.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * README + * + * This class was created because the kshortcutseditor class has some shortcomings. That class uses + * QTreeWidget and therefore makes it impossible for an outsider to switch the models. But the + * global shortcuts editor did that. Each global component ( kded, krunner, kopete ... ) was + * destined to be separately edited. If you selected another component the kshortcutseditor was + * cleared and refilled. But the items take care of undoing. Therefore when switching the component + * you lost the undo history. + * + * To solve that problem this class keeps one kshortcuteditor for each component. That is easier + * than rewrite that dialog to a model/view framework. + * + * It perfectly covers a bug of KExtedableItemDelegate when clearing and refilling the associated + * model. + */ + +class ComponentData + { + +public: + + ComponentData( + const QString &uniqueName, + const QDBusObjectPath &path, + KShortcutsEditor *_editor); + + ~ComponentData(); + + QString uniqueName() const; + KShortcutsEditor *editor(); + QDBusObjectPath dbusPath(); + +private: + + QString _uniqueName; + QDBusObjectPath _path; + QPointer _editor; + }; + + +ComponentData::ComponentData( + const QString &uniqueName, + const QDBusObjectPath &path, + KShortcutsEditor *editor) + : _uniqueName(uniqueName), + _path(path), + _editor(editor) + {} + + +ComponentData::~ComponentData() + { + delete _editor; _editor = 0; + } + + +QString ComponentData::uniqueName() const + { + return _uniqueName; + } + + +QDBusObjectPath ComponentData::dbusPath() + { + return _path; + } + + +KShortcutsEditor *ComponentData::editor() + { + return _editor; + } + + +class KGlobalShortcutsEditor::KGlobalShortcutsEditorPrivate +{ +public: + + KGlobalShortcutsEditorPrivate(KGlobalShortcutsEditor *q) + : q(q), + stack(0), + bus(QDBusConnection::sessionBus()) + {} + + //! Setup the gui + void initGUI(); + + //! Load the component at @a componentPath + bool loadComponent(const QDBusObjectPath &componentPath); + + //! Return the componentPath for component + QDBusObjectPath componentPath(const QString &componentUnique); + + //! Remove the component + void removeComponent(const QString &componentUnique); + + KGlobalShortcutsEditor *q; + Ui::KGlobalShortcutsEditor ui; + QStackedWidget *stack; + KShortcutsEditor::ActionTypes actionTypes; + QHash components; + QDBusConnection bus; +}; + + +void KGlobalShortcutsEditor::KGlobalShortcutsEditorPrivate::initGUI() +{ + ui.setupUi(q); + // Create a stacked widget. + stack = new QStackedWidget(q); + q->layout()->addWidget(stack); + + // Connect our components + connect(ui.components, SIGNAL(activated(QString)), + q, SLOT(activateComponent(QString))); + + // Build the menu + QMenu *menu = new QMenu(q); + menu->addAction( QIcon::fromTheme("document-import"), i18n("Import Scheme..."), q, SLOT(importScheme())); + menu->addAction( QIcon::fromTheme("document-export"), i18n("Export Scheme..."), q, SLOT(exportScheme())); + menu->addAction( i18n("Set All Shortcuts to None"), q, SLOT(clearConfiguration())); + QAction *action = menu->addAction( QIcon::fromTheme("edit-delete"), i18n("Remove Component")); + connect(action, &QAction::triggered, [this]() { + QString name = ui.components->currentText(); + QString componentUnique = components.value(name)->uniqueName(); + + // The confirmation text is different when the component is active + if (KGlobalAccel::isComponentActive(componentUnique)) { + if (KMessageBox::questionYesNo( + q, + i18n("Component '%1' is currently active. Only global shortcuts currently not active will be removed from the list.\n" + "All global shortcuts will reregister themselves with their defaults when they are next started.", componentUnique), + i18n("Remove component")) != KMessageBox::Yes) { + return; + } + } else { + if (KMessageBox::questionYesNo( + q, + i18n("Are you sure you want to remove the registered shortcuts for component '%1'? " + "The component and shortcuts will reregister themselves with their default settings" + " when they are next started.", + componentUnique), + i18n("Remove component")) != KMessageBox::Yes) { + return; + } + } + + // Initiate the removing of the component. + if (KGlobalAccel::cleanComponent(componentUnique)) { + + // Get the objectPath BEFORE we delete the source of it + QDBusObjectPath oPath = components.value(name)->dbusPath(); + // Remove the component from the gui + removeComponent(componentUnique); + + // Load it again + // ############# + if (loadComponent(oPath)) { + // Active it + q->activateComponent(name); + } + } + }); + + ui.menu_button->setMenu(menu); + + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(q); + proxyModel->setSourceModel(new QStandardItemModel(0, 1, proxyModel)); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + ui.components->setModel(proxyModel); +} + + +KGlobalShortcutsEditor::KGlobalShortcutsEditor(QWidget *parent, KShortcutsEditor::ActionTypes actionTypes) + : QWidget(parent), + d(new KGlobalShortcutsEditorPrivate(this)) +{ + d->actionTypes = actionTypes; + // Setup the ui + d->initGUI(); +} + + +KGlobalShortcutsEditor::~KGlobalShortcutsEditor() +{ + // Before closing the door, undo all changes + undo(); + qDeleteAll(d->components); + delete d; +} + + +void KGlobalShortcutsEditor::activateComponent(const QString &component) +{ + QHash::Iterator iter = d->components.find(component); + if (iter == d->components.end()) { + Q_ASSERT(iter != d->components.end()); + return; + } else { + int index = d->ui.components->findText(component); + Q_ASSERT(index != -1); + if (index > -1) { + // Known component. Get it. + d->ui.components->setCurrentIndex(index); + d->stack->setCurrentWidget((*iter)->editor()); + } + } +} + + +void KGlobalShortcutsEditor::addCollection( + KActionCollection *collection, + const QDBusObjectPath &objectPath, + const QString &id, + const QString &friendlyName) +{ + KShortcutsEditor *editor; + // Check if this component is known + QHash::Iterator iter = d->components.find(friendlyName); + if (iter == d->components.end()) { + // Unknown component. Create an editor. + editor = new KShortcutsEditor(this, d->actionTypes); + d->stack->addWidget(editor); + + // try to find one appropriate icon ( allowing NULL pixmap to be returned) + QPixmap pixmap = KIconLoader::global()->loadIcon(id, KIconLoader::Small, 0, + KIconLoader::DefaultState, QStringList(), 0, true); + // if NULL pixmap is returned, use the F.D.O "system-run" icon + if (pixmap.isNull()) { + pixmap = KIconLoader::global()->loadIcon("system-run", KIconLoader::Small); + } + + // Add to the component combobox + d->ui.components->addItem(pixmap, friendlyName); + d->ui.components->model()->sort(0); + + // Add to our component registry + ComponentData *cd = new ComponentData(id, objectPath, editor); + d->components.insert(friendlyName, cd); + + connect(editor, SIGNAL(keyChange()), this, SLOT(_k_key_changed())); + } else { + // Known component. + editor = (*iter)->editor(); + } + + // Add the collection to the editor of the component + editor->addCollection(collection, friendlyName); + + if (d->ui.components->count() > -1) { + d->ui.components->setCurrentIndex(0); + activateComponent(d->ui.components->itemText(0)); + } +} + + +void KGlobalShortcutsEditor::clearConfiguration() +{ + QString name = d->ui.components->currentText(); + d->components[name]->editor()->clearConfiguration(); +} + + +void KGlobalShortcutsEditor::defaults(ComponentScope scope) +{ + switch (scope) + { + case AllComponents: + Q_FOREACH (ComponentData *cd, d->components) { + // The editors are responsible for the reset + cd->editor()->allDefault(); + } + break; + + case CurrentComponent: { + QString name = d->ui.components->currentText(); + // The editors are responsible for the reset + d->components[name]->editor()->allDefault(); + } + break; + + default: + Q_ASSERT(false); + }; +} + + +void KGlobalShortcutsEditor::clear() +{ + // Remove all components and their associated editors + qDeleteAll(d->components); + d->components.clear(); + d->ui.components->clear(); +} + + +static bool compare(const QString &a, const QString &b) + { + return a.toLower().localeAwareCompare(b.toLower()) < 0; + } + + +void KGlobalShortcutsEditor::exportScheme() +{ + QStringList keys = d->components.keys(); + qSort(keys.begin(), keys.end(), compare); + ExportSchemeDialog dia(keys); + + if (dia.exec() != KMessageBox::Ok) { + return; + } + + QUrl url = QFileDialog::getSaveFileUrl(this, QString(), QUrl(), QStringLiteral("*.kksrc")); + if (!url.isEmpty()) { + KConfig config(url.path(), KConfig::SimpleConfig); + // TODO: Bug ossi to provide a method for this + Q_FOREACH(const QString &group, config.groupList()) + { + // do not overwrite the Settings group. That makes it possible to + // update the standard scheme kksrc file with the editor. + if (group == "Settings") continue; + config.deleteGroup(group); + } + exportConfiguration(dia.selectedComponents(), &config); + } +} + + +void KGlobalShortcutsEditor::importScheme() +{ + // Check for unsaved modifications + if (isModified()) { + int choice = KMessageBox::warningContinueCancel( + this, + i18n("Your current changes will be lost if you load another scheme before saving this one"), + i18n("Load Shortcut Scheme"), + KGuiItem(i18n("Load"))); + if (choice != KMessageBox::Continue) { + return; + } + } + + SelectSchemeDialog dialog(this); + if (dialog.exec() != KDialog::Accepted) { + return; + } + + KUrl url = dialog.selectedScheme(); + if (!url.isLocalFile()) { + KMessageBox::sorry(this, i18n("This file (%1) does not exist. You can only select local files.", + url.url())); + return; + } + KConfig config(url.path(), KConfig::SimpleConfig); + importConfiguration(&config); +} + + +void KGlobalShortcutsEditor::load() +{ + // Connect to kglobalaccel. If that fails there is no need to continue. + qRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType(); + + org::kde::KGlobalAccel kglobalaccel( + "org.kde.kglobalaccel", + "/kglobalaccel", + d->bus); + + if (!kglobalaccel.isValid()) { + QString errorString; + QDBusError error = kglobalaccel.lastError(); + // The global shortcuts DBus service manages all global shortcuts and we + // can't do anything useful without it. + if (error.isValid()) { + errorString = i18n("Message: %1\nError: %2", error.message(), error.name()); + } + + KMessageBox::sorry( + this, + i18n("Failed to contact the KDE global shortcuts daemon\n") + + errorString ); + return; + } + + // Undo all changes not yet applied + undo(); + clear(); + + QDBusReply< QList > componentsRc = kglobalaccel.allComponents(); + if (!componentsRc.isValid()) + { + // Sometimes error pop up only after the first real call. + QString errorString; + QDBusError error = componentsRc.error(); + // The global shortcuts DBus service manages all global shortcuts and we + // can't do anything useful without it. + if (error.isValid()) { + errorString = i18n("Message: %1\nError: %2", error.message(), error.name()); + } + + KMessageBox::sorry( + this, + i18n("Failed to contact the KDE global shortcuts daemon\n") + + errorString ); + return; + } + QList components = componentsRc; + + Q_FOREACH(const QDBusObjectPath &componentPath, components) { + d->loadComponent(componentPath); + } // Q_FOREACH(component) +} + + +void KGlobalShortcutsEditor::save() +{ + // The editors are responsible for the saving + kDebug() << "Save the changes"; + Q_FOREACH (ComponentData *cd, d->components) { + cd->editor()->commit(); + } +} + + +void KGlobalShortcutsEditor::importConfiguration(KConfigBase *config) +{ + kDebug() << config->groupList(); + + // In a first step clean out the current configurations. We do this + // because we want to minimize the chance of conflicts. + Q_FOREACH (ComponentData *cd, d->components) { + KConfigGroup group(config, cd->uniqueName()); + kDebug() << cd->uniqueName() << group.name(); + if (group.exists()) { + kDebug() << "Removing" << cd->uniqueName(); + cd->editor()->clearConfiguration(); + } + } + + // Now import the new configurations. + Q_FOREACH (ComponentData *cd, d->components) { + KConfigGroup group(config, cd->uniqueName()); + if (group.exists()) { + kDebug() << "Importing" << cd->uniqueName(); + cd->editor()->importConfiguration(&group); + } + } +} + +void KGlobalShortcutsEditor::exportConfiguration(QStringList components, KConfig *config) const + { + Q_FOREACH (const QString &componentFriendly, components) + { + QHash::Iterator iter = d->components.find(componentFriendly); + if (iter == d->components.end()) + { + Q_ASSERT(iter != d->components.end()); + continue; + } + else + { + KConfigGroup group(config, (*iter)->uniqueName()); + (*iter)->editor()->exportConfiguration(&group); + } + } + } + + +void KGlobalShortcutsEditor::undo() +{ + // The editors are responsible for the undo + kDebug() << "Undo the changes"; + Q_FOREACH (ComponentData *cd, d->components) { + cd->editor()->undoChanges(); + } +} + + +bool KGlobalShortcutsEditor::isModified() const +{ + Q_FOREACH (ComponentData *cd, d->components) { + if (cd->editor()->isModified()) { + return true; + } + } + return false; +} + + +void KGlobalShortcutsEditor::_k_key_changed() +{ + emit changed(isModified()); +} + + +QDBusObjectPath KGlobalShortcutsEditor::KGlobalShortcutsEditorPrivate::componentPath(const QString &componentUnique) +{ + return QDBusObjectPath(QLatin1String("/component/") + componentUnique); +} + + +bool KGlobalShortcutsEditor::KGlobalShortcutsEditorPrivate::loadComponent(const QDBusObjectPath &componentPath) +{ + // Get the component + org::kde::kglobalaccel::Component component( + "org.kde.kglobalaccel", + componentPath.path(), + bus); + if (!component.isValid()) { + kDebug() << "Component " << componentPath.path() << "not valid! Skipping!"; + return false; + } + + // Get the shortcut contexts. + QDBusReply shortcutContextsRc = component.getShortcutContexts(); + if (!shortcutContextsRc.isValid()) { + kDebug() << "Failed to get contexts for component " + << componentPath.path() <<"! Skipping!"; + kDebug() << shortcutContextsRc.error(); + return false; + } + QStringList shortcutContexts = shortcutContextsRc; + + // We add the shortcuts for all shortcut contexts to the editor. This + // way the user keeps full control of it's shortcuts. + Q_FOREACH (const QString &shortcutContext, shortcutContexts) { + + QDBusReply< QList > shortcutsRc = + component.allShortcutInfos(shortcutContext); + if (!shortcutsRc.isValid()) + { + kDebug() << "allShortcutInfos() failed for " << componentPath.path() << shortcutContext; + continue; + } + QList shortcuts = shortcutsRc; + // Shouldn't happen. But you never know + if (shortcuts.isEmpty()) { + kDebug() << "Got shortcut context" << shortcutContext << "without shortcuts for" + << componentPath.path(); + continue; + } + + // It's safe now + const QString componentUnique = shortcuts[0].componentUniqueName(); + QString componentContextId = componentUnique; + // kglobalaccel knows that '|' is our separator between + // component and context + if (shortcutContext != "default") { + componentContextId += QString("|") + shortcutContext; + } + + // Create a action collection for our current component:context + KActionCollection* col = new KActionCollection( + q, + componentContextId); + + // Now add the shortcuts. + Q_FOREACH (const KGlobalShortcutInfo &shortcut, shortcuts) { + + const QString &objectName = shortcut.uniqueName(); + QAction *action = col->addAction(objectName); + action->setProperty("isConfigurationAction", QVariant(true)); // see KAction::~KAction + action->setText(shortcut.friendlyName()); + + // Always call this to enable global shortcuts for the action. The editor widget + // checks it. + // Also actually loads the shortcut using the KAction::Autoloading mechanism. + // Avoid setting the default shortcut; it would just be written to the global + // configuration so we would not get the real one below. + KGlobalAccel::self()->setShortcut(action, QList()); + + // The default shortcut will never be loaded because it's pointless in a real + // application. There are no scarce resources [i.e. physical keys] to manage + // so applications can set them at will and there's no autoloading. + QList sc = shortcut.defaultKeys(); + if (sc.count()>0) { + KGlobalAccel::self()->setDefaultShortcut(action, sc); + } + } // Q_FOREACH(shortcut) + + QString componentFriendlyName = shortcuts[0].componentFriendlyName(); + + if (shortcuts[0].contextUniqueName() != "default") + { + componentFriendlyName += + QString('[') + shortcuts[0].contextFriendlyName() + QString(']'); + } + + q->addCollection(col, componentPath, componentContextId, componentFriendlyName ); + + } // Q_FOREACH(context) + + return true; +} + + +void KGlobalShortcutsEditor::KGlobalShortcutsEditorPrivate::removeComponent( + const QString &componentUnique ) + { + // TODO: Remove contexts too. + + Q_FOREACH (const QString &text, components.keys()) + { + if (components.value(text)->uniqueName() == componentUnique) + { + // Remove from QComboBox + int index = ui.components->findText(text); + Q_ASSERT(index != -1); + ui.components->removeItem(index); + + // Remove from QStackedWidget + stack->removeWidget(components[text]->editor()); + + // Remove the componentData + delete components.take(text); + } + } + } + + +#include "kglobalshortcutseditor.moc" diff --git a/kcms/keys/kglobalshortcutseditor.h b/kcms/keys/kglobalshortcutseditor.h new file mode 100644 index 0000000000..1889aa1650 --- /dev/null +++ b/kcms/keys/kglobalshortcutseditor.h @@ -0,0 +1,154 @@ +/* + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 KGLOBALSHORTCUTSEDITOR_H +#define KGLOBALSHORTCUTSEDITOR_H + +#include + +#include "kshortcutseditor.h" + +class KActionCollection; +class KShortcut; +class KConfig; +class QDBusObjectPath; + +/** + * Combine a KShortcutsEditor with a KComboBox. + * + * @see KShortcutsEditor + * @author Michael Jansen + */ +class KGlobalShortcutsEditor : public QWidget +{ + Q_OBJECT + +public: + + /** + * Constructor + * + * @param parent parent widget + */ + KGlobalShortcutsEditor(QWidget *parent, + KShortcutsEditor::ActionTypes actionTypes = KShortcutsEditor::AllActions); + ~KGlobalShortcutsEditor(); + + /** + * Insert an action collection, i.e. add all it's actions to the ones already associated + * with the KShortcutsEditor object. + * + * @param collection the collection to add + * @param component title for the component + * @param title title for the subtree in the component + */ + void addCollection(KActionCollection *, const QDBusObjectPath &path, const QString &id, const QString &name); + + /** + * Clear all collections were currently hosting. Current changes are not + * undone? Do that before calling this method. + */ + void clear(); + + + /** + * Revert all changes made since the last save. + */ + void undo(); + + + /** + * Load the shortcuts from the configuration. + */ + void importConfiguration(KConfigBase *config); + + + /** + * Save the shortcuts to the configuration. + */ + void exportConfiguration(QStringList componentsFriendly, KConfig *config) const; + + + /** + * Are the unsaved changes? + */ + bool isModified() const; + + enum ComponentScope + { + AllComponents, + CurrentComponent + }; + +Q_SIGNALS: + + /** + * Indicate that state of the modules contents has changed. + * + * @param state changed or not + */ + void changed(bool); + + +public Q_SLOTS: + + /** + * Activate the component \a component. + * + * @param component the component + */ + void activateComponent(const QString &component); + + /** + * Set all shortcuts to none. + */ + void clearConfiguration(); + + /** + * Load/Reload the global shortcuts + */ + void load(); + + /** + * Make the changes persistent. + * + * That's function is not really saving. Global shortcuts are saved immediately. This + * prevent the undo on deleting the editor. + */ + void save(); + + /** + * Set shortcuts to their default value; + */ + void defaults(ComponentScope scope); + + virtual void importScheme(); + virtual void exportScheme(); + +private Q_SLOTS: + void _k_key_changed(); + +private: + + friend class KGlobalShortcutsEditorPrivate; + class KGlobalShortcutsEditorPrivate; + KGlobalShortcutsEditorPrivate *const d; + + Q_DISABLE_COPY(KGlobalShortcutsEditor) +}; // class KGlobalShortcutsEditor + +#endif // KGLOBALSHORTCUTSEDITOR_H diff --git a/kcms/keys/kglobalshortcutseditor.ui b/kcms/keys/kglobalshortcutseditor.ui new file mode 100644 index 0000000000..444103e2de --- /dev/null +++ b/kcms/keys/kglobalshortcutseditor.ui @@ -0,0 +1,57 @@ + + + KGlobalShortcutsEditor + + + + 0 + 0 + 612 + 516 + + + + + + + + + KDE component: + + + + + + + + 0 + 0 + + + + + + + + File + + + + + + + + + + KComboBox + QComboBox +
    kcombobox.h
    +
    +
    + + components + menu_button + + + +
    diff --git a/kcms/keys/schemes/kde3.kksrc b/kcms/keys/schemes/kde3.kksrc new file mode 100644 index 0000000000..336757d387 --- /dev/null +++ b/kcms/keys/schemes/kde3.kksrc @@ -0,0 +1,166 @@ +[Settings] +Name=KDE Default for 3 Modifier Keys +Name[af]=Standaard KDE vir 3 verandering sleutels +Name[ar]=مبدئي كدي لـ3 مفاتيح مغيرة +Name[ast]=Predetermináu de KDE de 3 modificadores de tecláu +Name[be]=Стандартны для KDE з трыма клавішамі мадыфікацыі +Name[be@latin]=Zmoŭčanaja schiema „KDE” dla 3 klavišnych madyfikataraŭ +Name[bg]=KDE (с 3 модификационни клавиша) +Name[ca]=Omissió del KDE per a 3 tecles modificadores +Name[ca@valencia]=Omissió del KDE per a 3 tecles modificadores +Name[cs]=Výchozí pro KDE (3 modifikátory) +Name[csb]=Domëslny nastôw KDE dlô 3 klawiszów zjinaczi +Name[cy]=Rhagosodion KDE i 3 Bysell Addasu +Name[da]=KDE-standard med 3 modifikatortaster +Name[de]=KDE-Standard für 3 Sondertasten +Name[el]=Προκαθορισμένο του KDE για 3 τροποποιητές +Name[en_GB]=KDE Default for 3 Modifier Keys +Name[eo]=KDE-defaŭlto por 3 modifoklavoj +Name[es]=Predeterminado de KDE de 3 modificadores de teclado +Name[et]=KDE vaikeskeem 3 muuteklahviga +Name[eu]=KDE lehenetsia 3 tekla modifikatzailekin +Name[fa]=پیش‌فرض KDE برای ۳ کلید تغییردهنده +Name[fi]=KDE oletus 3:lle muokkausnäppäimelle +Name[fr]=KDE par défaut pour 3 touches de modifications +Name[fy]=KDE-standert foar 3 modifikaasjetoetsen +Name[ga]=Réamhshocrú KDE le haghaidh trí eochair mhionathraithe +Name[gl]=Predeterminado de KDE para 3 teclas modificadoras +Name[gu]=૩ બદલેલ કળો માટે KDE મૂળભૂત +Name[he]=ברירת המחדל של KDE עבור 3 כפתורים משני מצב +Name[hi]=3 मॉडीफ़ायर कुंजियों के लिए केडीई डिफ़ॉल्ट +Name[hne]=3 माडीफायर कुंजी मन बर केडीई डिफाल्ट +Name[hr]=KDE zadano za 3 modifikatorske tipke +Name[hsb]=KDE-standard za tři modifikowace tasty +Name[hu]=KDE-s alapértelmezés (3 módosító billentyűvel) +Name[ia]=KDE predefinite pro 3 claves modificator +Name[id]=Standar KDE untuk 3 Tombol Pengubah +Name[is]=Sjálfgefið KDE fyrir 3 breytilykla +Name[it]=Predefinito di KDE per 3 tasti modificatori +Name[ja]=KDE 標準 (修飾キー 3 個) +Name[kk]=3 түрлендіру пернелі KDE-нің әдетті баптауы +Name[km]=លំនាំដើម​របស់ KDE សម្រាប់​សោ​កែប្រែ ៣ +Name[kn]=೩ ಪರಿವರ್ತಕ ಕೀಲಿಗಳಿಗೆ ಕೆಡಿಇ ಪೂರ್ವನಿಯೋಜನೆ +Name[ko]=세 개의 수정자 키를 사용하는 KDE 기본값 +Name[ku]=KDE Standard ji bo 3 Bişkojkên Guherker +Name[lt]=KDE numatytoji 3 lygio klavišams – modifikatoriams +Name[lv]=KDE noklusējums ar 3 modifikācijas taustiņiem +Name[mai]=3 माडीफायर कुंजीसभ क' लेल केडीई पूर्वनिर्धारित +Name[mk]=KDE-стандардно за 3 копчиња-модификатори +Name[ml]=3 മോഡിഫയര്‍ കീകള്‍ക്കു് കെഡിഇയുടെ സഹജമായതു് +Name[mr]=3 संपादन की करीता KDE मुलभूत +Name[ms]=Piawai KDE untuk 3 Kekunci Pengubah Suai +Name[nb]=KDE-standard for tre valgtaster +Name[nds]=KDE-Standard för 3 Sünnertasten +Name[ne]=३ परिमार्जक कुञ्जीका लागि पूर्वनिर्धारित केडीई +Name[nl]=KDE-standaard voor 3 modificatietoetsen +Name[nn]=KDE-standard med tre valtastar +Name[or]=3ଟି ପରିବର୍ତ୍ତକ କି ପାଇଁ KDE ପୂର୍ବନିର୍ଦ୍ଧାରିତ +Name[pa]=3 ਮੋਡੀਫਾਇਰ ਸਵਿੱਚਾਂ ਲਈ KDE ਡਿਫਾਲਟ +Name[pl]=Ustawienia domyślne KDE dla 3 klawiszy modyfikatorów +Name[pt]=Predefinição do KDE para 3 Teclas Modificadoras +Name[pt_BR]=Padrão do KDE para 3 teclas modificadoras +Name[ro]=Implicit KDE pentru 3 modificatori +Name[ru]=KDE с тремя клавишами-модификаторами +Name[se]=KDE-standárda mas leat golbma válljeboalu +Name[si]=3 වෙනස් යතුරු සඳහා KDE පෙරනිමියන් +Name[sk]=KDE štandardné (3 modifikačné klávesy) +Name[sl]=Privzeto za 3 spremenilne tipke +Name[sr]=КДЕ‑ово подразумевано за три модификаторска тастера +Name[sr@ijekavian]=КДЕ‑ово подразумијевано за три модификаторска тастера +Name[sr@ijekavianlatin]=KDE‑ovo podrazumijevano za tri modifikatorska tastera +Name[sr@latin]=KDE‑ovo podrazumevano za tri modifikatorska tastera +Name[sv]=KDE-förinställt med 3 väljartangenter +Name[ta]=KDE Default for 3 Modifier Keys +Name[te]=3 సవరింపు కీలకొరకు KDE అప్రమేయం +Name[tg]=KDE с тремя клавишами-модификаторами +Name[th]=ค่าปริยายของ KDE สำหรับปุ่มเปลี่ยนหน้าที่ 3 ปุ่ม +Name[tr]=3 Değiştirici Anahtar için KDE Varsayılan +Name[uk]=Типова для KDE з 3 клавішами-модифікаторами +Name[vi]=Mặc định KDE cho 3 Phím Bổ trợ +Name[wa]=Prémetou KDE (3 tapes modifieueses) +Name[xh]=KDE Engagqibekanga ye 3 Izitsixo Mofifier +Name[x-test]=xxKDE Default for 3 Modifier Keysxx +Name[zh_CN]=三个修饰键的 KDE 默认值 +Name[zh_TW]=KDE 預設 3 個變更鍵 +Uses Win Modifier=false + +[klipper][Global Shortcuts] +clipboard_action=Ctrl+Alt+X +repeat_action=Ctrl+Alt+R +show_klipper_popup=Ctrl+Alt+V + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=Ctrl+Alt+L +Log Out Without Confirmation=none +Log Out=Ctrl+Alt+Del +Reboot Without Confirmation=none +Run Command=Alt+F2 +Show System Activity=Ctrl+Esc + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Ctrl+Print +Kill Window=Ctrl+Alt+Esc +Mouse Emulation=Alt+F12 +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Ctrl+F10 +Switch to Desktop 11=Ctrl+F11 +Switch to Desktop 12=Ctrl+F12 +Switch to Desktop 13=Ctrl+Shift+F1 +Switch to Desktop 14=Ctrl+Shift+F2 +Switch to Desktop 15=Ctrl+Shift+F3 +Switch to Desktop 16=Ctrl+Shift+F4 +Switch to Desktop 1=Ctrl+F1 +Switch to Desktop 2=Ctrl+F2 +Switch to Desktop 3=Ctrl+F3 +Switch to Desktop 4=Ctrl+F4 +Switch to Desktop 5=Ctrl+F5 +Switch to Desktop 6=Ctrl+F6 +Switch to Desktop 7=Ctrl+F7 +Switch to Desktop 8=Ctrl+F8 +Switch to Desktop 9=Ctrl+F9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=Ctrl+Shift+Tab +Walk Through Desktop List=Ctrl+Tab +Walk Through Desktops (Reverse)=none +Walk Through Desktops=none +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+Tab +Window Close=Alt+F4 +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=none +Window Minimize=none +Window Move=none +Window Operations Menu=Alt+F3 +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Alt+Print +Window Shade=none +Window to Desktop 10=none +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=none +Window to Desktop 2=none +Window to Desktop 3=none +Window to Desktop 4=none +Window to Desktop 5=none +Window to Desktop 6=none +Window to Desktop 7=none +Window to Desktop 8=none +Window to Desktop 9=none +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/schemes/kde4.kksrc b/kcms/keys/schemes/kde4.kksrc new file mode 100644 index 0000000000..2ea1432b92 --- /dev/null +++ b/kcms/keys/schemes/kde4.kksrc @@ -0,0 +1,166 @@ +[Settings] +Name=KDE Default for 4 Modifier Keys +Name[af]=Standaard KDE vir 4 verandering sleutels +Name[ar]=مبدئي كدي لـ4 مفاتيح مغيرة +Name[ast]=Predetermináu de KDE de 4 modificadores de tecláu +Name[be]=Стандартны для KDE з чатырма клавішамі мадыфікацыі +Name[be@latin]=Zmoŭčanaja schiema „KDE” dla 4 klavišnych madyfikataraŭ +Name[bg]=KDE (с 4 модификационни клавиша) +Name[ca]=Omissió del KDE per a 4 tecles modificadores +Name[ca@valencia]=Omissió del KDE per a 4 tecles modificadores +Name[cs]=Výchozí pro KDE (4 modifikátory) +Name[csb]=Domëslny nastôw KDE dlô 4 klawiszów zjinaczi +Name[cy]=Rhagosodion KDE i 4 Bysell Addasu +Name[da]=KDE-standard med 4 modifikatortaster +Name[de]=KDE-Standard für 4 Sondertasten +Name[el]=Προκαθορισμένο του KDE για 4 τροποποιητές +Name[en_GB]=KDE Default for 4 Modifier Keys +Name[eo]=KDE-defaŭlto por 4 modifoklavoj +Name[es]=Predeterminado de KDE de 4 modificadores de teclado +Name[et]=KDE vaikeskeem 4 muuteklahviga +Name[eu]=KDE lehenetsia 4 tekla modifikatzailekin +Name[fa]=پیش‌فرض KDE برای ۴ کلید تغییردهنده +Name[fi]=KDE oletus 4:lle muokkausnäppäimelle +Name[fr]=KDE par défaut pour 4 touches de modifications +Name[fy]=KDE-standert foar 4 modifikaasjetoetsen +Name[ga]=Réamhshocrú KDE le haghaidh ceithre eochair mhionathraithe +Name[gl]=Predeterminado de KDE para 4 teclas modificadoras +Name[gu]=૪ બદલેલ કળો માટે KDE મૂળભૂત +Name[he]=ברירת המחדל של KDE עבור 4 כפתורים משני מצב +Name[hi]=4 मॉडीफ़ायर कुंजियों के लिए केडीई डिफ़ॉल्ट +Name[hne]=4 माडीफायर कुंजी मन बर केडीई डिफाल्ट +Name[hr]=KDE zadano za 4 modifikatorske tipke +Name[hsb]=KDE-standard za štyri modifikowace tasty +Name[hu]=KDE-s alapértelmezés (4 módosító billentyűvel) +Name[ia]=KDE predefinite pro 4 claves modificator +Name[id]=Standar KDE untuk 4 Tombol Pengubah +Name[is]=Sjálfgefið KDE fyrir 4 breytilykla +Name[it]=Predefinito di KDE per 4 tasti modificatori +Name[ja]=KDE 標準 (修飾キー 4 個) +Name[kk]=4 түрлендіру пернелі KDE-нің әдетті баптауы +Name[km]=លំនាំដើម​របស់ KDE សម្រាប់​សោ​កែប្រែ ៤ +Name[kn]=೪ ಪರಿವರ್ತಕ ಕೀಲಿಗಳಿಗೆ ಕೆಡಿಇ ಪೂರ್ವನಿಯೋಜನೆ +Name[ko]=네 개의 수정자 키를 사용하는 KDE 기본값 +Name[ku]=KDE Standard ji bo 4 Bişkojkên Guherker +Name[lt]=KDE numatytoji 4 lygio klavišams – modifikatoriams +Name[lv]=KDE noklusējums ar 4 modifikācijas taustiņiem +Name[mai]=4 माडीफायर कुंजियों क' लेल केडीई पूर्वनिर्धारित +Name[mk]=KDE-стандардно за 4 копчиња-модификатори +Name[ml]=4 മോഡിഫയര്‍ കീകള്‍ക്കു് കെഡിഇയുടെ സഹജമായതു് +Name[mr]=4 संपादन की करीता KDE मुलभूत +Name[ms]=Piawai KDE untuk 4 Kekunci Pengubah Suai +Name[nb]=KDE-standard for fire valgtaster +Name[nds]=KDE-Standard för 4 Sünnertasten +Name[ne]=४ परिमार्जक कुञ्जीका लागि पूर्वनिर्धारित केडीई +Name[nl]=KDE-standaard voor 4 modificatietoetsen +Name[nn]=KDE-standard med fire valtastar +Name[or]=4ଟି ପରିବର୍ତ୍ତକ କି ପାଇଁ KDE ପୂର୍ବନିର୍ଦ୍ଧାରିତ +Name[pa]=4 ਮੋਡੀਫਾਇਰ ਸਵਿੱਚਾਂ ਲਈ KDE ਡਿਫਾਲਟ +Name[pl]=Ustawienia domyślne KDE dla 4 klawiszy modyfikatorów +Name[pt]=Predefinição do KDE para 4 Teclas Modificadoras +Name[pt_BR]=Padrão do KDE para 4 teclas modificadoras +Name[ro]=Implicit KDE pentru 4 modificatori +Name[ru]=KDE с четырьмя клавишами-модификаторами +Name[se]=KDE-standárda mas leat njeallje válljenboalu +Name[si]=4 වෙනස් යතුරු සඳහා KDE පෙරනිමියන් +Name[sk]=KDE štandardné (4 modifikačné klávesy) +Name[sl]=Privzeto za 4 spremenilne tipke +Name[sr]=КДЕ‑ово подразумевано за четири модификаторска тастера +Name[sr@ijekavian]=КДЕ‑ово подразумијевано за четири модификаторска тастера +Name[sr@ijekavianlatin]=KDE‑ovo podrazumijevano za četiri modifikatorska tastera +Name[sr@latin]=KDE‑ovo podrazumevano za četiri modifikatorska tastera +Name[sv]=KDE-förinställt med 4 väljartangenter +Name[ta]=KDE Default for 4 Modifier Keys +Name[te]=4 సవరింపు కీలకొరకు KDE అప్రమేయం +Name[tg]=KDE с четырьмя клавишами-модификаторами +Name[th]=ค่าปริยายของ KDE สำหรับปุ่มเปลี่ยนหน้าที่ 4 ปุ่ม +Name[tr]=4 Değiştirici Anahtar için KDE Varsayılan +Name[uk]=Типова для KDE з 4 клавішами-модифікаторами +Name[vi]=Mặc định KDE cho 4 Phím Bổ trợ +Name[wa]=Prémetou KDE (4 tapes modifieueses) +Name[xh]=KDE Engagqibekanga ye 4 Izitsixo Mofifier +Name[x-test]=xxKDE Default for 4 Modifier Keysxx +Name[zh_CN]=四个修饰键的 KDE 默认值 +Name[zh_TW]=KDE 預設 4 個變更鍵 +Uses Win Modifier=true + +[klipper][Global Shortcuts] +clipboard_action=Meta+Ctrl+X +repeat_action=Meta+Ctrl+R +show_klipper_popup=Meta+Ctrl+V + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=Meta+ScrollLock +Log Out Without Confirmation=none +Log Out=Meta+Esc +Reboot Without Confirmation=none +Run Command=Meta+Return; Alt+F2 +Show System Activity=Meta+Ctrl+Pause + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Meta+Print +Kill Window=Meta+Ctrl+Del +Mouse Emulation=none +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Meta+F10 +Switch to Desktop 11=none +Switch to Desktop 12=none +Switch to Desktop 13=none +Switch to Desktop 14=none +Switch to Desktop 15=none +Switch to Desktop 16=none +Switch to Desktop 1=Meta+F1 +Switch to Desktop 2=Meta+F2 +Switch to Desktop 3=Meta+F3 +Switch to Desktop 4=Meta+F4 +Switch to Desktop 5=Meta+F5 +Switch to Desktop 6=Meta+F6 +Switch to Desktop 7=Meta+F7 +Switch to Desktop 8=Meta+F8 +Switch to Desktop 9=Meta+F9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=none +Walk Through Desktop List=none +Walk Through Desktops (Reverse)=Meta+Shift+Tab +Walk Through Desktops=Meta+Tab +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+Tab +Window Close=Alt+Esc; Alt+F4 +Window Lower=none +Window Maximize Horizontal=Meta+= +Window Maximize Vertical=Meta+| +Window Maximize=Meta++ +Window Minimize=Meta+- +Window Move=none +Window Operations Menu=Alt+Menu +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Alt+Print +Window Shade=Meta+_ +Window to Desktop 10=Meta+Alt+F10 +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=Meta+Alt+F1 +Window to Desktop 2=Meta+Alt+F2 +Window to Desktop 3=Meta+Alt+F3 +Window to Desktop 4=Meta+Alt+F4 +Window to Desktop 5=Meta+Alt+F5 +Window to Desktop 6=Meta+Alt+F6 +Window to Desktop 7=Meta+Alt+F7 +Window to Desktop 8=Meta+Alt+F8 +Window to Desktop 9=Meta+Alt+F9 +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Meta+Ctrl+K diff --git a/kcms/keys/schemes/mac4.kksrc b/kcms/keys/schemes/mac4.kksrc new file mode 100644 index 0000000000..0ecde0079e --- /dev/null +++ b/kcms/keys/schemes/mac4.kksrc @@ -0,0 +1,171 @@ +[Settings] +Name=Mac Scheme +Name[af]=Mac Tema +Name[ar]=مخطط الماك +Name[ast]=Tema Mac +Name[be]=Схема Mac +Name[be@latin]=Schiema „Mac” +Name[bg]=Mac +Name[bn]=ম্যাক্ স্কীম +Name[bn_IN]=Mac স্কিম +Name[br]=Steuñv Mac +Name[ca]=Esquema Mac +Name[ca@valencia]=Esquema Mac +Name[cs]=Mac schéma +Name[csb]=Mòtiw Mac-a +Name[cy]=Cynllun Mac +Name[da]=Mac-system +Name[de]=Mac-Design +Name[el]=Σχήμα Mac +Name[en_GB]=Mac Scheme +Name[eo]=Makintoŝa aranĝo +Name[es]=Tema Mac +Name[et]=Maci skeem +Name[eu]=Mac eskema +Name[fa]=طرحواره مکینتاش +Name[fi]=Mac-skeema +Name[fr]=Agencement Mac +Name[fy]=Mac-skema +Name[ga]=Scéim Mac +Name[gl]=Esquema de Mac +Name[gu]=મેક પધ્ધતિ +Name[he]=ערכת Mac +Name[hi]=मॅक प्रसंग +Name[hne]=मॅक प्रसंग +Name[hr]=Mac shema +Name[hsb]=Mac-šema +Name[hu]=Mac +Name[ia]=Schema Mac +Name[id]=Skema Mac +Name[is]=Mac þema +Name[it]=Schema Mac +Name[ja]=Macintosh スキーマ +Name[ka]=Mac სქემა +Name[kk]=Mac сұлбасы +Name[km]=គ្រោងការណ៍ Mac +Name[kn]=ಮ್ಯಾಕ್ ಪದ್ಧತಿ (ಸ್ಕೀಮ್) +Name[ko]=Mac 배열 +Name[ku]=Dirbê Mac +Name[lt]=Mac schema +Name[lv]=Mac shēma +Name[mai]=मैक प्रसंग +Name[mk]=Mac-шема +Name[ml]=മാക് പദ്ധതി +Name[mr]=मॅक सुत्रयोजना +Name[nb]=Mac-oppsett +Name[nds]=Mac-Vörbild +Name[ne]=म्याक योजना +Name[nl]=Mac-schema +Name[nn]=Mac-oppsett +Name[or]=Mac ଯୋଜନା +Name[pa]=Mac ਸਕੀਮ +Name[pl]=Motyw Mac-a +Name[pt]=Esquema do Mac +Name[pt_BR]=Esquema do Mac +Name[ro]=Schemă Mac +Name[ru]=Mac +Name[se]=Mac-coakkáldat +Name[si]=Mac ක්‍රමය +Name[sk]=Mac schéma +Name[sl]=Shema Mac +Name[sr]=Мекинтошева шема +Name[sr@ijekavian]=Мекинтошева шема +Name[sr@ijekavianlatin]=Macintosheva šema +Name[sr@latin]=Macintosheva šema +Name[sv]=Mac schema +Name[ta]=Mac முறைமை +Name[te]=Mac స్కీమ్ +Name[tg]=Нақшаи Mac +Name[th]=ใช้แบบของ MAC +Name[tr]=Mac Şeması +Name[uk]=Схема Mac +Name[uz]=Mac mavzusi +Name[uz@cyrillic]=Mac мавзуси +Name[vi]=Phối hợp của Mac +Name[wa]=Djeu d' rascourtis Mac +Name[xh]=Udweliso lwe Mac +Name[x-test]=xxMac Schemexx +Name[zh_CN]=Mac 方案 +Name[zh_TW]=Mac 機制 +Uses Win Modifier=true + +[klipper][Global Shortcuts] +clipboard_action=Ctrl+Alt+X +repeat_action=Ctrl+Alt+R +show_klipper_popup=Ctrl+Alt+V + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=Ctrl+Alt+L +Log Out Without Confirmation=none +Log Out=Ctrl+Alt+Del +Reboot Without Confirmation=none +Run Command=Alt+F2 +Show System Activity=Ctrl+Esc + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Ctrl+Shift+3 +Kill Window=Ctrl+Alt+Esc +Mouse Emulation=none +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Ctrl+F10 +Switch to Desktop 11=Ctrl+F11 +Switch to Desktop 12=Ctrl+F12 +Switch to Desktop 13=Ctrl+Shift+F1 +Switch to Desktop 14=Ctrl+Shift+F2 +Switch to Desktop 15=Ctrl+Shift+F3 +Switch to Desktop 16=Ctrl+Shift+F4 +Switch to Desktop 1=Ctrl+F1 +Switch to Desktop 2=Ctrl+F2 +Switch to Desktop 3=Ctrl+F3 +Switch to Desktop 4=Ctrl+F4 +Switch to Desktop 5=Ctrl+F5 +Switch to Desktop 6=Ctrl+F6 +Switch to Desktop 7=Ctrl+F7 +Switch to Desktop 8=Ctrl+F8 +Switch to Desktop 9=Ctrl+F9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=Ctrl+E +Walk Through Desktop List (Reverse)=none +Walk Through Desktop List=none +Walk Through Desktops (Reverse)=Alt+Shift+Tab +Walk Through Desktops=Alt+Tab +Walk Through Windows (Reverse)=Ctrl+Shift+Tab +Walk Through Windows=Ctrl+Tab +Window Close=Alt+F4 +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=none +Window Minimize=none +Window Move=none +Window Operations Menu=Alt+F3 +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Ctrl+Shift+4 +Window Shade=none +Window to Desktop 10=none +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=none +Window to Desktop 2=none +Window to Desktop 3=none +Window to Desktop 4=none +Window to Desktop 5=none +Window to Desktop 6=none +Window to Desktop 7=none +Window to Desktop 8=none +Window to Desktop 9=none +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/schemes/old_kde3.kksrc b/kcms/keys/schemes/old_kde3.kksrc new file mode 100644 index 0000000000..561ff99f70 --- /dev/null +++ b/kcms/keys/schemes/old_kde3.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Alt+F1 +Reboot Computer=none +Show Window List=Alt+F5 +Toggle Showing Desktop=Ctrl+Alt+D + +[Shortcuts] +AddBookmark=Ctrl+B +Back=Alt+Left +Close=Ctrl+W +Copy=Ctrl+C; Ctrl+Insert +Cut=Ctrl+X; Shift+Del +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V; Shift+Insert +PopupMenuContext=Menu +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit=Ctrl+Q +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_kde4.kksrc b/kcms/keys/schemes/old_kde4.kksrc new file mode 100644 index 0000000000..64dfd8da32 --- /dev/null +++ b/kcms/keys/schemes/old_kde4.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Meta+Menu +Reboot Computer=none +Show Window List=Meta+0 +Toggle Showing Desktop=Meta+Ctrl+D + +[Shortcuts] +AddBookmark=Ctrl+B +Back=Alt+Left +Close=Ctrl+Esc; Ctrl+W +Copy=Ctrl+C; Ctrl+Insert +Cut=Ctrl+X; Shift+Del +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V; Shift+Insert +PopupMenuContext=Menu +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit=Ctrl+Q +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_mac4.kksrc b/kcms/keys/schemes/old_mac4.kksrc new file mode 100644 index 0000000000..f0da90deab --- /dev/null +++ b/kcms/keys/schemes/old_mac4.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Alt+F1 +Reboot Computer=none +Show Window List=Alt+F5 +Toggle Showing Desktop=Ctrl+Alt+D + +[Shortcuts] +AddBookmark=Ctrl+B +Back=Alt+Left +Close=Ctrl+W +Copy=Ctrl+C +Cut=Ctrl+X +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=Ctrl+G +FindPrev=Ctrl+Shift+G +Forward=Alt+Right +GotoLine=none +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V +PopupMenuContext=Menu +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit=Ctrl+Q +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_unix3.kksrc b/kcms/keys/schemes/old_unix3.kksrc new file mode 100644 index 0000000000..6e724007a7 --- /dev/null +++ b/kcms/keys/schemes/old_unix3.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Alt+F1 +Reboot Computer=none +Show Window List=none +Toggle Showing Desktop=Ctrl+Alt+D + +[Shortcuts] +AddBookmark=Ctrl+B +Back=Alt+Left +Close=Ctrl+W +Copy=Ctrl+C +Cut=Ctrl+X +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+S +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V +PopupMenuContext=Menu +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit=Ctrl+Q +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll= +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_win3.kksrc b/kcms/keys/schemes/old_win3.kksrc new file mode 100644 index 0000000000..410d68779d --- /dev/null +++ b/kcms/keys/schemes/old_win3.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Ctrl+Esc +Reboot Computer=none +Show Window List=none +Toggle Showing Desktop=Ctrl+Alt+D + +[Shortcuts] +AddBookmark=Ctrl+D +Back=Alt+Left +Close=Ctrl+F4; Ctrl+W +Copy=Ctrl+C; Ctrl+Insert +Cut=Ctrl+X; Shift+Del +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V; Shift+Insert +PopupMenuContext=F10 +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit= +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_win4.kksrc b/kcms/keys/schemes/old_win4.kksrc new file mode 100644 index 0000000000..3859eb68d3 --- /dev/null +++ b/kcms/keys/schemes/old_win4.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Ctrl+Esc +Reboot Computer=none +Show Window List=none +Toggle Showing Desktop=Meta+D; Win+M + +[Shortcuts] +AddBookmark=Ctrl+D +Back=Alt+Left +Close=Ctrl+F4; Ctrl+W +Copy=Ctrl+C; Ctrl+Insert +Cut=Ctrl+X; Shift+Del +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V; Shift+Insert +PopupMenuContext=F10 +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit= +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/old_wm3.kksrc b/kcms/keys/schemes/old_wm3.kksrc new file mode 100644 index 0000000000..561ff99f70 --- /dev/null +++ b/kcms/keys/schemes/old_wm3.kksrc @@ -0,0 +1,51 @@ + +[Global Shortcuts] +Halt Computer=none +Popup Launch Menu=Alt+F1 +Reboot Computer=none +Show Window List=Alt+F5 +Toggle Showing Desktop=Ctrl+Alt+D + +[Shortcuts] +AddBookmark=Ctrl+B +Back=Alt+Left +Close=Ctrl+W +Copy=Ctrl+C; Ctrl+Insert +Cut=Ctrl+X; Shift+Del +DeleteWordBack=Ctrl+Backspace +DeleteWordForward=Ctrl+Del +Deselect=Ctrl+Shift+A +End=Ctrl+End +Find=Ctrl+F +FindNext=F3 +FindPrev=Shift+F3 +Forward=Alt+Right +GotoLine=Ctrl+G +Help=F1 +Home=Ctrl+Home +Insert=Ctrl+Insert +New=Ctrl+N +Next=Next +NextCompletion=Ctrl+Down +Open=Ctrl+O +Paste=Ctrl+V; Shift+Insert +PopupMenuContext=Menu +PrevCompletion=Ctrl+Up +Print=Ctrl+P +Prior=Prior +Quit=Ctrl+Q +Redo=Ctrl+Shift+Z +Reload=F5 +Replace=Ctrl+R +RotateDown=Down +RotateUp=Up +Save=Ctrl+S +SelectAll=Ctrl+A +ShowMenubar=Ctrl+M +SubstringCompletion=Ctrl+T +TextCompletion=Ctrl+E +Undo=Ctrl+Z +Up=Alt+Up +WhatsThis=Shift+F1 +ZoomIn=Ctrl++ +ZoomOut=Ctrl+- diff --git a/kcms/keys/schemes/split_kksrc b/kcms/keys/schemes/split_kksrc new file mode 100755 index 0000000000..9fab61e42f --- /dev/null +++ b/kcms/keys/schemes/split_kksrc @@ -0,0 +1,111 @@ +#!/usr/bin/perl + +use strict; +use warnings; + + +foreach my $file( @ARGV ) + { + print STDERR "Working on $file\n"; + + open(my $FILEHD, $file) or do + { + print STDERR "Failed to open $file : $!"; + next; + }; + + open(my $NEWHD, ">new_$file") or do + { + print STDERR "Failed to open new_$file : $!"; + next; + }; + + open(my $OLDHD, ">old_$file") or do + { + print STDERR "Failed to open old_$file : $!"; + next; + }; + + my $process = 0; + my @kwin; + my @krunner; + my @klipper; + my @kxkb; + for( <$FILEHD> ) + { + /\[Settings\]/ and do { print $NEWHD $_; next; }; + /Name(\[[a-zA-Z_@]*\])?/ and do { print $NEWHD $_; next; }; + /Name\[x-test\]/ and do { print $NEWHD $_; next; }; + /Uses Win Modifier/ and do { print $NEWHD $_; next; }; + + /\[Global Shortcuts\]/ and do { print $OLDHD $_; $process = 1; next; }; + /\[Shortcuts\]/ and do { print $OLDHD $_; $process = 0; next; }; + + s/Alt\+Ctrl/Ctrl+Alt/; + s/Delete/Del/; + s/Escape/Esc/; + s/Win/Meta/; + + if ($process) + { + /Desktop Screenshot=/ and do { s/Desktop Screenshot=/Desktop Screenshot to Clipboard=/; push @kwin, $_; next; }; + /Kill Window=/ and do { push @kwin, $_; next; }; + /Mouse Emulation/ and do { push @kwin, $_; next; }; + /Switch to Desktop [0-9]+/ and do { push @kwin, $_; next; }; + /Switch to (Next|Previous) Desktop=/ and do { push @kwin, $_; next; }; + /Switch One Desktop / and do { push @kwin, $_; next; }; + /Toggle Window Raise\/Lower=/ and do { push @kwin, $_; next; }; + /Walk Through Desktop/ and do { push @kwin, $_; next; }; + /Walk Through Windows/ and do { push @kwin, $_; next; }; + /Window to (Next |Previous )?Desktop/ and do { push @kwin, $_; next; }; + /Window (Close|Minimize|Lower|Move|Raise|Resize|Shade)/ and do { push @kwin, $_; next; }; + /Window Maximize/ and do { push @kwin, $_; next; }; + /Window Operations Menu=/ and do { s/Window Screenshot=/Window Screenshot to Clipboard=/; push @kwin, $_; next; }; + /Window Screenshot=/ and do { s/Window Screenshot=/Window Screenshot to Clipboard=/; push @kwin, $_; next; }; + + /Switch to Next Keyboard Layout/ and do { push @kxkb, $_; next; }; + + /clipboard_action/ and do { push @klipper, $_; next; }; + /repeat_action/ and do { push @klipper, $_; next; }; + /show_klipper_popup/ and do { push @klipper, $_; next; }; + + /Halt without Confirmation/ and do { s/Halt without Confirmation/Halt Without Confirmation/; push @krunner, $_; next; }; + /Lock Session/ and do { push @krunner, $_; next; }; + /Log Out/ and do { push @krunner, $_; next; }; + /Log Out Without Confirmation/ and do { push @krunner, $_; next; }; + /Lock Session/ and do { push @krunner, $_; next; }; + /Reboot without Confirmation/ and do { s/Reboot without Confirmation/Reboot Without Confirmation/; push @krunner, $_; next; }; + /Run Command/ and do { push @krunner, $_; next; }; + /Show Taskmanager/ and do { s/Show Taskmanager/Show System Activity/; push @krunner, $_; next; }; + } + + print $OLDHD $_; + } + + print $NEWHD "\n[klipper][Global Shortcuts]\n"; + print $NEWHD sort @klipper; + print $NEWHD "\n[krunner][Global Shortcuts]\n"; + print $NEWHD sort @krunner; + print $NEWHD "\n[kwin][Global Shortcuts]\n"; + print $NEWHD sort @kwin; + print $NEWHD "\n[kxkb][Global Shortcuts]\n"; + print $NEWHD sort @kxkb; + + close($FILEHD) or do + { + print STDERR "Failed to close $file : $!"; + next; + }; + + close($NEWHD) or do + { + print STDERR "Failed to close new_$file : $!"; + next; + }; + + close($OLDHD) or do + { + print STDERR "Failed to close old_$file : $!"; + next; + }; + } diff --git a/kcms/keys/schemes/unix3.kksrc b/kcms/keys/schemes/unix3.kksrc new file mode 100644 index 0000000000..1845cde7c5 --- /dev/null +++ b/kcms/keys/schemes/unix3.kksrc @@ -0,0 +1,171 @@ +[Settings] +Name=UNIX Scheme +Name[af]=UNIX Tema +Name[ar]=مخطط يونِكس +Name[ast]=Esquema UNIX +Name[be]=Схема UNIX +Name[be@latin]=Schiema „UNIX” +Name[bg]=UNIX +Name[bn]=ইউনিক্স স্কীম +Name[bn_IN]=UNIX স্কিম +Name[br]=Steuñv UNIX +Name[ca]=Esquema UNIX +Name[ca@valencia]=Esquema UNIX +Name[cs]=Unixové schéma +Name[csb]=Mòtiw Uniksa +Name[cy]=Cynllun UNIX +Name[da]=UNIX-system +Name[de]=UNIX-Design +Name[el]=Σχήμα UNIX +Name[en_GB]=UNIX Scheme +Name[eo]=Uniksa aranĝo +Name[es]=Esquema UNIX +Name[et]=UNIX-i skeem +Name[eu]=UNIX eskema +Name[fa]=طرحواره یونیکس +Name[fi]=UNIX-skeema +Name[fr]=Agencement UNIX +Name[fy]=UNIX-skema +Name[ga]=Scéim UNIX +Name[gl]=Esquema de UNIX +Name[gu]=UNIX પધ્ધતિ +Name[he]=ערכת UNIX +Name[hi]=यूनिक्स प्रसंग +Name[hne]=यूनिक्स प्रसंग +Name[hr]=UNIX shema +Name[hsb]=UNIX-šema +Name[hu]=UNIX +Name[ia]=Schema UNIX +Name[id]=Skema UNIX +Name[is]=UNIX þema +Name[it]=Schema UNIX +Name[ja]=UNIX スキーマ +Name[ka]=UNIX სქემა +Name[kk]=UNIX сұлбасы +Name[km]=គ្រោងការណ៍​យូនីក +Name[kn]=ಯುನೀಕ್ಸ್ ಪದ್ಧತಿ (ಸ್ಕೀಮ್) +Name[ko]=UNIX 배열 +Name[ku]=Şemaya UNIX'ê +Name[lt]=UNIX schema +Name[lv]=UNIX shēma +Name[mai]=यूनिक्स प्रसंग +Name[mk]=UNIX-шема +Name[ml]=യൂണിക്സ് പദ്ധതി +Name[mr]=UNIX सुत्रयोजना +Name[nb]=UNIX-oppsett +Name[nds]=UNIX-Vörbild +Name[ne]=यूनिक्स योजना +Name[nl]=UNIX-schema +Name[nn]=UNIX-oppsett +Name[or]=UNIX ଯୋଜନା +Name[pa]=UNIX ਸਕੀਮ +Name[pl]=Motyw Uniksa +Name[pt]=Esquema do UNIX +Name[pt_BR]=Esquema do UNIX +Name[ro]=Schemă UNIX +Name[ru]=UNIX +Name[se]=UNIX-čoahkkáldat +Name[si]=UNIX ක්‍රමය +Name[sk]=UNIX schéma +Name[sl]=Shema UNIX +Name[sr]=Уникс шема +Name[sr@ijekavian]=Уникс шема +Name[sr@ijekavianlatin]=Unix šema +Name[sr@latin]=Unix šema +Name[sv]=Unix schema +Name[ta]=UNIX முறைமை +Name[te]=UNIX స్కీమ్ +Name[tg]=Нақшаи UNIX +Name[th]=ใช้แบบของ UNIX +Name[tr]=UNIX Şeması +Name[uk]=Схема UNIX +Name[uz]=UNIX mavzusi +Name[uz@cyrillic]=UNIX мавзуси +Name[vi]=Phối hợp của Unix +Name[wa]=Djeu d' rascourtis Unix +Name[xh]=Udweliso lwe UNIX +Name[x-test]=xxUNIX Schemexx +Name[zh_CN]=Unix 方案 +Name[zh_TW]=UNIX 機制 +Uses Win Modifier=false + +[klipper][Global Shortcuts] +clipboard_action=none +repeat_action=Ctrl+Alt+R +show_klipper_popup=none + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=Ctrl+Alt+L +Log Out Without Confirmation=none +Log Out=Ctrl+Alt+Del +Reboot Without Confirmation=none +Run Command=Alt+F2 +Show System Activity=Ctrl+Esc + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=none +Kill Window=Alt+F9 +Mouse Emulation=Alt+F12 +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Ctrl+F10 +Switch to Desktop 11=Ctrl+F11 +Switch to Desktop 12=Ctrl+F12 +Switch to Desktop 13=Ctrl+Shift+F1 +Switch to Desktop 14=Ctrl+Shift+F2 +Switch to Desktop 15=Ctrl+Shift+F3 +Switch to Desktop 16=Ctrl+Shift+F4 +Switch to Desktop 1=Ctrl+F1 +Switch to Desktop 2=Ctrl+F2 +Switch to Desktop 3=Ctrl+F3 +Switch to Desktop 4=Ctrl+F4 +Switch to Desktop 5=Ctrl+F5 +Switch to Desktop 6=Ctrl+F6 +Switch to Desktop 7=Ctrl+F7 +Switch to Desktop 8=Ctrl+F8 +Switch to Desktop 9=Ctrl+F9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=Ctrl+Shift+Tab +Walk Through Desktop List=none +Walk Through Desktops (Reverse)=none +Walk Through Desktops=Ctrl+Tab +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+F11 +Window Close=none +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=Alt+Shift+F3 +Window Minimize=Alt+F4 +Window Move=Alt+F5 +Window Operations Menu=none +Window Raise=none +Window Resize=Alt+F6 +Window Screenshot to Clipboard=none +Window Shade=none +Window to Desktop 10=none +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=none +Window to Desktop 2=none +Window to Desktop 3=none +Window to Desktop 4=none +Window to Desktop 5=none +Window to Desktop 6=none +Window to Desktop 7=none +Window to Desktop 8=none +Window to Desktop 9=none +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/schemes/win3.kksrc b/kcms/keys/schemes/win3.kksrc new file mode 100644 index 0000000000..e1929fb735 --- /dev/null +++ b/kcms/keys/schemes/win3.kksrc @@ -0,0 +1,170 @@ +[Settings] +Name=Windows Scheme (Without Win Key) +Name[af]=Venster Skema (Sonder Win Sleutel) +Name[ar]=مخطط ويندوز (بدون مفتاح Win) +Name[ast]=Esquema Windows (Ensin tecla Win) +Name[be]=Схема Windows (без клавішы "Win") +Name[be@latin]=Schiema „Windows” (biaz klavišy „Win”) +Name[bg]=Windows (без клавиша Win) +Name[bn]=উইণ্ডোস্ স্কীম (উইন্ কী ব্যতীত) +Name[br]=Steuñv Windows (hep stokell Win) +Name[ca]=Esquema Windows (sense la tecla Win) +Name[ca@valencia]=Esquema Windows (sense la tecla Win) +Name[cs]=Schéma Windows (bez klávesy Win) +Name[csb]=Mòtiw Windows (bez klawiszë Win) +Name[cy]=Cynllun Windows (Heb Allwedd Win) +Name[da]=Windows-system (uden Win-tast) +Name[de]=Windows-Design (ohne Windows-Taste) +Name[el]=Σχήμα Windows (Χωρίς πλήκτρο Win) +Name[en_GB]=Windows Scheme (Without Win Key) +Name[eo]=Vindoza aranĝo (sen Vindozoklavo) +Name[es]=Esquema Windows (Sin tecla Win) +Name[et]=Windowsi skeem (ilma Win-klahvita) +Name[eu]=Windows eskema (Win teklarik gabe) +Name[fa]=طرحواره ویندوز( بدون کلید پنجره) +Name[fi]=Windows-skeema (ilman Win-näppäintä) +Name[fr]=Agencement Windows (sans la touche « Win ») +Name[fy]=Windows-skema (sûnder Win-toets) +Name[ga]=Scéim Windows (Gan Eochair Win) +Name[gl]=Esquema de Windows (sen tecla de Windows) +Name[gu]=વિન્ડોઝ પધ્ધતિ (વિન કળ વગર) +Name[he]=ערכת חלונות (בלי מקש Win) +Name[hi]=विंडोज़ प्रसंग (विन कुंजी के बगैर) +Name[hne]=विंडोज प्रसंग (विन कुंजी के बिना) +Name[hr]=Windows shema (bez Windows tipki) +Name[hsb]=Windows-šema (bjez Win-tasty) +Name[hu]=Windows (Win billentyű nélkül) +Name[ia]=Schema Windows (Sin clave Win) +Name[id]=Skema Windows (Tanpa Tombol Win) +Name[is]=Windowsþema (án Win lykils) +Name[it]=Schema Windows (senza tasto Win) +Name[ja]=Windows スキーマ (Win キーなし) +Name[kk]=Windows сұлбасы (Win пернесіз) +Name[km]=គ្រោងការណ៍ វីនដូ (គ្មាន​គ្រាប់ចុច Win) +Name[kn]=ವಿಂಡೋಸ್ ಪದ್ಧತಿ (ವಿನ್ ಕೀಲಿ ರಹಿತ) +Name[ko]=윈도 배열 (윈도 키 사용 안함) +Name[ku]=Şemaya Windowsê (Bêyê Bişkojka Winê) +Name[lt]=Windows schema (be Win klavišo) +Name[lv]=Windows shēma (bez Win taustiņa) +Name[mai]=विंडोज प्रसंग (विन कुँजी केर बगैर) +Name[mk]=Windows-шема (без копчето Win) +Name[ml]=വിന്‍ഡോസ് പദ്ധതി (വിന്‍ കീ ഇല്ലാതെ) +Name[mr]=Windows सुत्रयोजना (विना Win किल्ली) +Name[ms]=Skim Tetingkap (Tanpa Kekunci Win) +Name[nb]=Windows-oppsett (uten Windows-tast) +Name[nds]=Windows-Schema (ahn Windows-Tast) +Name[ne]=विण्डोज योजना (विन कुञ्जी बाहेक) +Name[nl]=Windows-schema (zonder Win-toets) +Name[nn]=Windows-oppsett (utan Windows-tast) +Name[or]=ୱିଣ୍ଡୋ ଯୋଜନା (ୱିନ କି ବିନା) +Name[pa]=Windows ਸਕੀਮ (ਬਿਨਾਂ Win ਸਵਿੱਚ) +Name[pl]=Motyw Windows (bez klawisza Win) +Name[pt]=Esquema do Windows (Sem a Tecla Win) +Name[pt_BR]=Esquema do Windows (sem a tecla Win) +Name[ro]=Schemă Windows (fără tasta Win) +Name[ru]=Windows (без клавиши Win) +Name[se]=Windows-čoakkáldat (Windows-boalu haga) +Name[si]=Windows ක්‍රමය (Win යතුර නොමැතිව) +Name[sk]=Windows schéma (bez klávesu Win) +Name[sl]=Shema Windows (brez tipke Win) +Name[sr]=Виндоузова шема (без тастера Win) +Name[sr@ijekavian]=Виндоузова шема (без тастера Win) +Name[sr@ijekavianlatin]=Windowsova šema (bez tastera Win) +Name[sr@latin]=Windowsova šema (bez tastera Win) +Name[sv]=Windows schema (utan Win-tangent) +Name[ta]=சாளர முறைமை (விண் விசை இல்லாமல்) +Name[te]=Windows స్కీమ్ (విన్ కీ లేకుండా) +Name[tg]=Нақшаи Windows (Бе тугмаи Win) +Name[th]=ใช้แบบของวินโดวส์ (โดยไม่ใช้ปุ่ม Win) +Name[tr]=Windows Şeması (Win Key'siz) +Name[uk]=Схема Windows (без клавіші Win) +Name[uz]=Windows qolipi (Win tugmasi bilan) +Name[uz@cyrillic]=Windows қолипи (Win тугмаси билан) +Name[vi]=Phối hợp của Windows (không có phím Cửa sổ) +Name[wa]=Djeu Windows (sins tape Win) +Name[xh]=Window Yodweliso (Ngaphandle kwe Win key) +Name[x-test]=xxWindows Scheme (Without Win Key)xx +Name[zh_CN]=Windows 方案(无 Win 键) +Name[zh_TW]=Windows 機制(沒有 Win 鍵) +Uses Win Modifier=false + +[klipper][Global Shortcuts] +clipboard_action=none +repeat_action=none +show_klipper_popup=none + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=none +Log Out Without Confirmation=none +Log Out=none +Reboot Without Confirmation=none +Run Command=none +Show System Activity=Ctrl+Alt+Del + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Ctrl+Print +Kill Window=none +Mouse Emulation=none +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=none +Switch to Desktop 11=none +Switch to Desktop 12=none +Switch to Desktop 13=none +Switch to Desktop 14=none +Switch to Desktop 15=none +Switch to Desktop 16=none +Switch to Desktop 1=none +Switch to Desktop 2=none +Switch to Desktop 3=none +Switch to Desktop 4=none +Switch to Desktop 5=none +Switch to Desktop 6=none +Switch to Desktop 7=none +Switch to Desktop 8=none +Switch to Desktop 9=none +Switch to Next Desktop=Alt+Shift+Tab +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=none +Walk Through Desktop List=none +Walk Through Desktops (Reverse)=Ctrl+Alt+Shift+Tab +Walk Through Desktops=Ctrl+Alt+Tab +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+Tab +Window Close=Alt+F4 +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=none +Window Minimize=none +Window Move=none +Window Operations Menu=Alt+Space +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Alt+Print +Window Shade=none +Window to Desktop 10=none +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=none +Window to Desktop 2=none +Window to Desktop 3=none +Window to Desktop 4=none +Window to Desktop 5=none +Window to Desktop 6=none +Window to Desktop 7=none +Window to Desktop 8=none +Window to Desktop 9=none +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/schemes/win4.kksrc b/kcms/keys/schemes/win4.kksrc new file mode 100644 index 0000000000..b28e849938 --- /dev/null +++ b/kcms/keys/schemes/win4.kksrc @@ -0,0 +1,170 @@ +[Settings] +Name=Windows Scheme (With Win Key) +Name[af]=Windows Skema (Met Win Sleutel) +Name[ar]=مخطط ويندوز (مع مفتاح Win) +Name[ast]=Esquema Windows (Con tecla Win) +Name[be]=Схема Windows (з клавішай "Win") +Name[be@latin]=Schiema „Windows” (z klavišaj „Win”) +Name[bg]=Windows (с клавиша Win) +Name[bn]=উইণ্ডোস্ স্কীম (উইন্ কী সমেত) +Name[br]=Steuñv Windows (gant stokell Win) +Name[ca]=Esquema Windows (amb la tecla Win) +Name[ca@valencia]=Esquema Windows (amb la tecla Win) +Name[cs]=Schéma Windows (s klávesou Win) +Name[csb]=Mòtiw Windows (z klawiszą Win) +Name[cy]=Cynllun Windows (Gyda'r Allwedd Win) +Name[da]=Windows-system (med Win-tast) +Name[de]=Windows-Design (mit Windows-Taste) +Name[el]=Σχήμα Windows (με πλήκτρο Win) +Name[en_GB]=Windows Scheme (With Win Key) +Name[eo]=Vindoza aranĝo (kun Vindozoklavo) +Name[es]=Esquema Windows (Con tecla Win) +Name[et]=Windowsi skeem (Win-klahviga) +Name[eu]=Windows eskema (Win teklarekin) +Name[fa]=طرحواره پنجره( با کلید پنجره) +Name[fi]=Windows-skeema (Win-näppäimellä) +Name[fr]=Agencement Windows (avec la touche « Win ») +Name[fy]=Windows-skema (mei Win-toets) +Name[ga]=Scéim Windows (Le hEochair Win) +Name[gl]=Esquema de Windows (con tecla de Windows) +Name[gu]=વિન્ડોઝ પધ્ધતિ (વિન કળ સાથે) +Name[he]=ערכת חלונות (עם מקש Win) +Name[hi]=विंडोज प्रसंग (विन कुंजी समेत) +Name[hne]=विंडोज प्रसंग (विन कुंजी समेत) +Name[hr]=Windows shema (s Windows tipkama) +Name[hsb]=Windows-šema (z Win-tastu) +Name[hu]=Windows (Win billentyűvel) +Name[ia]=Schema Windows (con clave Win) +Name[id]=Skema Windows (Dengan Tombol Win) +Name[is]=Windowsþema (með Win lykli) +Name[it]=Schema Windows (con tasto Win) +Name[ja]=Windows スキーマ (Win キーあり) +Name[ka]=Windows სქემა (Win კლავიშით) +Name[kk]=Windows сұлбасы (Win пернемен) +Name[km]=គ្រោងការណ៍ វីនដូ (មាន​គ្រាប់ចុច Win) +Name[kn]=ವಿಂಡೋಸ್ ಪದ್ಧತಿ (ವಿನ್ ಕೀಲಿ ಸಹಿತ) +Name[ko]=윈도 배열 (윈도 키 사용) +Name[ku]=Şemaya Windowsê (Digel Bişkojka Winê) +Name[lt]=Windows schema (su Win klavišu) +Name[lv]=Windows shēma (ar Win taustiņu) +Name[mai]=विंडोज प्रसंग (विन कुँजी समेत) +Name[mk]=Windows-шема (со копчето Win) +Name[ml]=വിന്‍ഡോസ് പദ്ധതി (വിന്‍ കീയോടൊപ്പം) +Name[mr]=Windows सुत्रयोजना (विन किल्ली सह) +Name[nb]=Windows-oppsett (med Windows-tast) +Name[nds]=Windows-Schema (mit Windows-Tast) +Name[ne]=विण्डोज योजना (विन कुञ्जीसँग) +Name[nl]=Windows-schema (met Win-toets) +Name[nn]=Windows-oppsett (med Windows-tast) +Name[or]=ୱିଣ୍ଡୋ ଯୋଜନା (ୱିନ କି ବିନା) +Name[pa]=Windows ਸਕੀਮ (Win ਸਵਿੱਚ ਨਾਲ) +Name[pl]=Motyw Windows (z klawiszem Win) +Name[pt]=Esquema do Windows (Com a Tecla Win) +Name[pt_BR]=Esquema do Windows (com a tecla Win) +Name[ro]=Schemă Windows (cu tasta Win) +Name[ru]=Windows (поддержка клавиши Win) +Name[se]=Windows-čoakkáldat (Windows-boaluin) +Name[si]=Windows ක්‍රමය (Win යතුර සමඟ) +Name[sk]=Windows schéma (s klávesom Win) +Name[sl]=Shema Windows (s tipko Win) +Name[sr]=Виндоузова шема (са тастером Win) +Name[sr@ijekavian]=Виндоузова шема (са тастером Win) +Name[sr@ijekavianlatin]=Windowsova šema (sa tasterom Win) +Name[sr@latin]=Windowsova šema (sa tasterom Win) +Name[sv]=Windows schema (med Win-tangent) +Name[ta]=சாளர முறைமை (விண் விசையுடன்) +Name[te]=విండోస్ పధకం (విన్ కీ తో) +Name[tg]=Нақшаи Windows (Бо тугмаи Win) +Name[th]=ใช้แบบของวินโดวส์ (ใช้ปุ่ม Win) +Name[tr]=Windows Şeması (Win Key İle) +Name[uk]=Схема Windows (з клавішею Win) +Name[uz]=Windows qolipi (Win tugmasiz) +Name[uz@cyrillic]=Windows қолипи (Win тугмасиз) +Name[vi]=Phối hợp của Windows (có phím Cửa sổ) +Name[wa]=Djeu Windows (avou tape Win) +Name[xh]=Windows Ezingagqibekanga (Nge Win-key) +Name[x-test]=xxWindows Scheme (With Win Key)xx +Name[zh_CN]=Windows 方案(有 Win 键) +Name[zh_TW]=Windows 機制(有 Win 鍵) +Uses Win Modifier=true + +[klipper][Global Shortcuts] +clipboard_action=none +repeat_action=none +show_klipper_popup=none + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=none +Log Out Without Confirmation=none +Log Out=none +Reboot Without Confirmation=none +Run Command=Meta+R +Show System Activity=Ctrl+Alt+Del + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Print +Kill Window=none +Mouse Emulation=none +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Meta+F10 +Switch to Desktop 11=none +Switch to Desktop 12=none +Switch to Desktop 13=none +Switch to Desktop 14=none +Switch to Desktop 15=none +Switch to Desktop 16=none +Switch to Desktop 1=Meta+F1 +Switch to Desktop 2=Meta+F2 +Switch to Desktop 3=Meta+F3 +Switch to Desktop 4=Meta+F4 +Switch to Desktop 5=Meta+F5 +Switch to Desktop 6=Meta+F6 +Switch to Desktop 7=Meta+F7 +Switch to Desktop 8=Meta+F8 +Switch to Desktop 9=Meta+F9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=none +Walk Through Desktop List=none +Walk Through Desktops (Reverse)=Meta+Shift+Tab +Walk Through Desktops=Meta+Tab +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+Tab +Window Close=Alt+F4 +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=none +Window Minimize=none +Window Move=none +Window Operations Menu=Alt+Space +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Alt+Print +Window Shade=none +Window to Desktop 10=none +Window to Desktop 11=none +Window to Desktop 12=none +Window to Desktop 13=none +Window to Desktop 14=none +Window to Desktop 15=none +Window to Desktop 16=none +Window to Desktop 1=none +Window to Desktop 2=none +Window to Desktop 3=none +Window to Desktop 4=none +Window to Desktop 5=none +Window to Desktop 6=none +Window to Desktop 7=none +Window to Desktop 8=none +Window to Desktop 9=none +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/schemes/wm3.kksrc b/kcms/keys/schemes/wm3.kksrc new file mode 100644 index 0000000000..e57093fd13 --- /dev/null +++ b/kcms/keys/schemes/wm3.kksrc @@ -0,0 +1,165 @@ +[Settings] +Name=WindowMaker (3 Modifier Keys) +Name[af]=WindowMaker (3 verandering sleutels) +Name[ar]=صانع النوافذ (3 مفاتيح مغيرة) +Name[ast]=WindowMaker (3 tecles de modificación) +Name[be]=WindowMaker (тры клавішы мадыфікацыі) +Name[be@latin]=Schiema „WindowMaker” (z 3 madyfikacyjnymi klavišami) +Name[bg]=WindowMaker (с 3 модификационни клавиша) +Name[bn]=উইণ্ডো-মেকার (৩-টি মডিফায়ার কী) +Name[ca]=WindowMaker (3 tecles modificadores) +Name[ca@valencia]=WindowMaker (3 tecles modificadores) +Name[cs]=WindowMaker (3 modifikátory) +Name[csb]=WindowMaker (3 klawisze zjinaczi) +Name[cy]=WindowMaker (3 Bysell Addasu) +Name[da]=Windowmaker (3 modifikatortaster) +Name[de]=WindowMaker (3 Sondertasten) +Name[el]=WindowMaker (3 τροποποιητές) +Name[en_GB]=WindowMaker (3 Modifier Keys) +Name[eo]=WindowMaker (3 modifoklavoj) +Name[es]=WindowMaker (3 teclas de modificación) +Name[et]=WindowMaker (3 muuteklahviga) +Name[eu]=WindowMaker (3 tekla modifikatzailekin) +Name[fa]=WindowMaker (۳کلید تغییردهنده) +Name[fi]=WindowMaker (3 muokkausnäppäintä) +Name[fr]=WindowMaker (3 touches de modifications) +Name[fy]=WindowMaker (3 modifikaasjetoetsen) +Name[ga]=WindowMaker (3 Eochair Mhionathraithe) +Name[gl]=WindowMaker (3 teclas modificadoras) +Name[gu]=વિન્ડોમેકર (૩ બદલનાર કળો) +Name[he]=‏WindowMaker (עם 3 מקשים משני מצב) +Name[hi]=विंडोमेकर (3 मॉडीफ़ॉयर कुंजियाँ) +Name[hne]=विंडोमेकर (3 माडीफायर कुंजियाँ) +Name[hr]=WindowMaker (3 modifikatorske tipke) +Name[hsb]=WindowMaker (3 modifikowace tasty) +Name[hu]=WindowMaker (3 módosító billentyű) +Name[ia]=Windowmaker (3 Claves Modificator) +Name[id]=WindowMaker (3 Tombol Pengubah) +Name[is]=WindowMaker (3 breytilyklar) +Name[it]=WindowMaker (3 tasti modificatori) +Name[ja]=WindowMaker (修飾キー 3 個) +Name[ka]=WindowMaker (3 ცვლადი კლავიში) +Name[kk]=WindowMaker (3 түрлендіру перне) +Name[km]=WindowMaker (សោ​​កែប្រែ ៣) +Name[kn]=ವಿಂಡೋಮೇಕರ್ (೩ ಪರಿವರ್ತಕ ಕೀಲಿಗಳು) +Name[ko]=WindowMaker (수정자 키 세 개) +Name[ku]=WindowMaker(3 Bişkojkên Guherker) +Name[lt]=WindowMaker (3 lygio klavišai – modifikatoriai) +Name[lv]=WindowMaker (3 modifikācijas taustiņi) +Name[mai]=विंडोमेकर (3 माडीफायर कुंजीसभ) +Name[mk]=WindowMaker (3 копчиња-модификатори) +Name[ml]=വിന്‍ഡോമേക്കര്‍ (3 മോഡിഫയര്‍ കീകള്‍) +Name[mr]=चौकटमेकर (3 संपादन की) +Name[nb]=WindowMaker (tre valgtaster) +Name[nds]=WindowMaker (3 Sünnertasten) +Name[ne]=विण्डोज निर्माता (३ परिमार्जक कुञ्जी) +Name[nl]=WindowMaker (3 modificatietoetsen) +Name[nn]=WindowMaker (tre valtastar) +Name[or]=WindowMaker (3ଟି ପରିବର୍ତ୍ତକ କି) +Name[pa]=WindowMaker (3 ਸੋਧ ਸਵਿੱਚਾਂ) +Name[pl]=WindowMaker (3 klawisze modyfikatorów) +Name[pt]=WindowMaker (3 Teclas Modificadoras) +Name[pt_BR]=WindowMaker (3 teclas modificadoras) +Name[ro]=WindowMaker (3 modificatori) +Name[ru]=WindowMaker (3 клавиши-модификатора) +Name[se]=WindowMaker (golbma válljenboaluiguin) +Name[si]=කවුළු සැකසීම (3 වෙනස්කම් යතුරු) +Name[sk]=WindowMaker (3 modifikačné klávesy) +Name[sl]=WindowMaker (3 spremenilne tipke) +Name[sr]=Виндоумејкер (три модификаторска тастера) +Name[sr@ijekavian]=Виндоумејкер (три модификаторска тастера) +Name[sr@ijekavianlatin]=WindowMaker (tri modifikatorska tastera) +Name[sr@latin]=WindowMaker (tri modifikatorska tastera) +Name[sv]=Windowmaker (3 väljartangenter) +Name[ta]=WindowMaker (3 Modifier Keys) +Name[te]=విండోమేకర్ (3 సవరణి కీలు) +Name[tg]=WindowMaker (3 тугмаи якҷояшуда) +Name[th]=วินโดว์เมกเกอร์ (ใช้ปุ่มเปลี่ยนหน้าที่ 3ปุ่ม) +Name[tr]=WindowMaker (3 Değiştirici Anahtar) +Name[uk]=WindowMaker (3 клавіші-модифікатори) +Name[vi]=WindowMaker (3 Phím Bổ trợ) +Name[wa]=Djeu WindowMaker (3 tapes modifieuses) +Name[x-test]=xxWindowMaker (3 Modifier Keys)xx +Name[zh_CN]=WindowMaker (三个修饰键) +Name[zh_TW]=WindowMaker(3 個變更鍵) + +[klipper][Global Shortcuts] +clipboard_action=Ctrl+Alt+X +repeat_action=Ctrl+Alt+R +show_klipper_popup=Ctrl+Alt+V + +[krunner][Global Shortcuts] +Halt Without Confirmation=none +Lock Session=Ctrl+Alt+L +Log Out Without Confirmation=none +Log Out=Ctrl+Alt+Del +Reboot Without Confirmation=none +Run Command=Alt+F2 +Show System Activity=Ctrl+Esc + +[kwin][Global Shortcuts] +Desktop Screenshot to Clipboard=Ctrl+Print +Kill Window=Ctrl+Alt+Esc +Mouse Emulation=Alt+F12 +Switch One Desktop Down=none +Switch One Desktop Up=none +Switch One Desktop to the Left=none +Switch One Desktop to the Right=none +Switch to Desktop 10=Alt+Shift+1 +Switch to Desktop 11=Alt+Shift+2 +Switch to Desktop 12=Alt+Shift+3 +Switch to Desktop 13=Alt+Shift+4 +Switch to Desktop 14=Alt+Shift+5 +Switch to Desktop 15=Alt+Shift+6 +Switch to Desktop 16=Alt+Shift+7 +Switch to Desktop 1=Alt+1 +Switch to Desktop 2=Alt+2 +Switch to Desktop 3=Alt+3 +Switch to Desktop 4=Alt+4 +Switch to Desktop 5=Alt+5 +Switch to Desktop 6=Alt+6 +Switch to Desktop 7=Alt+7 +Switch to Desktop 8=Alt+8 +Switch to Desktop 9=Alt+9 +Switch to Next Desktop=none +Switch to Previous Desktop=none +Toggle Window Raise/Lower=none +Walk Through Desktop List (Reverse)=Ctrl+Shift+Tab +Walk Through Desktop List=Ctrl+Tab +Walk Through Desktops (Reverse)=none +Walk Through Desktops=none +Walk Through Windows (Reverse)=Alt+Shift+Tab +Walk Through Windows=Alt+Tab +Window Close=Alt+Esc +Window Lower=none +Window Maximize Horizontal=none +Window Maximize Vertical=none +Window Maximize=none +Window Minimize=none +Window Move=none +Window Operations Menu=Alt+F3 +Window Raise=none +Window Resize=none +Window Screenshot to Clipboard=Alt+Print +Window Shade=none +Window to Desktop 10=Ctrl+Alt+Shift+1 +Window to Desktop 11=Ctrl+Alt+Shift+2 +Window to Desktop 12=Ctrl+Alt+Shift+3 +Window to Desktop 13=Ctrl+Alt+Shift+4 +Window to Desktop 14=Ctrl+Alt+Shift+5 +Window to Desktop 15=Ctrl+Alt+Shift+6 +Window to Desktop 16=Ctrl+Alt+Shift+7 +Window to Desktop 1=Ctrl+Alt+1 +Window to Desktop 2=Ctrl+Alt+2 +Window to Desktop 3=Ctrl+Alt+3 +Window to Desktop 4=Ctrl+Alt+4 +Window to Desktop 5=Ctrl+Alt+5 +Window to Desktop 6=Ctrl+Alt+6 +Window to Desktop 7=Ctrl+Alt+7 +Window to Desktop 8=Ctrl+Alt+8 +Window to Desktop 9=Ctrl+Alt+9 +Window to Next Desktop=none +Window to Previous Desktop=none + +[kxkb][Global Shortcuts] +Switch to Next Keyboard Layout=Ctrl+Alt+K diff --git a/kcms/keys/select_scheme_dialog.cpp b/kcms/keys/select_scheme_dialog.cpp new file mode 100644 index 0000000000..aefb919f2a --- /dev/null +++ b/kcms/keys/select_scheme_dialog.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "select_scheme_dialog.h" +#include "ui_select_scheme_dialog.h" + + +#include "KDialog" +#include "KStandardDirs" +#include +#include +#include + +SelectSchemeDialog::SelectSchemeDialog(QWidget *parent) + : KDialog(parent), + ui(new Ui::SelectSchemeDialog) +{ + m_schemes = KGlobal::dirs()->findAllResources("data", "kcmkeys/*.kksrc"); + + ui->setupUi(this); + setMainWidget(ui->layoutWidget); + + foreach (const QString &res, m_schemes) { + KConfig config(res, KConfig::SimpleConfig); + KConfigGroup group(&config, "Settings"); + QString name = group.readEntry("Name"); + + if (name.isEmpty()) { + name = res; + } + ui->m_schemes->addItem(name); + } + + ui->m_schemes->setCurrentIndex(-1); + + ui->m_url->setMode(KFile::LocalOnly | KFile::ExistingOnly); + + connect(ui->m_schemes, SIGNAL(activated(int)), + this, SLOT(schemeActivated(int))); + connect(ui->m_url->lineEdit(), SIGNAL(textChanged(QString)), + this, SLOT(slotUrlChanged(QString))); + enableButtonOk(false); +} + + +SelectSchemeDialog::~SelectSchemeDialog() +{ + delete ui; +} + +void SelectSchemeDialog::schemeActivated(int index) +{ + ui->m_url->setUrl(QUrl(m_schemes[index])); +} + + +KUrl SelectSchemeDialog::selectedScheme() const +{ + return ui->m_url->url(); +} + +void SelectSchemeDialog::slotUrlChanged(const QString &_text) +{ + enableButtonOk(!_text.isEmpty()); +} + +#include "moc_select_scheme_dialog.cpp" diff --git a/kcms/keys/select_scheme_dialog.h b/kcms/keys/select_scheme_dialog.h new file mode 100644 index 0000000000..215fb30fa5 --- /dev/null +++ b/kcms/keys/select_scheme_dialog.h @@ -0,0 +1,49 @@ +/* + * Copyright 2008 Michael Jansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 SELECT_SCHEME_DIALOG_H +#define SELECT_SCHEME_DIALOG_H + +#include "KDialog" +#include + +namespace Ui +{ +class SelectSchemeDialog; +} + +class SelectSchemeDialog : public KDialog +{ + Q_OBJECT +public: + SelectSchemeDialog(QWidget *parent = 0); + ~SelectSchemeDialog(); + + KUrl selectedScheme() const; + +private Q_SLOTS: + void schemeActivated(int index); + void slotUrlChanged(const QString &); + +private: + Ui::SelectSchemeDialog *ui; + QStringList m_schemes; +}; // SelectSchemeDialog + + + +#endif diff --git a/kcms/keys/select_scheme_dialog.ui b/kcms/keys/select_scheme_dialog.ui new file mode 100644 index 0000000000..0803ad5db7 --- /dev/null +++ b/kcms/keys/select_scheme_dialog.ui @@ -0,0 +1,150 @@ + + + Michael Jansen + SelectSchemeDialog + + + + 0 + 0 + 717 + 224 + + + + Select Shortcut Scheme + + + true + + + + + 32 + 12 + 671 + 71 + + + + + + + + 0 + 50 + + + + Select one of the standard KDE shortcut schemes + + + &Standard scheme: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_schemes + + + + + + + + 0 + 0 + + + + + 0 + 50 + + + + true + + + + + + + + 150 + 0 + + + + + 1 + 0 + + + + + 0 + 50 + + + + Select a shortcut scheme file + + + &Path: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + m_url + + + + + + + + 3 + 0 + + + + + 0 + 50 + + + + *.kksrc + + + Select Shortcut Scheme + + + + + + + + + KComboBox + QComboBox +
    kcombobox.h
    +
    + + KDialog + QDialog +
    kdialog.h
    + 1 +
    + + KUrlRequester + QFrame +
    kurlrequester.h
    +
    +
    + + +
    diff --git a/kcms/kfontinst/AUTHORS b/kcms/kfontinst/AUTHORS new file mode 100644 index 0000000000..afabc4a809 --- /dev/null +++ b/kcms/kfontinst/AUTHORS @@ -0,0 +1 @@ +Craig Drummond diff --git a/kcms/kfontinst/CMakeLists.txt b/kcms/kfontinst/CMakeLists.txt new file mode 100644 index 0000000000..40d394ff89 --- /dev/null +++ b/kcms/kfontinst/CMakeLists.txt @@ -0,0 +1,49 @@ +if (KFI_BUILD_STANDALONE) + cmake_minimum_required(VERSION 2.6.4) + find_package(KDE4 "4.6.0" REQUIRED) + find_package(Qt4 REQUIRED) + find_package(Freetype REQUIRED) + find_package(Fontconfig REQUIRED) + find_package(Strigi REQUIRED) + find_package(X11 REQUIRED) + macro_log_feature(X11_Xft_FOUND "libxft" "X FreeType interface library" "http://www.x.org" FALSE "" "Font installer and font previews") + include(KDE4Defaults) +endif () + +if (X11_Xft_FOUND) + check_include_files(locale.h HAVE_LOCALE_H) + configure_file(config-fontinst.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-fontinst.h) + include_directories( + ${FREETYPE_INCLUDE_DIRS} + ${FONTCONFIG_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/lib + ${CMAKE_CURRENT_BINARY_DIR}/lib + ${CMAKE_CURRENT_SOURCE_DIR}/dbus + ${CMAKE_CURRENT_BINARY_DIR}/dbus + ${CMAKE_CURRENT_SOURCE_DIR}/viewpart + ${CMAKE_CURRENT_SOURCE_DIR}/kcmfontinst + ${CMAKE_CURRENT_BINARY_DIR}/kcmfontinst) + add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) + + set(libkfontinstdbusiface_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/dbus/FontinstIface.cpp) + set(libkfontinstview_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/viewpart/FontPreview.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/viewpart/PreviewSelectAction.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/viewpart/CharTip.cpp ) + set(libkfontinstactionlabel_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/kcmfontinst/ActionLabel.cpp) + set(libkfontinstjobrunner_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/kcmfontinst/JobRunner.cpp + ${libkfontinstactionlabel_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/kcmfontinst/FontsPackage.cpp) + + add_subdirectory( lib ) +# add_subdirectory( dbus ) + add_subdirectory( kcmfontinst ) + add_subdirectory( apps ) + add_subdirectory( kio ) + add_subdirectory( thumbnail ) + add_subdirectory( viewpart ) + + ecm_install_icons( ${ICON_INSTALL_DIR} ) + +endif () diff --git a/kcms/kfontinst/ChangeLog b/kcms/kfontinst/ChangeLog new file mode 100644 index 0000000000..fe87b58aea --- /dev/null +++ b/kcms/kfontinst/ChangeLog @@ -0,0 +1,562 @@ +KDE4.4 +====== +1. Create a dbus daemon for handling font installtion, and have the kcm and ioslave + use this. +2. Use policykit to control installation of system-wide fonts. +3. Merged progress, skip, cancel, and error dialogs used when installing, etc., into + 1 dialog. +4. Simplify layout. +5. Remove simple mode - always use font management mode. +6. When multiple fonts are selected, use a list style preview of all selected fonts. +7. Because of the above, remove the in-line previews from the font list. + +KDE4.3 +====== +1. Dont cache previews to disk. + +KDE4.2 +====== +1. Added zoom controls to font preview. +2. Made viewer application a KUniqueApplication + +KDE3.5 -> KDE4.0 +================ + 1. Enabling/disabling of fonts. + 2. Creation of "Font Groups" + 3. Fonts are now grouped via family name, i.e. shown as: + + Courier [4] + - Times [2] + Regular + Italic + ...where the number in brackets indicates the number of styles. Clicking + on the expand icon (+) will then show the list of styles. + 4. Add ability in font view part to show unicode tables. + 5. Remove all references to Speedo fonts - haven't been supported since + KDE3.3! + 6. Only one view - list view. However, each item now has a small preview. + 7. Xft is now required. + 8. Remove Fontmap creation. + 9. Creation of fonts.dir & fonts.scale will be done via mkfontscale and + mkfontdir. +10. Legacy X is only configured for a folder if it already contains a fonts.dir + file. +11. Font installtion is *much* faster - as config files are now updated after + all fonts are installed, as opposed to every 50 fonts. +12. Folders are no longer added to X's config files - because of 10 above. + The only system config file that will be altered is either + /etc/fonts/local.conf or /etc/fonts/conf.d/00kde.conf (dependant upon + your fontconfig version) +13. When installing font files, install into a sub folder named after the 1st + character. e.g. + wibble.ttf -> ~/.fonts/w/wibble.ttf +14. Better unique names when creating font packages. +15. Use zip and not tar.gz for font packages. +16. Allow import of fonts/package. +17. Allow fonts/package to be installed via konqueror service menu. +18. Better TTC handling. +19. When installing to fonts:/, as non-root, automatically install to fonts:/Personal. + To install to fonts:/System need to explicity copy to fonts:/System. +20. Hide kfontview from KMenu - its only required by kcm, and when cliking on a font. +21. Renamed kcmfontinst to just fontinst. +22. When printing, use external kfontprint app - that way newly installed fonts can + also be printed. +23. When run as non-root, the kcontrol module will have a combo box allowing the user + to select Personal or System fonts. +24. Better bitmap font previews - list of sizes obtained via fontconfig. +25. Regular fonts listed as fonts:/, Regular - e.g. fonts:/Times, Regular +26. Use a kio_font_helper app when accesing fonts:/System - much faster, as kdesu is + not required to be called for each action. +27. Add a "Find Duplicates" tool, that looks for multiple installtions of the same font. + i.e. different locations, or the same location but different filename case + (e.g. times.ttf / times.TTF) + +KDE3.4 -> KDE3.5 +================ +1. When copying a file out of fonts sub-system, copy as filename, or .fonts.tar.gz + in the case of multiple font files mapped to the same font name. + + e.g. Times New Roman -> times.ttf + Helvetica, Bold Oblique-> Hevetica, Bold Oblique.fonts.tar.gz + Which contains: + 75dpi_helvBO10.pcf.gz + 75dpi_helvBO12.pcf.gz + 100dpi_helvBO10.pcf.gz + 100dpi_helvBO12.pcf.gz + ...etc + +2. New mimetype: fonts/package - to cater for the above. +3. Add settings to enable/disable configuring fonts for legacy X, and Ghostscript + (X defaults to true, and Ghostscript defaults to false) +4. Show mime-type in detailed view. +5. Simple font sample printing - but only of installed fonts! +6. Add toggle button to control display of bitmap fonts. + +KDE3.3 -> KDE3.4 +================ +1. Font listing comes from fontconfig. This means that fonts will be grouped, i.e. + previously each size of a bitmap font was shown seperately, now only 1 font + will be displayed which represents all sizes. +2. Only fonts, and not folders (except System and Personal), are now shown. +3. Creation of afms from pfa/pfb and a pfm file. +4. Previews are drawn via Xft - previously FreeType was called directly. +5. New font preview look. +6. No longer dependant upon file extension. +7. Check for FPE of "fontconfig" -> if set, then no need to configure X core fonts. + +KDE3.2 -> KDE3.3 +================ +1. List fonts as "Full Name" -> i.e. "Times New Roman". +2. Preview of bitmap fonts. +3. No fontname-title in thumbnails - as fonts:/ lists the fontnames! +4. When copying to fonts:/ (as non-root) only ask for destination if more than 5 seconds + since previously asked. +5. Add a konqueror service menu "Install" +6. Use FreeType2 for reading Type1 - instead of parsing the pfa/pfb header. +7. FamilyName is now the fonts *real* family name - no adding of style information. +8. Add extra style information (which was previously added to FamilyName) into the XLFD. +9. Consider regular weight to be medium (same as mkfontscale). +10. Default to width=normal, weight=medium if not set. +11. Allow change of preview string. +12. Allow zooming in/out of preview. +13. Waterfall font preview. +14. Use font preview part in the KControl module - less code duplication. +15. Include simple fontviwer app - basically just an application wrapper for the viewpart. + +KDE3.1 -> KDE3.2 +================ +1. Re-designed (yet again...) to be a kio slave. As a user, starting fonts:/ will display + + Personal Lists contents of $HOME/.fonts and $KDEHOME/share/fonts (where previous installer installed to) + Fonts are installed to $HOME/.fonts + + System Lists contents of /usr/local/share/fonts, /usr/share/fonts, and /usr/X11R6/lib/X11/fonts + Fonts are installed to /usr/local/share/fonts (as per FHS) + + To install fonts system wide, just drop onto "System" and root's password will be asked + for. + + As root, fonts:/ will show the same as fonts:/System (but without the System part...) + +2. New kcontrol module that uses fonts:/ +3. Removed: + AFM creation -- only really required (TTF wise) for SO <6.0 + StarOffice configuration (S0 6.0 / OO.o is *much* better anyway) +4. X font server (xfs) - if used - is refreshed by sending a SIGUSR1 instead of + relying on a /etc/init.d/xfs script. This is much more portable. +5. Simple FontView part for konqueror - this is basically a big re-sizable preview of the font. +6. Speed up creation of fonts.dir and fonts.scale - by reading in any existing files, and using the + entries from these instead of loading and testing the font (if listed). +7. Better font preview and thumbnails. +8. Only add a dir to fontpath if fonts.dir has greater than 0 entries! +9. Use /etc/fonts/local.conf as root fontconfig file. +10. Only add dirs to fontconfig if *not* a sub-dir of an existing dir. +11. Ensure that top-level fonts dir is always in fontpath. +12. A Fontmap file is created in each sub dir, which is then combined into 1 top level Fontmap file. + ~/.fonts/Fontmap for normal users, and /etc/fonts/Fontmap for root. +13. Modify /Fontmap to contain: + (/etc/fonts/Fontmap) .runlibfile + ...as this is the system-wide Fontmap file created. As for the per-user, one, hmmm... +14. When a folder is configured, ensure fonts.dir/fonts.scale/Fontmap/.fonts-config-timestamp (SuSE + specific) all have the same timestamp (if they exist). Helps to discover if a folder has been + modified - in which case it needs to be reconfigured (and should happen automatically). +15. Add support for TrueType Collections (.ttc), and OpenType (.otf) fonts. Currently TTC's are only + configured for X - need to also configure GS to see other faces. +16. CID fonts are *not* handled - therefore don't list the X11 CID directory, and don't let users + try to create this. +17. Don't list "encodings" in fonts:/System - and don't allow users to create this. +18. Use XFree86's libfontenc (if found) to read font-encodings. +19. Handle 1bpp glyphs in thumbnail code. +20. Ensure X fontpaths *never* end in "/" - i.e. when write XF86Config, xfs/config, + or fontpaths remove any trailing "/" +21. When adding/removing an unscaled dir from X font path, ensure ":unscaled" is + part of the path! +22. Call fc-cache on top-level dir, not on each dir. +23. Use "~" in Xft config and user X config files -> e.g. /home/user/.fonts -> ~/.fonts +24. Remove top-level dir spec from top-level fontmap, e.g. + + TimesNewRomanPSMT (/home/user/.fonts/wibble/times.ttf); + + ...becomes... + + TimesNewRomanPSMT (wibble/times.ttf); + +25. Add meta-data for AFM files to KFile plugin. + +0.11-> KDE3.1 +============= +1. Re-design of UI - removed "Install From" view. +2. Created a KIO/thumbnail font preview class. +3. Fonts are installed/uninstalled on "Apply". +4. Settings are saved on "Apply". +5. Settings tab simplified - some uneccesary settings removed. +6. Removal of Anti-Alias tab - relevant settings moved to kcmfonts. +7. Add kfile-plugin to display Meta data for fonts. +8. Remove settings wizard. +9. Drop use of internal version numbering - not tagging CVS anyway, so whats the point? +10. DCOP interface. +11. Remember size of main window when run via kcmshell. + +0.10->0.11 (KDE3.0) +=================== +1. Port to KDE3/Qt3. +2. Add support for CUPS's Fontmap. +3. Create backups of system files. +4. When install symbol encoding fonts, set encoding to "glyphs-fontspecific" in XftConfig. +5. When install monospaced fonts, set spacing to mono in XftConfig. +6. When first run (as root) - checks XFree86 config file to see if a font server is being used, if + so then fs/config is used as the config file, and "/etc/rc.d/init.d/xfs restart" is selected as + as the X refresh command. +7. Only install fonts that are useable. +8. Add checkbox to enable overwriting of existing AFMs. +9. Remember open directories in advanced mode. +10. Add support for .Z compressed Bitmap fonts. +11. Read Type1 encodings from .afm files if listed as "array" in pfa/pfb. + +0.10b11->0.10 +============= +1. Version added to KDE CVS. +2. Modified some keyboard shortcuts to remove conflicts. +3. Disable "Touch" and "Delete" folder if top-level X fonts dir is selected. + +0.10b10->0.10b11 (Test version...) +================ +1. Removed "root"/"Modify" and "Help" buttons - this gives more space to font lists, plus when using "root"/"Modify" root's + config files are not being saved. +2. "IsFixedPitch" flag in AFMs produced incorrectly - was outputing "false" for monospaced fonts! +3. Added rounding to AFM metric scaling. +4. When creating AFMs, check that each characters' BBox is within the main BBox - this is a quick fix for wingdings.afm, + which seems to be giving incorrect results. +5. StarOffice 6 / OpenOffice only need AFM files for Type1 fonts - plus no config files need to be altered. Therefore, added the ability to + select which font types AFMs should be created for. +6. Output *all* characters from a font into the AFM file. +7. Fixed a bug with Full/Family name in Speedo fonts. +8. For TrueType, Type1, and Speedo fonts - family name is obtained by using the fonts' FullName, remove FamilyName (read from file), remove + any weight, width, or italic designation, and re-add FamilyName. (This is because some fonts are named + , and was previously being lost). +9. When adding encodings to lists, check that they aren't alredy inserted. + +0.10b9->0.10b10 (Test version...) +=============== +1. Fixed a problem with non-enabled install button in basic mode - again, thanks to Hardy Griech for spotting this. + +0.10b8->0.10b9 (Test version...) +============== + +*** NOTE +*** Please remove any Kfontinst generated StarOffice psstd.fonts and Ghostscript Fontmap output before using this version + +1. StarOffice psstd.fonts generated output is no longer marked line-by line, instead it is marked as a section, e.g. + + # kfontinst /usr/X11R6/lib/X11/fonts/TrueType + + # kfontinst /usr/X11R6/lib/X11/fonts/TrueType + + ...Likewise for Ghostscript's Fontmap + +2. Limited generated StarOffice psstd.fonts lines to 126 characters, and lines longher than this will not be output. It appears + as if this is the max line len StarOffice will accept - thanks to Hardy Griech for discovering this. +3. Fixed a bug where a static pointer was not reset to NULL when module was unloaded. +4. When chekcing ps-fonts, I was looking for the string "%!PS-Adbobe", however the hershey fonts just has "%!FontType" - therefore + I've change the code to just look for "%!" +5. For pcf fonts, look for FAMILY as well as FAMILY_NAME +6. Construct name from xlfd for bitmap fonts where can't get seperate components + +0.10b7->0.10b8 (Test version...) +============== + +*** NOTE +*** Please remove any Kfontinst generated Ghostscript and/or StarOffice output before using this version + +1. Forgot to extract foundry from bitmap fonts - however, changed bitmap Xlfd creation, see below. +2. Extract Xlfd from Bitmap fonts directly - not all fonts have each seperate component available. Thanks to Claudio Bandaloukas + for helping me discover the various bugs with Bitmap output. +3. When displaying bitmap details, if individual entries (family, point size, etc) can't be read, then the + Xlfd will be displayed. +4. Ghostscript & StarOffice include guards changed from "kfontinst" to "kfi" -- this will *require" removing of any previous output! +5. Shortened generated TrueType foundry fields - to help with StarOffice + +0.10b6->0.10b7 (Test version...) +============== +1. Fixed a bug with string-to-width conversion for Type1 and bitmap fonts +2. Fixed some compile bugs if no Xft.h found +3. Remove any fonts.alias when deleting a dir +4. When try to open Type1 or Speedo fonts, check magic numbers - for Speedo check char[0]=='D' or 'd', char[1]==num, char[2]=='.', and char[3]==num + +0.10b5->0.10b6 (Test version...) +============== +1. Fonts with "Normal" weight now installed as "Medium" +2. Added support for "Oblique" in xlfd +3. Check is performed to see if destination is writeable before enabling "Install" button, likewise for the "Remove" button. + +0.10b4->0.10b5 (Test version...) +============== +1. Forgot to reset the made-changes state of XftConfig when saved! +2. Add a validator to math & edit line-edits to disallow usage of double-quotes & tabs +3. Select correct default entries for field-name combos when adding an XftRule. +4. Removed check for number of items in match list, as these are not always required (such as for the sub-pixel hinting + rule.) +5. When setting rgba - use symbolic name - previously always setting to 0! +6. Modified help a little +7. Reduced Advanced mode list-view treeStepSize to 10 pixels (from default of 20), this makes it easier for browsing + /usr/X11R6/lib/X11/fonts/etc... +8. Fixed bug where could not remove Xft exclude range! +9. Fixed a bug where uninstalled items could cause duplicates in "Install from" list. +10. Renamed the "Configure System" button to "Apply" - this should make the neccessity of the option more obvious. +11. Fixed display of uninstall folder. +12. Added "include" and "includeif" directives from XftConfig to editor. + +0.10b3->0.10b4 (Test version...) +============== + +*** NOTE +*** Please delete your existing ~/.kde/share/config/kfontinstrc -or- ~/.kde2/share/config/kfontinstrc file +*** before using this version + +1. Added support for X font server config files. +2. Show "unscaled" directories in italic. +3. Abilty to set directories as scaled/unscaled. +4. Modified GUI slightly so that it works beter with Liquid style. +5. Added chack to make sure XftConfig file exists before trying to parse. +6. Advanced editing of XftConfig. +7. Added help on XftConfig - from Danny Tholen (obiwan@mailmij.org) +8. Removed some memory leaks +10. Default folders changed for non-root users. KFontinst will now (upon initial start-up) select the following: + + X fonts dir: $KDEHOME/share/fonts + XConfig file: $KDEHOME/share/fonts/fontpaths + XftConfig file: $HOME/.xftconfig + Fontmap file: $KDEHOME/share/fonts/Fontmap + + ...This should make it possible for users to install fonts without being root. However, problems may arrise when + configuring StarOffice - as this requires some other files to be modified, which won't be possible if SO has been installed + by root. + + ...Also to accomplish this, some changes are needed to 'startkde' - see file README.startkde + +11. Because of the above, when started as non-root, KFontinst will create Type1 and TrueType sub-folders in + $KDEHOME/share/fonts - if they do not already exist. +12. Moved XftConfig stuff from a sub-page of settings tab into its own tab. +13. Added question dialog if module is unloaded before system has been configured. +14. Added ability to "touch" a X font folder - marking it as being modified, so that a re-configure of the that folder + can be done in order to create AFMs, modify encoding, etc. + +0.10b2->0.10b3 (Test version...) +============== +1. When locating Ghostscript's Fontmap file, sub-directories (up to a level of 4) are searched - this allows + for the possiblity of users using a different version of Ghostscript. +2. Create a fonts.scale as well as fonts.dir - just incase another program runs mkfontdir. +3. Fixed an error when creating AFMs for some symbol-encoded fonts. +4. Re-worded SettingsWizard "Folders/Files" tab. +5. Added a checkbox to Ghostscript configuration. +6. Added support for XftConfig. +7. Added/fixed support of Type1 fonts with no FullName or FamilyName fields - such as the hershey fonts. +8. Fixed some bugs when configuring with --enable-final. +9. Basic html help added. + +0.10b1->0.10b2 (Test version...) +============== +1. Minor compile error (struct declared as private, but used elsewhere!) + +0.9.2->0.10b1 (Test version...) +============= +1. Almost a complete re-write, +2. Handles Speedo, and Bitmap fonts +3. fonts.dir & encodings.dir are now created internally - no need for ttmkfdir +4. Re-design of GUI. +5. Advanced mode where X11 folder structure is displayed and all font types may be installed - and a Basic + mode where the X11 folder structure is hidden, and only TrueType and Type1 fonts may be installed. +6. Settings wizard. +7. Application is now a kcontrol module. +8. Complete X11 fonts directory structure is now managed - no need for seperate 'Managed' directory. +9. X11.PS is no longer created, instead the StarOffice printer file (*.PS) is now modified. +10. Ported to FreeType2. +11. Support more encodings - encodings combos now list standard encodings as well as those read from + .enc(.gz) files. +12. Internal AMF creator for Type1 and TrueType fonts - ttf2pt1 and pf2afm.ps are no longer used/supplied. +13. Removed the 'Process AFMs' & 'Delete AFMs' options - all AFMs are created be KFontinst, therefore they + should be OK for StarOffice and AbiWord. +14. If a writable XF86Config file is found - then complete folders may be installed, and folders in the X11 + directory may be uninstalled or disabled (i.e. the folder is not deleted, but it's entry is removed from + the XF86Config file). +15. No longer supply .enc files with KFontinst - they should be provided by the distro. + +0.9.1->0.9.2 +============ +1. Removed a bug where the "Configure System" menu entry was always disabled! +2. Spelling error in Settings dialog. +3. t1lib has problems with some of the fonts supplied with Adobe acrobat - therefore, if t1lib fails to load the + font, then KFontinst itself will try to read the header information (although no preview will be available, + everything else should still work). +4. Fixed multiple installing of programs in other/ directory. For instance KFontinst's version of ttmkfdir + was being installed into $(PREFIX) (usually /usr/bin) as well as $(KDE_DATADIR)/kfontinst - this was incorrect + as KFontinst will only use the version in $(KDE_DATADIR)/kfontinst, and it was possible that a previous version + of ttmkfdir (such as that supplied with XFree86) would have been overwritten. +5. Fixed bug where the user was allowed to select (and subsequently install) fonts which could not be loaded correctly. +6. Added the ability to enter a custom preview string. + +0.9->0.9.1 +========== +1. Fixed a few compile errors. +2. Fix to html formatting error. +3. Fixed a ./configure error if t1lib was not found (the string NO was being used as the + librarary name, instead of an empty string!) +4. Modified the reading of Type1 header information. + +0.8.3->0.9 +========== +1. Converted to KDE2. +2. Rearranged this file! +3. Removed command line interface - KDE2's command line stuff is way different! +4. Re-created dialogs with Qt designer. +5. Removed ProgressDialog, and replaced with a progress bar on a new statusbar. +6. Modified configure script to check for FreeType & t1lib. +7. If an encoding (not unicode) is selected, then the .enc file is copied to the X11 fonts directory. +8. As with the .enc files, the StarOffice .xpp files are also copied, and no longer just sym linked. +9. Removed enabling/disabing of Configure System button. +10. Fontmap.X11 is no longer created, instead the real Fontmap file itself is modified. + +0.8.2->0.8.3 +============ +1. Modified 'kfontinst.kdelnk' so that kdesu is now used - so that a user will automatically be prompted + for the root password. +2. Modified dialogs to use the KDE caption ("Font Installer") instead of the app name ("kfontinst") +3. Corrected size of Configure dialog. +4. Fixed a minor bug where if all fonts were uninstalled, the 'Configure System' button was disabled - therefore not + allowing you to activate the changes! +5. Added a command line interface. (type 'kfontinst --help' for details) +6. Added option to automatically fix TTF postscript names upon install. + +0.8.1->0.8.2 +============ +1. Fixed a bug which always had SO configuration disabled! +2. Fixed a bug when selecting Unicode encoding. +3. Changed "Fonts/Uninstalled" menu entry to "Fonts/Disk" +4. Added keyboard short-cuts to dialogs + +0.8->0.8.1 +========== +1. Fixed a bug where X configuration would fail if no TT fonts present. +2. If no fonts are installed, then the system configuration button/menu-entry is now disabled. +3. Changed menu structure to add 'Fonts' menu. + +0.7.4->0.8 +========== +1. Changed location of StarOffice stuf from /xp3 to just + -- As StarOffice 5.2 has 'xp3' within a 'share' sub-dir. +2. Changed structure of config file to be more modular. +3. Modified internal code structure to allow easier additon of extra apps to be configured. (NOTE: If any + apps need to be configured, then I'll also [later on] modify the Settings & Configure dialogs to + accomodate these.) +4. Because of 3, added a 'StarOffice' check to the settings dialog. If this is not seleted, then no check + is performed to make sure the SO dir is OK - and the option to config SO is diabled on the config dialog. +5. Added check when installing font to make sure that it's not already installed. + +0.7.3->0.7.4 +============ +1. Changed location of Fontmap.X11 -- from /lib/Fontmap.X11 to + /Fontmap.X11. As it seems some ghostscript installations don't + have the 'lib' sub directory. +2. Improved the documentation a little - added a FAQ section + +0.7.2->0.7.3 +============ +1. Very minor bug fix. + +0.7.1->0.7.2 +============ +1. Added more detailed error messages when system configuration fails. + +0.7->0.7.1 +========== +1. Removed lots of debug info from ttf2pt1, and afm.pl -- this should drastically speed up afm creation. +2. Modified ttf2pt1 to accept a parameter to just create .afm files +3. Added option to modify a .afm file when installing. +4. Added "Unicode" to list of encodings that can be used. +5. Removed kfontinst-cp1252.enc, kfontinst-cp1252.xpp -- these were hacks anyway, and seing as Qt2 is going to + support cp1252 by a hard-coded codec, there's no real point... +6. Rearranged the Configure System dialog - so that Force AFM regeneration is grouped next to the Generate AFMs option. +7. Encoding files now stored in /share/apps/kfontinst/Encodings + +0.6.1->0.7 +========== +1. Modified ttmkfdir & ttf2pt1 to allow usage of X11 style font re-encoding files. +2. Because .enc files are now used by kfontinst, removed the possibility of using gzipped encodings. +3. Added the ability to delete an installed font's .afm file. +4. Fixed a bug in the TtfPsNameFixer class - this would cause ttf2pt1 to creash when accessing a modified font! +5. Font encodings are now stored in /share/x11encodings +6. Removed the reencode shell script, as the encodng is all done by ttmkfdir. +7. Removed xfinst shell script - handled internally. +8. Supplied a kfontinst-cp1252 encoding - with the ugly single-quotes normaly found in .ttf files remapped to + the nice looking ones. +9. Added functionality, when configuring StarOffice, to select an appropriate xprinter.prolog for the selected + encoding (if one exists)... + +0.6->0.6.1 +========== +1. Fixed a display bug in the 'Un/Exclude from StarOffice" options. + +0.5->0.6 +======== +1. Added the ability to 'fix' the postscript names in a ttf file. +2. Fixed some missing changes to help files. + +0.4->0.5 +======== +1. Discovered a patch that modifies StarOffice's xprinter.prolog so that font's don't need to be modified + to use the microsoft cp1252 enocding scheme. (Previosuly the PS output from StarOffice would not print + OK with ghostscript - when using extra characters - unless the .ttf file was modified.) +2. Because of 1, removed the abilty to modify a TrueType font's internal charactermap - this was a hack anyway. +3. xfinst now uses mkfontdir to create encodings.dir - instead of kfontinst's install procedure copying a standard + one in (this didn't actually work...) +4. As kfontinst no longer reads the .enc files themselves, added the ability to use .enc.gz files as well + when selecting an encoding for X. +5. Re-wrote xfinst & reencode to be plain 'sh' scripts, as opposed to 'tcsh' scripts. + +0.3->0.4 +======== +1. All X fonts will now be placed with in a directory - "Managed" - this makes things easier for + AbiWord, and maybe others. +2. encodings.dir & Encodings/ will now be placed within this new "Managed" dir. +3. Only 1 StarOffice .PS file will be created - X11.PS +4. Only 1 Fontmap will be created - Fontmap.X11 - and this will be placed within + /lib +5. Because of 4, an option has been added to the Settings dialog to specify the location of + Ghostscript. +6. Because of 1, removed the font option from the Configure dialog. +7. Fixed an error with getting PS name from TT font - PS names are not allowed to have spaces, but in + fences.ttf it does. FontEngine.cpp will now check for, and fix, this - using the same 'algorithm' as that + of ttf2pt1 (which means the names will tie up with those in the .afm files). +8. Added some improvements to control of dialogs. + +0.2.1->0.3 +========== +1. Reverted back to naming .afm files .afm - and renaming any conflicting fonts. +2. Speeded up copying of files - by copying preview bitmap as opposed to regenerating it! +3. Removed need for FontMetrics directory - .afm files now placed within TrueType or Type1 dir, + and sym links are produced for StarOffice. + + 1. & 3. should now make things easier for AbiWord. + +4. Fixed output of Fontmap so that "URW Gothic" will be aliased as "UrwGothic-Roman" (etc.) as + this is what Qt will output. +5. Added more processing of .afm files - this makes them OK for AbiWord. + +0.2->0.2.1 +========== +1. Modified start-up progress dailog, and added progress dialogs to main window when scanning + fonts. These will only appear if numTTfonts>X || numT1fonts>Y + +0.1->0.2 +======== +1. Combined views of installed TrueType and Type1 fonts into 1 list. +2. When uninstalling a font, can now move the font to another directory - or delete. +3. Used t1lib so that Type1 fonts can also be previewed. +4. Changed Fontmap creator to dynamically allocate memory for each font-category. +5. .afm files are now named as ..afm - this removes the need + for renaming the .afm file if there exists Type1 and TrueType fonts with the same + fontname. +6. Removed the re-scanning of the install directories whenever a font is added. +7. Added support for extra Type1 font weights. +8. Added a start-up screen to inform the user that the installed/disk fonts are being scanned. +9. When exiting, confirmation is now only asked if the system has been changed and not + reconfigured. diff --git a/kcms/kfontinst/Messages.sh b/kcms/kfontinst/Messages.sh new file mode 100644 index 0000000000..0634d49b0a --- /dev/null +++ b/kcms/kfontinst/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name \*.rc` >> rc.cpp +$XGETTEXT rc.cpp */*.cpp */*.h -o $podir/kfontinst.pot +rm -f rc.cpp diff --git a/kcms/kfontinst/apps/CMakeLists.txt b/kcms/kfontinst/apps/CMakeLists.txt new file mode 100644 index 0000000000..5519e87442 --- /dev/null +++ b/kcms/kfontinst/apps/CMakeLists.txt @@ -0,0 +1,51 @@ +include_directories( + ${kcms_SOURCE_DIR}/kfontinst/kcmfontinst/ + ${kcms_SOURCE_DIR}/kfontinst/viewpart/ + ${CMAKE_CURRENT_BINARY_DIR} + ) + +set(kfontinst_bin_SRCS ${libkfontinstjobrunner_SRCS} ${libkfontinstdbusiface_SRCS} Installer.cpp ) +# qt5_add_dbus_interface(kfontinst_bin_SRCS ../dbus/org.kde.fontinst.xml FontInstInterfaceBase) + +set(kfontprint_bin_SRCS ${libkfontinstactionlabel_SRCS} Printer.cpp ) +set(kfontview_bin_SRCS Viewer.cpp ) + +add_executable(kfontinst_bin ${kfontinst_bin_SRCS}) +add_executable(kfontprint_bin ${kfontprint_bin_SRCS}) +add_executable(kfontview_bin ${kfontview_bin_SRCS}) + +set_target_properties(kfontinst_bin PROPERTIES OUTPUT_NAME kfontinst) +set_target_properties(kfontprint_bin PROPERTIES OUTPUT_NAME kfontprint) +set_target_properties(kfontview_bin PROPERTIES OUTPUT_NAME kfontview) + +target_link_libraries(kfontinst_bin + Qt5::X11Extras + KF5::Archive + KF5::IconThemes + KF5::KIOCore + KF5::KIOWidgets + KF5::XmlGui + KF5::KDE4Support + ${X11_X11_LIB} + kfontinst +) +target_link_libraries(kfontprint_bin + Qt5::PrintSupport + KF5::IconThemes + KF5::KDE4Support + ${X11_X11_LIB} + ${FREETYPE_LIBRARIES} + kfontinstui + kfontinst +) +target_link_libraries(kfontview_bin KF5::Parts KF5::XmlGui kfontinstui kfontinst ) + +install(TARGETS kfontinst_bin ${INSTALL_TARGETS_DEFAULT_ARGS} ) +install(TARGETS kfontprint_bin DESTINATION ${LIBEXEC_INSTALL_DIR} ) +install(TARGETS kfontview_bin ${INSTALL_TARGETS_DEFAULT_ARGS} ) +install(FILES kfontviewui.rc DESTINATION ${DATA_INSTALL_DIR}/kfontview ) +install(PROGRAMS kfontview.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) +install(FILES installfont.desktop DESTINATION +${SERVICES_INSTALL_DIR}/ServiceMenus ) + +ecm_install_icons( ${ICON_INSTALL_DIR} ) diff --git a/kcms/kfontinst/apps/CreateParent.h b/kcms/kfontinst/apps/CreateParent.h new file mode 100644 index 0000000000..f42158ee9e --- /dev/null +++ b/kcms/kfontinst/apps/CreateParent.h @@ -0,0 +1,73 @@ +#ifndef __CREATE_PARENT_H__ +#define __CREATE_PARENT_H__ + +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include + +// +// *Very* hacky way to get some KDE dialogs to appear to be transient +// for 'xid' +// +// Create's a QWidget with size 0/0 and no border, makes this transient +// for xid, and all other widgets can use this as their parent... +static QWidget * createParent(int xid) +{ + if(!xid) + return NULL; + + QWidget *parent=new QWidget(NULL, Qt::FramelessWindowHint); + + parent->resize(1, 1); + parent->show(); + + XWindowAttributes attr; + int rx, ry; + Window junkwin; + + XSetTransientForHint(QX11Info::display(), parent->winId(), xid); + if(XGetWindowAttributes(QX11Info::display(), xid, &attr)) + { + XTranslateCoordinates(QX11Info::display(), xid, attr.root, + -attr.border_width, -16, + &rx, &ry, &junkwin); + + rx=(rx+(attr.width/2)); + if(rx<0) + rx=0; + ry=(ry+(attr.height/2)); + if(ry<0) + ry=0; + parent->move(rx, ry); + } + parent->setWindowOpacity(0); + parent->setWindowTitle(QLatin1String("KFI")); + + return parent; +} + +#endif diff --git a/kcms/kfontinst/apps/Installer.cpp b/kcms/kfontinst/apps/Installer.cpp new file mode 100644 index 0000000000..a10a6814b7 --- /dev/null +++ b/kcms/kfontinst/apps/Installer.cpp @@ -0,0 +1,153 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "Installer.h" +#include "Misc.h" +#include "FontsPackage.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "JobRunner.h" +#include "CreateParent.h" + +namespace KFI +{ + +int CInstaller::install(const QSet &urls) +{ + QSet::ConstIterator it(urls.begin()), + end(urls.end()); + bool sysInstall(false); + CJobRunner *jobRunner=new CJobRunner(itsParent); + + CJobRunner::startDbusService(); + + if(!Misc::root()) + { + switch(KMessageBox::questionYesNoCancel(itsParent, + i18n("Do you wish to install the font(s) for personal use " + "(only available to you), or " + "system-wide (available to all users)?"), + i18n("Where to Install"), KGuiItem(i18n(KFI_KIO_FONTS_USER)), + KGuiItem(i18n(KFI_KIO_FONTS_SYS)))) + { + case KMessageBox::No: + sysInstall=true; + break; + case KMessageBox::Cancel: + return -1; + default: + break; + } + } + + QSet instUrls; + + for(; it!=end; ++it) + { + KUrl local(KIO::NetAccess::mostLocalUrl(*it, NULL)); + bool package(false); + + if(local.isLocalFile()) + { + QString localFile(local.toLocalFile()); + + if(Misc::isPackage(localFile)) + { + instUrls+=FontsPackage::extract(localFile, &itsTempDir); + package=true; + } + } + if(!package) + { + KUrl::List associatedUrls; + + CJobRunner::getAssociatedUrls(*it, associatedUrls, false, itsParent); + instUrls.insert(*it); + + KUrl::List::Iterator aIt(associatedUrls.begin()), + aEnd(associatedUrls.end()); + + for(; aIt!=aEnd; ++aIt) + instUrls.insert(*aIt); + } + } + + if(instUrls.count()) + { + CJobRunner::ItemList list; + QSet::ConstIterator it(instUrls.begin()), + end(instUrls.end()); + + for(; it!=end; ++it) + list.append(*it); + + return jobRunner->exec(CJobRunner::CMD_INSTALL, list, Misc::root() || sysInstall); + } + else + return -1; +} + +CInstaller::~CInstaller() +{ + delete itsTempDir; +} + +} + +static K4AboutData aboutData("kfontinst", KFI_CATALOGUE, ki18n("Font Installer"), "1.0", ki18n("Simple font installer"), + K4AboutData::License_GPL, ki18n("(C) Craig Drummond, 2007")); + +int main(int argc, char **argv) +{ + KCmdLineArgs::init(argc, argv, &aboutData); + + KCmdLineOptions options; + options.add("embed ", ki18n("Makes the dialog transient for an X app specified by winid")); + options.add("+[URL]", ki18n("URL to install")); + KCmdLineArgs::addCmdLineOptions(options); + + QSet urls; + KCmdLineArgs *args(KCmdLineArgs::parsedArgs()); + + for(int i=0; i < args->count(); i++) + urls.insert(args->url(i)); + + if(urls.count()) + { + + KApplication app; + QString opt(args->getOption("embed")); + KFI::CInstaller inst(createParent(opt.size() ? opt.toInt(0, 16) : 0)); + + return inst.install(urls); + } + + return -1; +} diff --git a/kcms/kfontinst/apps/Installer.h b/kcms/kfontinst/apps/Installer.h new file mode 100644 index 0000000000..f259491d69 --- /dev/null +++ b/kcms/kfontinst/apps/Installer.h @@ -0,0 +1,53 @@ +#ifndef __INSTALLER_H__ +#define __INSTALLER_H__ + +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include + +class QWidget; +class KTempDir; + +namespace KFI +{ +class CInstaller +{ + public: + + CInstaller(QWidget *p) + : itsParent(p), itsTempDir(NULL) { } + ~CInstaller(); + + int install(const QSet &urls); + + private: + + QWidget *itsParent; + KTempDir *itsTempDir; +}; + +} + +#endif diff --git a/kcms/kfontinst/apps/Printer.cpp b/kcms/kfontinst/apps/Printer.cpp new file mode 100644 index 0000000000..1ec6f11e6e --- /dev/null +++ b/kcms/kfontinst/apps/Printer.cpp @@ -0,0 +1,495 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "config-fontinst.h" +#include "Printer.h" +#include "FcEngine.h" +#include "ActionLabel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#include +#include +#include FT_FREETYPE_H +#endif + +#ifdef HAVE_LOCALE_H +#include +#endif +#include "CreateParent.h" + +// Enable the following to allow printing of non-installed fonts. Does not seem to work :-( +//#define KFI_PRINT_APP_FONTS + +using namespace KFI; + +static const int constMarginLineBefore=1; +static const int constMarginLineAfter=2; +static const int constMarginFont=4; + +inline bool sufficientSpace(int y, int pageHeight, const QFontMetrics &fm) +{ + return (y+constMarginFont+fm.height())fontMetrics().height(), + required=titleFontHeight+constMarginLineBefore+constMarginLineAfter; + + for(unsigned int s=0; sizes[s]; ++s) + { + font.setPointSize(sizes[s]); + required+=QFontMetrics(font, painter->device()).height(); + if(sizes[s+1]) + required+=constMarginFont; + } + + if(0==size) + { + font.setPointSize(CFcEngine::constDefaultAlphaSize); + int fontHeight=QFontMetrics(font, painter->device()).height(); + + required+=(3*(constMarginFont+fontHeight))+ + constMarginLineBefore+constMarginLineAfter; + } + return (y+required)num_charmaps; ++cmap) + if(face->charmaps[cmap] && FT_ENCODING_ADOBE_CUSTOM==face->charmaps[cmap]->encoding) + { + FT_Select_Charmap(face, FT_ENCODING_ADOBE_CUSTOM); + break; + } + + for(unsigned int i=1; i<65535; ++i) + if(FT_Get_Char_Index(face, i)) + { + newStr+=QChar(i); + if(newStr.length()>255) + break; + } + + return newStr; +} + +static QString usableStr(FT_Face face, const QString &str) +{ + unsigned int slen=str.length(), + ch; + QString newStr; + + for(ch=0; ch &items, int size, QObject *parent) + : QThread(parent) + , itsPrinter(printer) + , itsItems(items) + , itsSize(size) + , itsCancelled(false) +{ +} + +CPrintThread::~CPrintThread() +{ +} + +void CPrintThread::cancel() +{ + itsCancelled=true; +} + +void CPrintThread::run() +{ + QPainter painter; + QFont sans("sans", 12, QFont::Bold); + bool changedFontEmbeddingSetting(false); + QString str(CFcEngine(false).getPreviewString()); + + if(!itsPrinter->fontEmbeddingEnabled()) + { + itsPrinter->setFontEmbeddingEnabled(true); + changedFontEmbeddingSetting=true; + } + + itsPrinter->setResolution(72); + painter.begin(itsPrinter); + + int pageWidth=painter.device()->width(), + pageHeight=painter.device()->height(), + y=0, + oneSize[2]={itsSize, 0}; + const int *sizes=oneSize; + bool firstFont(true); + + if(0==itsSize) + sizes=CFcEngine::constScalableSizes; + + painter.setClipping(true); + painter.setClipRect(0, 0, pageWidth, pageHeight); + + QList::ConstIterator it(itsItems.constBegin()), + end(itsItems.constEnd()); + + for(int i=0; it!=end && !itsCancelled; ++it, ++i) + { + QString name(FC::createName((*it).family, (*it).styleInfo)); + emit progress(i, name); + + unsigned int s=0; + QFont font; + +#ifdef KFI_PRINT_APP_FONTS + QString family; + + if(-1!=appFont[(*it).family]) + { + family=QFontDatabase::applicationFontFamilies(appFont[(*it).family]).first(); + font=QFont(family); + } +#else + font=CFcEngine::getQFont((*it).family, (*it).styleInfo, CFcEngine::constDefaultAlphaSize); +#endif + painter.setFont(sans); + + if(!firstFont && !sufficientSpace(y, &painter, font, sizes, pageHeight, itsSize)) + { + itsPrinter->newPage(); + y=0; + } + painter.setFont(sans); + y+=painter.fontMetrics().height(); + painter.drawText(0, y, name); + + y+=constMarginLineBefore; + painter.drawLine(0, y, pageWidth, y); + y+=constMarginLineAfter; + + bool onlyDrawChars=false; + Qt::TextElideMode em=Qt::LeftToRight==QApplication::layoutDirection() ? Qt::ElideRight : Qt::ElideLeft; + + if(0==itsSize) + { + font.setPointSize(CFcEngine::constDefaultAlphaSize); + painter.setFont(font); + + QFontMetrics fm(font, painter.device()); + bool lc=hasStr(font, CFcEngine::getLowercaseLetters()), + uc=hasStr(font, CFcEngine::getUppercaseLetters()); + + onlyDrawChars=!lc && !uc; + + if(lc || uc) + y+=CFcEngine::constDefaultAlphaSize; + + if(lc) + { + painter.drawText(0, y, fm.elidedText(CFcEngine::getLowercaseLetters(), em, pageWidth)); + y+=constMarginFont+CFcEngine::constDefaultAlphaSize; + } + + if(uc) + { + painter.drawText(0, y, fm.elidedText(CFcEngine::getUppercaseLetters(), em, pageWidth)); + y+=constMarginFont+CFcEngine::constDefaultAlphaSize; + } + + if(lc || uc) + { + QString validPunc(usableStr(font, CFcEngine::getPunctuation())); + if(validPunc.length()>=(CFcEngine::getPunctuation().length()/2)) + { + painter.drawText(0, y, fm.elidedText(CFcEngine::getPunctuation(), em, pageWidth)); + y+=constMarginFont+constMarginLineBefore; + } + painter.drawLine(0, y, pageWidth, y); + y+=constMarginLineAfter; + } + } + + for(; sizes[s]; ++s) + { + y+=sizes[s]; + font.setPointSize(sizes[s]); + painter.setFont(font); + + QFontMetrics fm(font, painter.device()); + + if(sufficientSpace(y, pageHeight, fm)) + { + painter.drawText(0, y, fm.elidedText(previewString(font, str, onlyDrawChars), em, pageWidth)); + if(sizes[s+1]) + y+=constMarginFont; + } + else + break; + } + y+=(s<1 || sizes[s-1]<25 ? 14 : 28); + firstFont=false; + } + emit progress(itsItems.count(), QString()); + painter.end(); + + // + // Did we change the users font settings? If so, reset to their previous values... + if(changedFontEmbeddingSetting) + itsPrinter->setFontEmbeddingEnabled(false); +} + +CPrinter::CPrinter(QWidget *parent) + : KDialog(parent) +{ + setCaption(i18n("Print")); + setButtons(Cancel); + + QFrame *page = new QFrame(this); + QGridLayout *layout=new QGridLayout(page); + layout->setMargin(KDialog::marginHint()); + layout->setSpacing(KDialog::spacingHint()); + itsStatusLabel=new QLabel(page); + itsProgress=new QProgressBar(page); + layout->addWidget(itsActionLabel = new CActionLabel(this), 0, 0, 2, 1); + layout->addWidget(itsStatusLabel, 0, 1); + layout->addWidget(itsProgress, 1, 1); + itsProgress->setRange(0, 100); + layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 2, 0); + setMainWidget(page); + setMinimumSize(420, 80); +} + +CPrinter::~CPrinter() +{ +} + +void CPrinter::print(const QList &items, int size) +{ + #ifdef HAVE_LOCALE_H + char *oldLocale=setlocale(LC_NUMERIC, "C"); + #endif + + QPrinter printer; + QPrintDialog *dialog = new QPrintDialog(&printer, parentWidget()); + + if(dialog->exec()) + { + CPrintThread *thread = new CPrintThread(&printer, items, size, this); + + itsProgress->setRange(0, items.count()); + itsProgress->setValue(0); + progress(0, QString()); + connect(thread, SIGNAL(progress(int,QString)), SLOT(progress(int,QString))); + connect(thread, SIGNAL(finished()), SLOT(accept())); + connect(this, SIGNAL(cancelled()), thread, SLOT(cancel())); + itsActionLabel->startAnimation(); + thread->start(); + exec(); + delete thread; + } + + delete dialog; + + #ifdef HAVE_LOCALE_H + if(oldLocale) + setlocale(LC_NUMERIC, oldLocale); + #endif +} + +void CPrinter::progress(int p, const QString &label) +{ + if(!label.isEmpty()) + itsStatusLabel->setText(label); + itsProgress->setValue(p); +} + +void CPrinter::slotButtonClicked(int button) +{ + Q_UNUSED(button) + itsStatusLabel->setText(i18n("Canceling...")); + emit cancelled(); +} + +void CPrinter::closeEvent(QCloseEvent *e) +{ + Q_UNUSED(e) + e->ignore(); + slotButtonClicked(0); +} + +static K4AboutData aboutData("kfontprint", KFI_CATALOGUE, ki18n("Font Printer"), "1.1", ki18n("Simple font printer"), + K4AboutData::License_GPL, ki18n("(C) Craig Drummond, 2007")); + +int main(int argc, char **argv) +{ + KCmdLineArgs::init(argc, argv, &aboutData); + + KCmdLineOptions options; + options.add("embed ", ki18n("Makes the dialog transient for an X app specified by winid")); + options.add("size ", ki18n("Size index to print fonts")); + options.add("pfont ", ki18n("Font to print, specified as \"Family,Style\" where Style is a 24-bit decimal number composed as: ")); //krazy:exclude=i18ncheckarg + options.add("listfile ", ki18n("File containing list of fonts to print")); + options.add("deletefile", ki18n("Remove file containing list of fonts to print")); + KCmdLineArgs::addCmdLineOptions(options); + + KApplication app; + KCmdLineArgs *args(KCmdLineArgs::parsedArgs()); + QList fonts; + int size(args->getOption("size").toInt()); + + if(size>-1 && size<256) + { + QString listFile(args->getOption("listfile")); + + if(listFile.size()) + { + QFile f(listFile); + + if(f.open(QIODevice::ReadOnly)) + { + QTextStream str(&f); + + while (!str.atEnd()) + { + QString family(str.readLine()), + style(str.readLine()); + + if(!family.isEmpty() && !style.isEmpty()) + fonts.append(Misc::TFont(family, style.toUInt())); + else + break; + } + f.close(); + } + + if(args->isSet("deletefile")) + ::unlink(listFile.toLocal8Bit().constData()); + } + else + { + QStringList fl(args->getOptionList("pfont")); + QStringList::ConstIterator it(fl.begin()), + end(fl.end()); + + for(; it!=end; ++it) + { + QString f(*it); + + int commaPos=f.lastIndexOf(','); + + if(-1!=commaPos) + fonts.append(Misc::TFont(f.left(commaPos), f.mid(commaPos+1).toUInt())); + } + } + + if(fonts.count()) + { + CPrinter(createParent(args->getOption("embed").toInt(0, 16))).print(fonts, size); + + return 0; + } + } + + return -1; +} + +#include "Printer.moc" diff --git a/kcms/kfontinst/apps/Printer.h b/kcms/kfontinst/apps/Printer.h new file mode 100644 index 0000000000..146bc3e3e1 --- /dev/null +++ b/kcms/kfontinst/apps/Printer.h @@ -0,0 +1,103 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2011 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 __PRINTER_H__ +#define __PRINTER_H__ + +#include +#include +#include +#include +#include "Misc.h" + +class QLabel; +class QProgressBar; +class QStackedWidget; +class QPrinter; + +namespace KFI +{ + +class CActionLabel; + +class CPrintThread : public QThread +{ + Q_OBJECT + + public: + + CPrintThread(QPrinter *printer, const QList &items, int size, QObject *parent); + ~CPrintThread(); + + void run(); + + Q_SIGNALS: + + void progress(int p, const QString &f); + + public Q_SLOTS: + + void cancel(); + + private: + + QPrinter *itsPrinter; + QList itsItems; + int itsSize; + bool itsCancelled; +}; + +class CPrinter : public KDialog +{ + Q_OBJECT + + public: + + explicit CPrinter(QWidget *parent); + ~CPrinter(); + + void print(const QList &items, int size); + + Q_SIGNALS: + + void cancelled(); + + public Q_SLOTS: + + void progress(int p, const QString &label); + void slotButtonClicked(int button); + + private: + + void closeEvent(QCloseEvent *e); + + private: + + QLabel *itsStatusLabel; + QProgressBar *itsProgress; + CActionLabel *itsActionLabel; +}; + +} + +#endif diff --git a/kcms/kfontinst/apps/Viewer.cpp b/kcms/kfontinst/apps/Viewer.cpp new file mode 100644 index 0000000000..438bede3ae --- /dev/null +++ b/kcms/kfontinst/apps/Viewer.cpp @@ -0,0 +1,168 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "Viewer.h" +#include "KfiConstants.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace KFI +{ + +CViewer::CViewer() +{ + KPluginFactory *factory=KPluginLoader("kfontviewpart").factory(); + + if(factory) + { + itsPreview=factory->create(this); + + actionCollection()->addAction(KStandardAction::Open, this, SLOT(fileOpen())); + actionCollection()->addAction(KStandardAction::Quit, this, SLOT(close())); + actionCollection()->addAction(KStandardAction::KeyBindings, this, SLOT(configureKeys())); + itsPrintAct=actionCollection()->addAction(KStandardAction::Print, itsPreview, SLOT(print())); + + itsPrintAct->setEnabled(false); + + if(itsPreview->browserExtension()) + connect(itsPreview->browserExtension(), SIGNAL(enableAction(const char*,bool)), + this, SLOT(enableAction(const char*,bool))); + + setCentralWidget(itsPreview->widget()); + createGUI(itsPreview); + + setAutoSaveSettings(); + applyMainWindowSettings(KGlobal::config()->group("MainWindow")); + } + else + exit(0); +} + +void CViewer::fileOpen() +{ + KUrl url(KFileDialog::getOpenUrl(KUrl(), "application/x-font-ttf application/x-font-otf " + "application/x-font-type1 " + "application/x-font-bdf application/x-font-pcf ", + this, i18n("Select Font to View"))); + showUrl(url); +} + +void CViewer::showUrl(const KUrl &url) +{ + if(url.isValid()) + itsPreview->openUrl(url); +} + +void CViewer::configureKeys() +{ + KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this); + + dlg.addCollection(actionCollection()); + dlg.configure(); +} + +void CViewer::enableAction(const char *name, bool enable) +{ + if(0==qstrcmp("print", name)) + itsPrintAct->setEnabled(enable); +} + + + + +class ViewerApplication : public KUniqueApplication +{ + public: + +#ifdef Q_WS_X11 + ViewerApplication(Display *display, Qt::HANDLE visual, Qt::HANDLE colormap) + : KUniqueApplication(display,visual,colormap) + { + } +#endif + + ViewerApplication() : KUniqueApplication() + { + } + + int newInstance() + { + KCmdLineArgs *args(KCmdLineArgs::parsedArgs()); + KFI::CViewer *viewer=new KFI::CViewer; + + viewer->show(); + if(args->count() > 0) + { + for (int i = 0; i < args->count(); ++i) + { + KUrl url(args->url(i)); + + if (i != 0) + { + viewer=new KFI::CViewer; + viewer->show(); + } + viewer->showUrl(url); + } + } + + return 0; + } +}; + +} + +static K4AboutData aboutData("kfontview", KFI_CATALOGUE, ki18n("Font Viewer"), "1.1", ki18n("Simple font viewer"), + K4AboutData::License_GPL, ki18n("(C) Craig Drummond, 2004-2007")); + +int main(int argc, char **argv) +{ + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addTempFileOption(); + + KCmdLineOptions options; + options.add("+[URL]", ki18n("URL to open")); + KCmdLineArgs::addCmdLineOptions(options); + + if (!KUniqueApplication::start()) + exit(0); + + KFI::ViewerApplication app; + + return app.exec(); +} + +#include "Viewer.moc" diff --git a/kcms/kfontinst/apps/Viewer.h b/kcms/kfontinst/apps/Viewer.h new file mode 100644 index 0000000000..4207431d54 --- /dev/null +++ b/kcms/kfontinst/apps/Viewer.h @@ -0,0 +1,60 @@ +#ifndef __VIEWER_H__ +#define __VIEWER_H__ + +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2007 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include + +class QAction; +class KUrl; + +namespace KFI +{ + +class CViewer : public KParts::MainWindow +{ + Q_OBJECT + + public: + + CViewer(); + virtual ~CViewer() { } + void showUrl(const KUrl &url); + + public Q_SLOTS: + + void fileOpen(); + void configureKeys(); + void enableAction(const char *name, bool enable); + + private: + + KParts::ReadOnlyPart *itsPreview; + QAction *itsPrintAct; +}; + +} + +#endif diff --git a/kcms/kfontinst/apps/installfont.desktop b/kcms/kfontinst/apps/installfont.desktop new file mode 100644 index 0000000000..bf18749098 --- /dev/null +++ b/kcms/kfontinst/apps/installfont.desktop @@ -0,0 +1,96 @@ +[Desktop Entry] +X-KDE-ServiceTypes=KonqPopupMenu/Plugin,application/x-font-ttf,application/x-font-type1,application/x-font-bdf,application/x-font-pcf,application/x-font-otf,application/x-font-afm,fonts/package +Actions=installFont; +Type=Service + +[Desktop Action installFont] +Name=Install... +Name[af]=Installeer... +Name[ar]=ثبّت... +Name[as]=সংস্থাপন কৰক... +Name[ast]=Instalar... +Name[be]=Устанавіць... +Name[be@latin]=Zainstaluj... +Name[bg]=Инсталиране... +Name[bn]=ইনস্টল... +Name[bn_IN]=ইনস্টল করুন... +Name[bs]=Instaliraj... +Name[ca]=Instal·la... +Name[ca@valencia]=Instal·la... +Name[cs]=Instalovat... +Name[csb]=Instalëjë... +Name[da]=Installér... +Name[de]=Installieren ... +Name[el]=Εγκατάσταση... +Name[en_GB]=Install... +Name[eo]=Instali... +Name[es]=Instalar... +Name[et]=Paigalda... +Name[eu]=Instalatu... +Name[fa]=نصب... +Name[fi]=Asenna… +Name[fr]=Installer... +Name[fy]=Ynstallearje... +Name[ga]=Suiteáil... +Name[gl]=Instalar… +Name[gu]=સ્થાપન... +Name[he]=התקנה... +Name[hi]=संस्थापित करें... +Name[hne]=इंस्टाल करव... +Name[hr]=Instaliraj… +Name[hsb]=instalować... +Name[hu]=Telepítés... +Name[ia]=Installa ... +Name[id]=Instal... +Name[is]=Setja upp... +Name[it]=Installa... +Name[ja]=インストール... +Name[kk]=Орнату... +Name[km]=ដំឡើង... +Name[kn]=ಅನುಸ್ಢಾಪಿಸು... +Name[ko]=설치... +Name[ku]=Sazkirin... +Name[lt]=Įdiegti... +Name[lv]=Instalēt... +Name[mai]=संस्थापित करू... +Name[mk]=Инсталирање... +Name[ml]=ഇന്‍‌സ്റ്റോള്‍ ചെയ്യുക... +Name[mr]=प्रतिष्ठापन... +Name[nb]=Installer … +Name[nds]=Installeren... +Name[ne]=स्थापना गर्नुहोस् +Name[nl]=Installeren... +Name[nn]=Installer … +Name[oc]=Installar... +Name[or]=ସ୍ଥାପନ କରନ୍ତୁ... +Name[pa]=ਇੰਸਟਾਲ... +Name[pl]=Instaluj... +Name[pt]=Instalar... +Name[pt_BR]=Instalar... +Name[ro]=Instalare... +Name[ru]=Установить... +Name[se]=Sajáiduhte … +Name[si]=ස්ථාපනය... +Name[sk]=Inštalovať... +Name[sl]=Namesti ... +Name[sr]=Инсталирај... +Name[sr@ijekavian]=Инсталирај... +Name[sr@ijekavianlatin]=Instaliraj... +Name[sr@latin]=Instaliraj... +Name[sv]=Installera... +Name[ta]=நிறுவுக... +Name[te]=సంస్థాపించు... +Name[tg]=Коргузорӣ... +Name[th]=ติดตั้ง... +Name[tr]=Yükle... +Name[ug]=ئورنات… +Name[uk]=Встановити... +Name[uz]=Oʻrnatish... +Name[uz@cyrillic]=Ўрнатиш... +Name[vi]=Cài đặt... +Name[wa]=Astaler... +Name[x-test]=xxInstall...xx +Name[zh_CN]=安装... +Name[zh_TW]=安裝... +Icon=preferences-desktop-font-installer +Exec=kfontinst --icon preferences-desktop-font-installer %U diff --git a/kcms/kfontinst/apps/kfontview.desktop b/kcms/kfontinst/apps/kfontview.desktop new file mode 100755 index 0000000000..141d247081 --- /dev/null +++ b/kcms/kfontinst/apps/kfontview.desktop @@ -0,0 +1,192 @@ +[Desktop Entry] +Name=KFontView +Name[af]=KFontView +Name[ar]=عارض خطوط كيدي +Name[ast]=KFontView +Name[be]=Прагляд шрыфтоў +Name[be@latin]=KFontView +Name[bg]=KFontView +Name[bn]=কে-ফন্ট-ভিউ +Name[bn_IN]=KFontView +Name[br]=KFontView +Name[bs]=K‑prikazivač-fontova +Name[ca]=KFontView +Name[ca@valencia]=KFontView +Name[cs]=Prohlížeč písem +Name[csb]=KFontView +Name[cy]=KFontView +Name[da]=KFontView +Name[de]=KFontView +Name[el]=KFontView +Name[en_GB]=KFontView +Name[eo]=KFontView +Name[es]=KFontView +Name[et]=KFontView +Name[eu]=KFontWiew +Name[fi]=KFontView +Name[fr]=KFontView +Name[fy]=KFontView +Name[ga]=KFontView +Name[gl]=KFontView +Name[gu]=KFontView +Name[he]=KFontView +Name[hi]=के-फ़ॉन्ट-व्यू +Name[hne]=के-फोंट-व्यू +Name[hr]=KFontView +Name[hsb]=KFontView +Name[hu]=KFontView +Name[ia]=KFontView +Name[id]=KFontView +Name[is]=KFontView +Name[it]=KFontView +Name[ja]=KFontView +Name[ka]=KFontView +Name[kk]=KFontView +Name[km]=KFontView +Name[kn]=ಕೆಫಾಂಟ್ ವ್ಯೂ +Name[ko]=KFontView +Name[ku]=KFontView +Name[lt]=KFontView +Name[lv]=KFontView +Name[mai]=के-फान्ट-व्यू +Name[mk]=КФонтПреглед +Name[ml]=കെഫോണ്ട്‌വ്യൂ +Name[mr]=केफॉन्टव्यू +Name[ms]=KFontView +Name[nb]=KFontView +Name[nds]=KFontView +Name[ne]=केडीई फन्ट दृश्य +Name[nl]=KFontView +Name[nn]=Skriftvisar +Name[oc]=KFontView +Name[or]=KFontView +Name[pa]=KFontView +Name[pl]=KFontView +Name[pt]=KFontView +Name[pt_BR]=KFontView +Name[ro]=KFontView +Name[ru]=KFontView +Name[se]=Fontačájeheaddji +Name[si]=KFontView +Name[sk]=KFontView +Name[sl]=KFontView +Name[sr]=К‑приказивач-фонтова +Name[sr@ijekavian]=К‑приказивач-фонтова +Name[sr@ijekavianlatin]=K‑prikazivač-fontova +Name[sr@latin]=K‑prikazivač-fontova +Name[sv]=Kfontview +Name[ta]=KFontView +Name[te]=KFontView +Name[tg]=Намоиши ҳарф +Name[th]=ดูแบบอักษร-K +Name[tr]=KFontView +Name[ug]=KFontView +Name[uk]=KFontView +Name[uz]=KFontView +Name[uz@cyrillic]=KFontView +Name[vi]=KFonView +Name[wa]=Håyneu d' fontes +Name[x-test]=xxKFontViewxx +Name[zh_CN]=KFontView +Name[zh_TW]=KFontView +Exec=kfontview %U +Icon=kfontview +X-KDE-StartupNotify=true +Type=Application +MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-otf;application/x-font-pcf;application/x-font-bdf;application/vnd.kde.fontspackage; +GenericName=Font Viewer +GenericName[af]=Skriftipe Besigter +GenericName[ar]=عارض الخطوط +GenericName[ast]=Visor del triba de lletra +GenericName[be]=Прагляд шрыфта +GenericName[be@latin]=Prahladnik šryftoŭ +GenericName[bg]=Преглед на шрифтове +GenericName[bn]=ফন্ট প্রদর্শক +GenericName[bn_IN]=ফন্ট প্রদর্শক +GenericName[br]=Gweler Nodrezhoù +GenericName[bs]=Prikazivač fontova +GenericName[ca]=Visor de tipus de lletra +GenericName[ca@valencia]=Visor de tipus de lletra +GenericName[cs]=Prohlížeč písem +GenericName[csb]=Przezérnik fòntów +GenericName[cy]=Gwelydd Wynebfathau +GenericName[da]=Skrifttype-fremviser +GenericName[de]=Schriftartenbetrachter +GenericName[el]=Προβολέας γραμματοσειρών +GenericName[en_GB]=Font Viewer +GenericName[eo]=Tipara rigardilo +GenericName[es]=Visor del tipo de letra +GenericName[et]=Fontide näitaja +GenericName[eu]=Letra-tipoen ikustailea +GenericName[fa]=مشاهده‌گر قلم +GenericName[fi]=Kirjasinkatselin +GenericName[fr]=Afficheur de polices de caractères +GenericName[fy]=Lettertypewerjefte +GenericName[ga]=Amharcán Clónna +GenericName[gl]=Visor de tipos de letra +GenericName[gu]=ફોન્ટ દર્શક +GenericName[he]=מציג גופנים +GenericName[hi]=फ़ॉन्ट प्रदर्शक +GenericName[hne]=फोंट प्रदर्सक +GenericName[hr]=Preglednik fontova +GenericName[hsb]=Přehladowar za pisma +GenericName[hu]=Betűtípusböngésző +GenericName[ia]=Visor de fronte +GenericName[id]=Penampil Fonta +GenericName[is]=Leturskoðari +GenericName[it]=Visore di caratteri +GenericName[ja]=フォントビューア +GenericName[ka]=პროგრამა ფონტების სანახავად +GenericName[kk]=Қаріпті қарау құралы +GenericName[km]=កម្មវិធី​មើល​ពុម្ពអក្សរ +GenericName[kn]=ಅಕ್ಷರಶೈಲಿ ವೀಕ್ಷಕ +GenericName[ko]=글꼴 뷰어 +GenericName[ku]=Nîşandêra Curetîpan +GenericName[lt]=Šriftų žiūryklė +GenericName[lv]=Fontu skatītājs +GenericName[mai]=फान्ट प्रदर्शक +GenericName[mk]=Прегледувач на фонтови +GenericName[ml]=അക്ഷരസഞ്ചയദര്‍ശിനി +GenericName[mr]=फॉन्ट प्रदर्शक +GenericName[ms]=Pemapar Fon +GenericName[nb]=Skrifttypeviser +GenericName[nds]=Schriftoortkieker +GenericName[ne]=फन्ट दर्शक +GenericName[nl]=Lettertypeweergave +GenericName[nn]=Skriftvisar +GenericName[or]=ଅକ୍ଷରରୂପ ପ୍ରଦର୍ଶକ +GenericName[pa]=ਫੋਂਟ ਦਰਸ਼ਕ +GenericName[pl]=Przeglądarka czcionek +GenericName[pt]=Visualizador do Tipo de Letra +GenericName[pt_BR]=Visualizador de fontes +GenericName[ro]=Vizualizator de fonturi +GenericName[ru]=Просмотр шрифтов +GenericName[se]=Fontačájeheaddji +GenericName[si]=අකුරු දසුන +GenericName[sk]=Prehliadač písiem +GenericName[sl]=Pregledovalnik pisav +GenericName[sr]=Приказивач фонтова +GenericName[sr@ijekavian]=Приказивач фонтова +GenericName[sr@ijekavianlatin]=Prikazivač fontova +GenericName[sr@latin]=Prikazivač fontova +GenericName[sv]=Teckensnittsvisning +GenericName[ta]=Font Viewer +GenericName[te]=ఫాంట్ వీక్షణి +GenericName[tg]=Намоишгари ҳарфҳо +GenericName[th]=ดูตัวอย่างแบบอักษร +GenericName[tr]=Yazı Tipi Görüntüleyici +GenericName[ug]=خەت نۇسخا كۆرگۈ +GenericName[uk]=Переглядач шрифтів +GenericName[uz]=Shrift koʻruvchi +GenericName[uz@cyrillic]=Шрифт кўрувчи +GenericName[vi]=Trình xem phông chữ +GenericName[wa]=Håyneu d' fontes +GenericName[x-test]=xxFont Viewerxx +GenericName[zh_CN]=字体查看器 +GenericName[zh_TW]=字型檢視器 +Terminal=false +InitialPreference=1 +NoDisplay=true +Categories=Qt;KDE;Utility; +X-DBUS-StartupType=Unique +X-KDE-HasTempFileOption=true diff --git a/kcms/kfontinst/apps/kfontviewui.rc b/kcms/kfontinst/apps/kfontviewui.rc new file mode 100644 index 0000000000..f2e4a86fa8 --- /dev/null +++ b/kcms/kfontinst/apps/kfontviewui.rc @@ -0,0 +1,4 @@ + + + + diff --git a/kcms/kfontinst/apps/ox16-app-kfontview.png b/kcms/kfontinst/apps/ox16-app-kfontview.png new file mode 100644 index 0000000000000000000000000000000000000000..3691f9068b5e297632061a9f1772e1d3ed17b8d9 GIT binary patch literal 719 zcmV;=0xk@#$4V#1-U z(mz~FtarYD^OAV}kjc~Qx^n!O^Ewf|V;DAwdSa&sAPUz#G!Fy6MQK=}MPE)a1 zB%|4+XI0g`!C=rp0MFmwZ7#vm4w~v3)0W7oGkKBX$uAU*M(NeuJPFwXN$NUT6s11e z2j$;gB&i_cjY}JOTAEv+`N?roYW0%N?n^c@qJZ;Sr*igA@FTl5V^C)V1uN4^JSk02 zKc`qMR?unLPipCVk>fN^D+UY>Uc4%9u6*cj6ovK{Lxup~bWk)aKdTfZY6L-W(LN|f zM@MNFdq;cV?dum>zK(0_>asVq+FF0|hWfrpB+}sZdT)n9AD-0;{lW&cnjKKiEHo)LY4_&9fi;5 zdyHw$*lf1dy#YNH{>&gke$fs%{4uPv^e5nd_zgIR1@P-;wx0k1002ovPDHLkV1hS!s8V~3H!vQ}|Ps!Q4!#h5pFqfM9OP2N3+1b!Bgu=PtmJn!?q@Oi_R z_kAe<>Kg#?!v9ZDQ5w%$3xixje29XqAaO)QDu@TUi~wc}xs6bW39%wWh#i6Een`wC z2gv()#~3uTva(_ihaY?)ih0OvW#F%Pd@r@RISE84O2y$=Mg|f7&^7$6;`{-n)6H|L zhYufpR|n>!%uZe#i$<(QgAv?aCoAX9p7{wt3H0~(i-df*Dfgq}5h+gK{IJ!}z4;#_ zg89U|7FUl=RmlTgEr6QmVK-j{TIV>ZN!u@8q&Lrxj*iv{`4b%D=y*U@5ok&0=I-9q znd}~u%VRO?Szt8=P}L|91OYg;23S+4ZX;QBSgob`X7{apj1++ggVJAHOSxPQ>fb(P zY~Zn6Z-6A0ppZ=f!!STGJalMJD7KC+ZAQ#oASLKXz-v*Fi&~>GNDYCmp)`LWL#}uL z@puAOS6AWL#@|X+R`%-(oo9KWHak0e7LEx+E-cH?d#@DWqzZ5h4f$LVVzEDfrfD$S zI%MxaW2aP>vkXJIDT-p-7MCPRbh>KhicE9mO0^MT}4zAQssuGS0!vuyy;DM`gY0n@hl z#`WvdyV>Vy6BKseaqyJGtbGNoC=J=d?04;DQ)f&@Lu6uN!hW2Xo}8QnG7IsDwhH z&c}~`zLgjA!JX}GNTpIw5{dZvp`jsTcXxN9udmPHcDrk9YipkcgTeW>#Kar*366Ws z^*4N8eSjGm896;LFc9H+-s$yvm1HtGJ~lS?_2G{HLzb79n}2)1ty!?qJ_n)9LiLfZ{g_zBre05*@$c{0r$k%@^W* R(LDeF002ovPDHLkV1h!A>9_y@ literal 0 HcmV?d00001 diff --git a/kcms/kfontinst/apps/ox32-app-kfontview.png b/kcms/kfontinst/apps/ox32-app-kfontview.png new file mode 100644 index 0000000000000000000000000000000000000000..c3063f15b993f67c7e93963ee5d386d482b78894 GIT binary patch literal 1545 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 literal 0 HcmV?d00001 diff --git a/kcms/kfontinst/apps/oxsc-app-kfontview.svgz b/kcms/kfontinst/apps/oxsc-app-kfontview.svgz new file mode 100644 index 0000000000000000000000000000000000000000..6a6a4f8d6b2d9b69a23443cd52105366efe87a78 GIT binary patch literal 9292 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 header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +#endif diff --git a/kcms/kfontinst/dbus/CMakeLists.txt b/kcms/kfontinst/dbus/CMakeLists.txt new file mode 100644 index 0000000000..5e203eb7b7 --- /dev/null +++ b/kcms/kfontinst/dbus/CMakeLists.txt @@ -0,0 +1,31 @@ +include_directories(${CMAKE_CURRENT_BINARY_DIR} + ${kcms_SOURCE_DIR}/fonts) +add_definitions(${QT_DEFINITIONS}) + +set(fontinst_bin_SRCS FcConfig.cpp FontInst.cpp Folder.cpp Main.cpp Utils.cpp ${libkfontinstdbusiface_SRCS} ) +set(fontinst_helper_SRCS FcConfig.cpp Helper.cpp Folder.cpp Utils.cpp ${libkfontinstdbusiface_SRCS} ) + +# qt5_generate_dbus_interface(FontInst.h org.kde.fontinst.xml) +qt5_add_dbus_adaptor(fontinst_bin_SRCS org.kde.fontinst.xml FontInst.h KFI::FontInst) +# qt5_add_dbus_interface(fontinst_bin_SRCS org.kde.fontinst.xml FontinstIface) + +add_executable(fontinst_bin ${fontinst_bin_SRCS}) +add_executable(fontinst_helper ${fontinst_helper_SRCS}) + +set_target_properties(fontinst_bin PROPERTIES OUTPUT_NAME fontinst) +target_link_libraries(fontinst_bin + Qt5::DBus Qt5::Xml ${FONTCONFIG_LIBRARIES} kfontinst) + +set_target_properties(fontinst_helper PROPERTIES OUTPUT_NAME fontinst_helper) +target_link_libraries(fontinst_helper + Qt5::DBus Qt5::Xml ${FONTCONFIG_LIBRARIES} kfontinst) + +install(TARGETS fontinst_bin DESTINATION ${LIBEXEC_INSTALL_DIR} ) +install(TARGETS fontinst_helper DESTINATION ${LIBEXEC_INSTALL_DIR} ) +install(PROGRAMS fontinst_x11 DESTINATION ${LIBEXEC_INSTALL_DIR}) + +configure_file(org.kde.fontinst.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/session/org.kde.fontinst.service) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/session/org.kde.fontinst.service DESTINATION ${DBUS_SERVICES_INSTALL_DIR} ) + +kauth_install_helper_files(fontinst_helper org.kde.fontinst root) +kauth_install_actions(org.kde.fontinst fontinst.actions) diff --git a/kcms/kfontinst/dbus/FcConfig.cpp b/kcms/kfontinst/dbus/FcConfig.cpp new file mode 100644 index 0000000000..2213a5ef26 --- /dev/null +++ b/kcms/kfontinst/dbus/FcConfig.cpp @@ -0,0 +1,194 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2009 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 "FcConfig.h" +#include "Misc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KFI_DBUG kDebug() << time(0L) + +namespace KFI +{ + +namespace FcConfig +{ + +inline QString xDirSyntax(const QString &d) { return Misc::fileSyntax(d); } + +// +// Obtain location of config file to use. +// +// For system, prefer the following: +// +// <...>/config.d/00kde.conf = preferred method from FCConfig >= 2.3 +// <...>/local.conf +// +// Non-system, prefer: +// +// $HOME/<...>/.fonts.conf +// $HOME/<...>/fonts.conf +// +QString getConfigFile(bool system) +{ +#if (FC_VERSION>=20300) + static const char constKdeRootFcFile[] = "00kde.conf"; +#endif + + FcStrList *list=FcConfigGetConfigFiles(FcConfigGetCurrent()); + QStringList files; + FcChar8 *file; + QString home(Misc::dirSyntax(QDir::homePath())); + + while((file=FcStrListNext(list))) + { + QString f((const char *)file); + + if(Misc::fExists(f)) + { + // For nonsystem, only consider file within $HOME + if(system || 0==Misc::fileSyntax(f).indexOf(home)) + files.append(f); + } +#if (FC_VERSION>=20300) + if(system && Misc::dExists(f) && (f.contains(QRegExp("/conf\\.d/?$")) || + f.contains(QRegExp("/conf\\.d?$"))) ) + return Misc::dirSyntax(f)+constKdeRootFcFile; // This ones good enough for me! +#endif + } + + // + // Go through list of files, looking for the preferred one... + if(files.count()) + { + QStringList::const_iterator it(files.begin()), + end(files.end()); + + for(; it!=end; ++it) + if(-1!=(*it).indexOf(QRegExp(system ? "/local\\.conf$" : "/\\.?fonts\\.conf$"))) + return *it; + return files.front(); // Just return the 1st one... + } + else // Hmmm... no known files? + return system ? "/etc/fonts/local.conf" : Misc::fileSyntax(home+"/.fonts.conf"); +} + +void addDir(const QString &dir, bool system) +{ + QDomDocument doc("fontconfig"); + QString fileName=getConfigFile(system); + QFile f(fileName); + bool hasDir(false); + + KFI_DBUG << "Using fontconfig file:" << fileName; + + // Load existing file - and check to see whether it has the dir... + if(f.open(QIODevice::ReadOnly)) + { + doc.clear(); + + if(doc.setContent(&f)) + { + QDomNode n = doc.documentElement().firstChild(); + + while(!n.isNull() && !hasDir) + { + QDomElement e = n.toElement(); + + if(!e.isNull() && "dir"==e.tagName()) + if(0==Misc::expandHome(Misc::dirSyntax(e.text())).indexOf(dir)) + hasDir=true; + n=n.nextSibling(); + } + } + f.close(); + } + + // Add dir, and save, if config does not already have this dir. + if(!hasDir) + { + if(doc.documentElement().isNull()) + doc.appendChild(doc.createElement("fontconfig")); + + QDomElement newNode = doc.createElement("dir"); + QDomText text = doc.createTextNode(Misc::contractHome(xDirSyntax(dir))); + + newNode.appendChild(text); + doc.documentElement().appendChild(newNode); + + FcAtomic *atomic=FcAtomicCreate((const unsigned char *)(QFile::encodeName(fileName).data())); + + if(atomic) + { + if(FcAtomicLock(atomic)) + { + FILE *f=fopen((char *)FcAtomicNewFile(atomic), "w"); + + if(f) + { + // + // Check document syntax... + static const char qtXmlHeader[] = ""; + static const char xmlHeader[] = ""; + static const char qtDocTypeLine[] = ""; + static const char docTypeLine[] = ""; + + QString str(doc.toString()); + int idx; + + if(0!=str.indexOf(" + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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. + */ + +class QString; + +namespace KFI +{ + +namespace FcConfig +{ + void addDir(const QString &dir, bool system); +} + +} + +#endif diff --git a/kcms/kfontinst/dbus/Folder.cpp b/kcms/kfontinst/dbus/Folder.cpp new file mode 100644 index 0000000000..ba9b45f9ef --- /dev/null +++ b/kcms/kfontinst/dbus/Folder.cpp @@ -0,0 +1,418 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2009 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Folder.h" +#include "FcConfig.h" +#include "Misc.h" +#include "KfiConstants.h" +#include "XmlStrings.h" +#include "Style.h" +#include "File.h" +#include "config-fontinst.h" + +#define DISABLED_FONTS "disabledfonts" +#define KFI_DBUG kDebug() << time(0L) + +namespace KFI +{ + +bool Folder::CfgFile::modified() +{ + return timestamp!=Misc::getTimeStamp(name); +} + +void Folder::CfgFile::updateTimeStamp() +{ + timestamp=Misc::getTimeStamp(name); +} + +Folder::~Folder() +{ + saveDisabled(); +} + +void Folder::init(bool system, bool systemBus) +{ + itsIsSystem=system; + if(!system) + { + FcStrList *list=FcConfigGetFontDirs(FcInitLoadConfigAndFonts()); + QStringList dirs; + FcChar8 *fcDir; + + while((fcDir=FcStrListNext(list))) + dirs.append(Misc::dirSyntax((const char *)fcDir)); + + itsLocation=Misc::getFolder(Misc::dirSyntax(QDir::homePath()+"/.fonts/"), Misc::dirSyntax(QDir::homePath()), dirs); + } + else + itsLocation=KFI_DEFAULT_SYS_FONTS_FOLDER; + + if((!system && !systemBus) || (system && systemBus)) + FcConfig::addDir(itsLocation, system); + + itsDisabledCfg.dirty=false; + if(itsDisabledCfg.name.isEmpty()) + { + QString fileName("/"DISABLED_FONTS".xml"); + + if(system) + itsDisabledCfg.name=QString::fromLatin1(KFI_ROOT_CFG_DIR)+fileName; + else + { + QString path=KGlobal::dirs()->localxdgconfdir(); + + if(!Misc::dExists(path)) + Misc::createDir(path); + itsDisabledCfg.name=path+fileName; + } + itsDisabledCfg.timestamp=0; + } +} + +bool Folder::allowToggling() const +{ + return Misc::fExists(itsDisabledCfg.name) + ? Misc::fWritable(itsDisabledCfg.name) + : Misc::dWritable(Misc::getDir(itsDisabledCfg.name)); +} + +void Folder::loadDisabled() +{ + if(itsDisabledCfg.dirty) + saveDisabled(); + + QFile f(itsDisabledCfg.name); + + KFI_DBUG << itsDisabledCfg.name; + itsDisabledCfg.dirty=false; + if(f.open(QIODevice::ReadOnly)) + { + QDomDocument doc; + + if(doc.setContent(&f)) + for(QDomNode n=doc.documentElement().firstChild(); !n.isNull(); n=n.nextSibling()) + { + QDomElement e=n.toElement(); + + if(FONT_TAG==e.tagName()) + { + Family fam(e, false); + + if(!fam.name().isEmpty()) + { + Style style(e, false); + + if(KFI_NO_STYLE_INFO!=style.value()) + { + QList files; + + if(e.hasAttribute(PATH_ATTR)) + { + File file(e, true); + + if(!file.path().isEmpty()) + files.append(file); + else + itsDisabledCfg.dirty=true; + } + else + { + for(QDomNode n=e.firstChild(); !n.isNull(); n=n.nextSibling()) + { + QDomElement ent=n.toElement(); + + if(FILE_TAG==ent.tagName()) + { + File file(ent, true); + + if(!file.path().isEmpty()) + files.append(file); + else + { + KFI_DBUG << "Set dirty from load"; + itsDisabledCfg.dirty=true; + } + } + } + } + + if(files.count()>0) + { + QList::ConstIterator it(files.begin()), + end(files.end()); + + FamilyCont::ConstIterator f(itsFonts.insert(fam)); + StyleCont::ConstIterator s((*f).add(style)); + + for(; it!=end; ++it) + (*s).add(*it); + } + } + } + } + } + + f.close(); + itsDisabledCfg.updateTimeStamp(); + } + + saveDisabled(); +} + +void Folder::saveDisabled() +{ + if(itsDisabledCfg.dirty) + { + if(!itsIsSystem || Misc::root()) + { + KFI_DBUG << itsDisabledCfg.name; + + KSaveFile file; + + file.setFileName(itsDisabledCfg.name); + + if(!file.open()) + { + KFI_DBUG << "Exit - cant open save file"; + qApp->exit(0); + } + + QTextStream str(&file); + + str << "<"DISABLED_FONTS">" << endl; + + FamilyCont::ConstIterator it(itsFonts.begin()), + end(itsFonts.end()); + + for(; it!=end; ++it) + (*it).toXml(true, str); + str << "" << endl; + str.flush(); + + if(!file.finalize()) + { + KFI_DBUG << "Exit - cant finalize save file"; + qApp->exit(0); + } + } + itsDisabledCfg.updateTimeStamp(); + itsDisabledCfg.dirty=false; + } +} + +QStringList Folder::toXml(int max) +{ + QStringList rv; + FamilyCont::ConstIterator it(itsFonts.begin()), + end(itsFonts.end()); + QString string; + QTextStream str(&string); + + for(int i=0; it!=end; ++it, ++i) + { + if(0==(i%max)) + { + if(i) + { + str << "" << endl; + rv.append(string); + string=QString(); + } + str << "<"FONTLIST_TAG" " << SYSTEM_ATTR"=\"" << (itsIsSystem ? "true" : "false") << "\">" << endl; + } + + (*it).toXml(false, str); + } + + if(!string.isEmpty()) + { + str << "" << endl; + rv.append(string); + } + return rv; +} + +Families Folder::list() +{ + Families fam(itsIsSystem); + FamilyCont::ConstIterator it(itsFonts.begin()), + end(itsFonts.end()); + + for(int i=0; it!=end; ++it, ++i) + fam.items.insert(*it); + + return fam; +} + +bool Folder::contains(const QString &family, quint32 style) +{ + FamilyCont::ConstIterator fam=itsFonts.find(Family(family)); + + if(fam==itsFonts.end()) + return false; + + StyleCont::ConstIterator st=(*fam).styles().find(Style(style)); + + return st!=(*fam).styles().end(); +} + +void Folder::add(const Family &family) +{ + FamilyCont::ConstIterator existingFamily=itsFonts.find(family); + + if(existingFamily==itsFonts.end()) + itsFonts.insert(family); + else + { + StyleCont::ConstIterator it(family.styles().begin()), + end(family.styles().end()); + + for(; it!=end; ++it) + { + StyleCont::ConstIterator existingStyle=(*existingFamily).styles().find(*it); + + if(existingStyle==(*existingFamily).styles().end()) + (*existingFamily).add(*it); + else + { + FileCont::ConstIterator fit((*it).files().begin()), + fend((*it).files().end()); + + for(; fit!=fend; ++fit) + { + FileCont::ConstIterator f=(*existingStyle).files().find(*fit); + + if(f==(*existingStyle).files().end()) + (*existingStyle).add(*fit); + } + + (*existingStyle).setWritingSystems((*existingStyle).writingSystems()|(*it).writingSystems()); + if(!(*existingStyle).scalable() && (*it).scalable()) + (*existingStyle).setScalable(true); + } + } + } +} + +void Folder::configure(bool force) +{ +KFI_DBUG << "EMPTY MODIFIED " << itsModifiedDirs.isEmpty(); + + if(force || !itsModifiedDirs.isEmpty()) + { + saveDisabled(); + + QSet::ConstIterator it(itsModifiedDirs.constBegin()), + end(itsModifiedDirs.constEnd()); + QSet dirs; + + for(; it!=end; ++it) + if(Misc::fExists((*it)+"fonts.dir")) + dirs.insert(KShell::quoteArg(*it)); + + if(!dirs.isEmpty()) + QProcess::startDetached(QLatin1String(KFONTINST_LIB_EXEC_DIR"/fontinst_x11"), dirs.toList()); + + itsModifiedDirs.clear(); + +KFI_DBUG << "RUN FC"; + Misc::doCmd("fc-cache"); +KFI_DBUG << "DONE"; + } +} + +Folder::Flat Folder::flatten() const +{ + FamilyCont::ConstIterator fam=itsFonts.begin(), + famEnd=itsFonts.end(); + Flat rv; + + for(; fam!=famEnd; ++fam) + { + StyleCont::ConstIterator style((*fam).styles().begin()), + styleEnd((*fam).styles().end()); + + for(; style!=styleEnd; ++style) + { + FileCont::ConstIterator file((*style).files().begin()), + fileEnd((*style).files().end()); + + for(; file!=fileEnd; ++file) + rv.insert(FlatFont(*fam, *style, *file)); + } + } + + return rv; +} + +Families Folder::Flat::build(bool system) const +{ + ConstIterator it(begin()), + e(end()); + Families families(system); + + for(; it!=e; ++it) + { + Family f((*it).family); + Style s((*it).styleInfo, (*it).scalable, (*it).writingSystems); + FamilyCont::ConstIterator fam=families.items.constFind(f); + + if(families.items.constEnd()==fam) + { + s.add((*it).file); + f.add(s); + families.items.insert(f); + } + else + { + StyleCont::ConstIterator st=(*fam).styles().constFind(s); + + if((*fam).styles().constEnd()==st) + { + s.add((*it).file); + (*fam).add(s); + } + else + (*st).add((*it).file); + } + } + + return families; +} + +} diff --git a/kcms/kfontinst/dbus/Folder.h b/kcms/kfontinst/dbus/Folder.h new file mode 100644 index 0000000000..5c07ed08ec --- /dev/null +++ b/kcms/kfontinst/dbus/Folder.h @@ -0,0 +1,114 @@ +#ifndef FOLDER_H +#define FOLDER_H + +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2009 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include "Family.h" +#include "Style.h" +#include "File.h" +#include "Misc.h" + +namespace KFI +{ + +class Folder +{ + struct CfgFile + { + bool modified(); + void updateTimeStamp(); + + bool dirty; + QString name; + time_t timestamp; + }; + + public: + + struct FlatFont : Misc::TFont + { + FlatFont(const Family &fam, const Style &style, const File &f) + : Misc::TFont(fam.name(), style.value()), + writingSystems(style.writingSystems()), + scalable(style.scalable()), + file(f) + { + } + bool operator==(const FlatFont &o) const { return file.path()==o.file.path(); } + + qulonglong writingSystems; + bool scalable; + File file; + }; + + struct Flat : public QSet + { + Families build(bool system) const; + }; + + Folder() { } + ~Folder(); + + void init(bool system, bool systemBus); + const QString & location() const { return itsLocation; } + bool allowToggling() const; + void loadDisabled(); + void saveDisabled(); + void setDisabledDirty() { itsDisabledCfg.dirty=true; } + bool disabledDirty() const { return itsDisabledCfg.dirty; } + QStringList toXml(int max=0); + Families list(); + bool contains(const QString &family, quint32 style); + void add(const Family &family); + void addModifiedDir(const QString &dir) { itsModifiedDirs.insert(dir); } + void addModifiedDirs(const QSet &dirs) { itsModifiedDirs+=dirs; } + bool isModified() const { return !itsModifiedDirs.isEmpty(); } + void clearModified() { itsModifiedDirs.clear(); } + void configure(bool force=false); + Flat flatten() const; + const FamilyCont & fonts() const { return itsFonts; } + FamilyCont::ConstIterator addFont(const Family &fam) { return itsFonts.insert(fam); } + void removeFont(const Family &fam) { itsFonts.remove(fam); } + void clearFonts() { itsFonts.clear(); } + + private: + + bool itsIsSystem; + FamilyCont itsFonts; + CfgFile itsDisabledCfg; + QString itsLocation; + QSet itsModifiedDirs; +}; + +inline Q_DECL_EXPORT uint qHash(const Folder::FlatFont &key) +{ + return qHash(key.file); // +qHash(key.index()); +} + +} + +#endif diff --git a/kcms/kfontinst/dbus/FontInst.cpp b/kcms/kfontinst/dbus/FontInst.cpp new file mode 100644 index 0000000000..37d5adebc8 --- /dev/null +++ b/kcms/kfontinst/dbus/FontInst.cpp @@ -0,0 +1,971 @@ +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2009 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "FontInst.h" +#include "fontinstadaptor.h" +#include "Misc.h" +#include "Fc.h" +#include "WritingSystems.h" +#include "Utils.h" +#include "FontinstIface.h" + +#define KFI_DBUG kDebug() << time(0L) + +namespace KFI +{ + +static void decompose(const QString &name, QString &family, QString &style) +{ + int commaPos=name.lastIndexOf(','); + + family=-1==commaPos ? name : name.left(commaPos); + style=-1==commaPos ? KFI_WEIGHT_REGULAR : name.mid(commaPos+2); +} + +static bool isSystem=false; +static Folder theFolders[FontInst::FOLDER_COUNT]; +static const int constSystemReconfigured=-1; +static const int constConnectionsTimeout = 30 * 1000; +static const int constFontListTimeout = 10 * 1000; + +typedef void (*SignalHandler)(int); + +static void registerSignalHandler(SignalHandler handler) +{ + if (!handler) + handler = SIG_DFL; + + sigset_t mask; + sigemptyset(&mask); + +#ifdef SIGSEGV + signal(SIGSEGV, handler); + sigaddset(&mask, SIGSEGV); +#endif +#ifdef SIGFPE + signal(SIGFPE, handler); + sigaddset(&mask, SIGFPE); +#endif +#ifdef SIGILL + signal(SIGILL, handler); + sigaddset(&mask, SIGILL); +#endif +#ifdef SIGABRT + signal(SIGABRT, handler); + sigaddset(&mask, SIGABRT); +#endif + + sigprocmask(SIG_UNBLOCK, &mask, 0); +} + +void signalHander(int) +{ + static bool inHandler=false; + + if(!inHandler) + { + inHandler=true; + theFolders[isSystem ? FontInst::FOLDER_SYS : FontInst::FOLDER_USER].saveDisabled(); + inHandler=false; + } +} + +FontInst::FontInst() +{ + isSystem=Misc::root(); + registerTypes(); + + new FontinstAdaptor(this); + QDBusConnection bus=QDBusConnection::sessionBus(); + + KFI_DBUG << "Connecting to session bus"; + if(!bus.registerService(OrgKdeFontinstInterface::staticInterfaceName())) + { + KFI_DBUG << "Failed to register service!"; + ::exit(-1); + } + if(!bus.registerObject(FONTINST_PATH, this)) + { + KFI_DBUG << "Failed to register object!"; + ::exit(-1); + } + + registerSignalHandler(signalHander); + itsConnectionsTimer=new QTimer(this); + itsFontListTimer=new QTimer(this); + connect(itsConnectionsTimer, SIGNAL(timeout()), SLOT(connectionsTimeout())); + connect(itsFontListTimer, SIGNAL(timeout()), SLOT(fontListTimeout())); + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); + + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + theFolders[i].init(FOLDER_SYS==i, isSystem); + + updateFontList(false); +} + +FontInst::~FontInst() +{ + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + theFolders[i].saveDisabled(); +} + +void FontInst::list(int folders, int pid) +{ + KFI_DBUG << folders << pid; + + itsConnections.insert(pid); + updateFontList(false); + QList fonts; + + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + if(0==folders || folders&(1<start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); + emit fontList(pid, fonts); +} + +void FontInst::stat(const QString &name, int folders, int pid) +{ + KFI_DBUG << name << folders << pid; + + bool checkSystem=0==folders || folders&SYS_MASK || isSystem, + checkUser=0==folders || (folders&USR_MASK && !isSystem); + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + + itsConnections.insert(pid); + if( (checkSystem && findFont(name, FOLDER_SYS, fam, st)) || + (checkUser && findFont(name, FOLDER_USER, fam, st, !checkSystem)) ) + { + Family rv((*fam).name()); + rv.add(*st); + KFI_DBUG << "Found font, emit details..."; + emit fontStat(pid, rv); + } + else + { + KFI_DBUG << "Font not found, emit empty details..."; + emit fontStat(pid, Family(name)); + } +} + +void FontInst::install(const QString &file, bool createAfm, bool toSystem, int pid, bool checkConfig) +{ + KFI_DBUG << file << createAfm << toSystem << pid << checkConfig; + + itsConnections.insert(pid); + + if(checkConfig) + updateFontList(); + + EFolder folder=isSystem || toSystem ? FOLDER_SYS : FOLDER_USER; + Family font; + Utils::EFileType type=Utils::check(file, font); + + int result=Utils::FILE_BITMAP==type && !FC::bitmapsEnabled() + ? STATUS_BITMAPS_DISABLED + : Utils::FILE_INVALID==type + ? STATUS_NOT_FONT_FILE + : STATUS_OK; + + if(STATUS_OK==result) + { + if(Utils::FILE_AFM!=type && Utils::FILE_PFM!=type) + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT) && STATUS_OK==result; ++i) + if(theFolders[i].contains(font.name(), (*font.styles().begin()).value())) + result=STATUS_ALREADY_INSTALLED; + + if(STATUS_OK==result) + { + QString name(Misc::modifyName(Misc::getFile(file))), + destFolder(Misc::getDestFolder(theFolders[folder].location(), name)); + + result=Utils::FILE_AFM!=type && Utils::FILE_PFM!=type && Misc::fExists(destFolder+name) ? (int)KIO::ERR_FILE_ALREADY_EXIST : (int)STATUS_OK; + if(STATUS_OK==result) + { + if(toSystem && !isSystem) + { + KFI_DBUG << "Send request to system helper" << file << destFolder << name; + QVariantMap args; + args["method"] = "install"; + args["file"] = file; + args["name"] = name; + args["destFolder"] = destFolder; + args["createAfm"] = createAfm; + args["type"] = (int)type; + result=performAction(args); + } + else + { + if(!Misc::dExists(destFolder)) + result=Misc::createDir(destFolder) ? (int)STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED; + + if(STATUS_OK==result) + result=QFile::copy(file, destFolder+name) ? (int)STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED; + + if(STATUS_OK==result) + { + Misc::setFilePerms(QFile::encodeName(destFolder+name)); + if((Utils::FILE_SCALABLE==type || Utils::FILE_PFM==type) && createAfm) + Utils::createAfm(destFolder+name, type); + } + } + + if(STATUS_OK==result && Utils::FILE_AFM!=type && Utils::FILE_PFM!=type) + { + StyleCont::ConstIterator st(font.styles().begin()); + FileCont::ConstIterator f((*st).files().begin()); + File df(destFolder+name, (*f).foundry(), (*f).index()); + + (*st).clearFiles(); + (*st).add(df); + theFolders[folder].add(font); + theFolders[folder].addModifiedDir(destFolder); + emit fontsAdded(Families(font, FOLDER_SYS==folder)); + } + } + } + } + + emit status(pid, result); + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); +} + +void FontInst::uninstall(const QString &family, quint32 style, bool fromSystem, int pid, bool checkConfig) +{ + KFI_DBUG << family << style << fromSystem << pid << checkConfig; + + itsConnections.insert(pid); + + if(checkConfig) + updateFontList(); + + EFolder folder=isSystem || fromSystem ? FOLDER_SYS : FOLDER_USER; + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST; + + if(STATUS_OK==result) + { + Family del((*fam).name()); + Style s((*st).value(), (*st).scalable(), (*st).writingSystems()); + FileCont files((*st).files()); + FileCont::ConstIterator it(files.begin()), + end(files.end()); + + if(fromSystem && !isSystem) + { + QStringList fileList; + bool wasDisabled(false); + + for(; it!=end; ++it) + { + fileList.append((*it).path()); + theFolders[FOLDER_SYS].addModifiedDir(Misc::getDir((*it).path())); + if(!wasDisabled && Misc::isHidden(Misc::getFile((*it).path()))) + wasDisabled=true; + } + QVariantMap args; + args["method"] = "uninstall"; + args["files"] = fileList; + result=performAction(args); + + if(STATUS_OK==result) + { + FileCont empty; + s.setFiles(files); + (*st).setFiles(empty); + if(wasDisabled) + theFolders[FOLDER_SYS].setDisabledDirty(); + } + } + else + { + for(; it!=end; ++it) + if(!Misc::fExists((*it).path()) || QFile::remove((*it).path())) + { + // Also remove any AFM or PFM files... + QStringList other; + Misc::getAssociatedFiles((*it).path(), other); + QStringList::ConstIterator oit(other.constBegin()), + oend(other.constEnd()); + for(; oit!=oend; ++oit) + QFile::remove(*oit); + + theFolders[folder].addModifiedDir(Misc::getDir((*it).path())); + (*st).remove(*it); + s.add(*it); + if(!theFolders[folder].disabledDirty() && Misc::isHidden(Misc::getFile((*it).path()))) + theFolders[folder].setDisabledDirty(); + } + } + + if(STATUS_OK==result) + { + if((*st).files().isEmpty()) + { + (*fam).remove(*st); + if((*fam).styles().isEmpty()) + theFolders[folder].removeFont(*fam); + } + else + result=STATUS_PARTIAL_DELETE; + del.add(s); + } + emit fontsRemoved(Families(del, FOLDER_SYS==folder)); + + } + KFI_DBUG << "status" << result; + emit status(pid, result); + + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); +} + +void FontInst::uninstall(const QString &name, bool fromSystem, int pid, bool checkConfig) +{ + KFI_DBUG << name << fromSystem << pid << checkConfig; + + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + if(findFont(name, fromSystem || isSystem ? FOLDER_SYS : FOLDER_USER, fam, st)) + uninstall((*fam).name(), (*st).value(), fromSystem, pid, checkConfig); + else + emit status(pid, KIO::ERR_DOES_NOT_EXIST); +} + +void FontInst::move(const QString &family, quint32 style, bool toSystem, int pid, bool checkConfig) +{ + KFI_DBUG << family << style << toSystem << pid << checkConfig; + + itsConnections.insert(pid); + if(checkConfig) + updateFontList(); + + if(isSystem) + emit status(pid, KIO::ERR_UNSUPPORTED_ACTION); + else + { + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + EFolder from=toSystem ? FOLDER_USER : FOLDER_SYS, + to=toSystem ? FOLDER_SYS : FOLDER_USER; + + if(findFont(family, style, from, fam, st)) + { + FileCont::ConstIterator it((*st).files().begin()), + end((*st).files().end()); + QStringList files; + + for(; it!=end; ++it) + { + files.append((*it).path()); + theFolders[from].addModifiedDir(Misc::getDir((*it).path())); + // Actual 'to' folder does not really matter, as we only want to call fc-cache + // ...actual folders only matter for xreating fonts.dir, etc, and we wont be doing this... + theFolders[to].addModifiedDir(theFolders[to].location()); + } + + QVariantMap args; + args["method"] = "move"; + args["files"] = files; + args["toSystem"] = toSystem; + args["dest"] = theFolders[to].location(); + args["uid"] = getuid(); + args["gid"] = getgid(); + int result=performAction(args); + + if(STATUS_OK==result) + updateFontList(); + emit status(pid, result); + } + else + { + KFI_DBUG << "does not exist"; + emit status(pid, KIO::ERR_DOES_NOT_EXIST); + } + } + + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); +} + +static bool renameFontFile(const QString &from, const QString &to, int uid=-1, int gid=-1) +{ + QByteArray src(QFile::encodeName(from)), + dest(QFile::encodeName(to)); + + if(KDE_rename(src.data(), dest.data())) + return false; + + Misc::setFilePerms(dest); + if(-1!=uid && -1!=gid) + ::chown(dest.data(), uid, gid); + return true; +} + +void FontInst::enable(const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig) +{ + KFI_DBUG << family << style << inSystem << pid << checkConfig; + toggle(true, family, style, inSystem, pid, checkConfig); +} + +void FontInst::disable(const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig) +{ + KFI_DBUG << family << style << inSystem << pid << checkConfig; + toggle(false, family, style, inSystem, pid, checkConfig); +} + +void FontInst::removeFile(const QString &family, quint32 style, const QString &file, bool fromSystem, int pid, + bool checkConfig) +{ + KFI_DBUG << family << style << file << fromSystem << pid << checkConfig; + + itsConnections.insert(pid); + + if(checkConfig) + updateFontList(); + + // First find the family/style + EFolder folder=isSystem || fromSystem ? FOLDER_SYS : FOLDER_USER; + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST; + + if(STATUS_OK==result) + { + // Family/style found - now check that the requested file is *within* the same folder as one + // of the files linked to this font... + FileCont files((*st).files()); + FileCont::ConstIterator it(files.begin()), + end(files.end()); + QString dir(Misc::getDir(file)); + + result=KIO::ERR_DOES_NOT_EXIST; + for(; it!=end && STATUS_OK!=result; ++it) + if(Misc::getDir((*it).path())==dir) + result=STATUS_OK; + + if(STATUS_OK==result) + { + // OK, found folder - so can now proceed to delete the file... + if(fromSystem && !isSystem) + { + QVariantMap args; + args["method"] = "removeFile"; + args["file"] = file; + result=performAction(args); + } + else + { + result=Misc::fExists(file) + ? QFile::remove(file) + ? (int)STATUS_OK + : (int)KIO::ERR_WRITE_ACCESS_DENIED + : (int)KIO::ERR_DOES_NOT_EXIST; + } + + if(STATUS_OK==result) + theFolders[folder].addModifiedDir(dir); + } + } + + emit status(pid, result); +} + +void FontInst::reconfigure(int pid, bool force) +{ + KFI_DBUG << pid << force; + bool sysModified(theFolders[FOLDER_SYS].isModified()); + + saveDisabled(); + + KFI_DBUG << theFolders[FOLDER_USER].isModified() << sysModified; + if(!isSystem && (force || theFolders[FOLDER_USER].isModified())) + theFolders[FOLDER_USER].configure(force); + + if(sysModified) + { + if(isSystem) + { + theFolders[FOLDER_SYS].configure(); + } + else + { + QVariantMap args; + args["method"] = "reconfigure"; + performAction(args); + theFolders[FOLDER_SYS].clearModified(); + } + } + + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); + + updateFontList(); + emit status(pid, isSystem ? constSystemReconfigured : STATUS_OK); +} + +QString FontInst::folderName(bool sys) +{ + return theFolders[sys || isSystem ? FOLDER_SYS : FOLDER_USER].location(); +} + +void FontInst::saveDisabled() +{ + if(isSystem) + theFolders[FOLDER_SYS].saveDisabled(); + else + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + if(FOLDER_SYS==i && !isSystem) + { + if(theFolders[i].disabledDirty()) + { + QVariantMap args; + args["method"] = "saveDisabled"; + performAction(args); + theFolders[i].saveDisabled(); + } + } + else + theFolders[i].saveDisabled(); +} + +void FontInst::connectionsTimeout() +{ + bool canExit(true); + + KFI_DBUG << "exiting"; + checkConnections(); + + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + { + if(theFolders[i].disabledDirty()) + canExit=false; + theFolders[i].saveDisabled(); + } + + if(0==itsConnections.count()) + { + if(canExit) + qApp->exit(0); + else // Try again later... + itsConnectionsTimer->start(constConnectionsTimeout); + } +} + +void FontInst::fontListTimeout() +{ + updateFontList(true); + itsFontListTimer->start(constFontListTimeout); +} + +void FontInst::updateFontList(bool emitChanges) +{ + // For some reason just the "!FcConfigUptoDate(0)" check does not always work :-( + FcBool fcModified=!FcConfigUptoDate(0); + + if(fcModified || + theFolders[FOLDER_SYS].fonts().isEmpty() || + (!isSystem && theFolders[FOLDER_USER].fonts().isEmpty()) || + theFolders[FOLDER_SYS].disabledDirty() || + (!isSystem && theFolders[FOLDER_USER].disabledDirty())) + { + KFI_DBUG << "Need to refresh font lists"; + if(fcModified) + { + KFI_DBUG << "Re-init FC"; + if(!FcInitReinitialize()) + KFI_DBUG << "Re-init failed????"; + } + + Folder::Flat old[FOLDER_COUNT]; + + if(emitChanges) + { + KFI_DBUG << "Flatten existing font lists"; + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + old[i]=theFolders[i].flatten(); + } + + saveDisabled(); + + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + theFolders[i].clearFonts(); + + KFI_DBUG << "update list of fonts"; + + FcPattern *pat = FcPatternCreate(); + FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_FAMILY, FC_FAMILYLANG, + FC_WEIGHT, FC_LANG, FC_CHARSET, FC_SCALABLE, +#ifndef KFI_FC_NO_WIDTHS + FC_WIDTH, +#endif + FC_SLANT, FC_INDEX, FC_FOUNDRY, (void*)0); + + FcFontSet *list=FcFontList(0, pat, os); + + FcPatternDestroy(pat); + FcObjectSetDestroy(os); + + theFolders[FOLDER_SYS].loadDisabled(); + if(!isSystem) + theFolders[FOLDER_USER].loadDisabled(); + + if(list) + { + QString home(Misc::dirSyntax(QDir::homePath())); + + for (int i = 0; i < list->nfont; i++) + { + QString fileName(Misc::fileSyntax(FC::getFcString(list->fonts[i], FC_FILE))); + + if(!fileName.isEmpty() && Misc::fExists(fileName)) // && 0!=fileName.indexOf(constDefomaLocation)) + { + QString family, + foundry; + quint32 styleVal; + int index; + qulonglong writingSystems(WritingSystems::instance()->get(list->fonts[i])); + FcBool scalable=FcFalse; + + if(FcResultMatch!=FcPatternGetBool(list->fonts[i], FC_SCALABLE, 0, &scalable)) + scalable=FcFalse; + + FC::getDetails(list->fonts[i], family, styleVal, index, foundry); + FamilyCont::ConstIterator fam=theFolders[isSystem || 0!=fileName.indexOf(home) + ? FOLDER_SYS : FOLDER_USER].addFont(Family(family)); + StyleCont::ConstIterator style=(*fam).add(Style(styleVal)); + FileCont::ConstIterator file=(*style).add(File(fileName, foundry, index)); + + (*style).setWritingSystems((*style).writingSystems()|writingSystems); + if(scalable) + (*style).setScalable(); + } + } + + FcFontSetDestroy(list); + } + + if(emitChanges) + { + KFI_DBUG << "Look for differences"; + for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) + { + KFI_DBUG << "Flatten, and take copies..."; + Folder::Flat newList=theFolders[i].flatten(), + onlyNew=newList; + + KFI_DBUG << "Determine differences..."; + onlyNew.subtract(old[i]); + old[i].subtract(newList); + + KFI_DBUG << "Emit changes..."; + Families families=onlyNew.build(isSystem || i==FOLDER_SYS); + + if(!families.items.isEmpty()) + emit fontsAdded(families); + + families=old[i].build(isSystem || i==FOLDER_SYS); + if(!families.items.isEmpty()) + emit fontsRemoved(families); + } + } + KFI_DBUG << "updated list of fonts"; + } +} + +void FontInst::toggle(bool enable, const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig) +{ + KFI_DBUG; + itsConnections.insert(pid); + + if(checkConfig) + updateFontList(); + + EFolder folder=isSystem || inSystem ? FOLDER_SYS : FOLDER_USER; + FamilyCont::ConstIterator fam; + StyleCont::ConstIterator st; + int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST; + + if(STATUS_OK==result) + { + FileCont files((*st).files()), + toggledFiles; + FileCont::ConstIterator it(files.begin()), + end(files.end()); + QHash movedFonts; + QHash movedAssoc; + QSet modifiedDirs; + + for(; it!=end && STATUS_OK==result; ++it) + { + QString to=Misc::getDir((*it).path())+ + QString(enable ? Misc::unhide(Misc::getFile((*it).path())) + : Misc::hide(Misc::getFile((*it).path()))); + if(to!=(*it).path()) + { + KFI_DBUG << "MOVE:" << (*it).path() << " to " << to; + // If the font is a system font, and we're not root, then just go through the actions here - so + // that we can build the list of changes that would happen... + if((inSystem && !isSystem) || renameFontFile((*it).path(), to)) + { + modifiedDirs.insert(Misc::getDir(enable ? to : (*it).path())); + toggledFiles.insert(File(to, (*it).foundry(), (*it).index())); + // Now try to move an associated AFM or PFM files... + QStringList assoc; + + movedFonts[*it]=to; + Misc::getAssociatedFiles((*it).path(), assoc); + + QStringList::ConstIterator ait(assoc.constBegin()), + aend(assoc.constEnd()); + + for(; ait!=aend && STATUS_OK==result; ++ait) + { + to=Misc::getDir(*ait)+ + QString(enable ? Misc::unhide(Misc::getFile(*ait)) + : Misc::hide(Misc::getFile(*ait))); + + if(to!=*ait) + { + if((inSystem && !isSystem) || renameFontFile(*ait, to)) + { + movedAssoc[*ait]=to; + } + else + { + result=KIO::ERR_WRITE_ACCESS_DENIED; + } + } + } + } + else + { + result=KIO::ERR_WRITE_ACCESS_DENIED; + } + } + } + + if(inSystem && !isSystem) + { + Family toggleFam((*fam).name()); + + toggleFam.add(*st); + QVariantMap args; + args["method"] = "toggle"; + QString xml; + QTextStream str(&xml); + toggleFam.toXml(false, str); + args["xml"] = xml; + args["enable"] = enable; + result=performAction(args); + } + + if(STATUS_OK==result) + { + Family addFam((*fam).name()), + delFam((*fam).name()); + Style addStyle((*st).value(), (*st).scalable(), (*st).writingSystems()), + delStyle((*st).value(), (*st).scalable(), (*st).writingSystems()); + + addStyle.setFiles(toggledFiles); + addFam.add(addStyle); + delStyle.setFiles(files); + delFam.add(delStyle); + (*st).setFiles(toggledFiles); + + theFolders[folder].addModifiedDirs(modifiedDirs); + emit fontsAdded(Families(addFam, FOLDER_SYS==folder)); + emit fontsRemoved(Families(delFam, FOLDER_SYS==folder)); + + theFolders[folder].setDisabledDirty(); + } + else // un-move fonts! + { + QHash::ConstIterator fit(movedFonts.constBegin()), + fend(movedFonts.constEnd()); + QHash::ConstIterator ait(movedAssoc.constBegin()), + aend(movedAssoc.constEnd()); + + for(; fit!=fend; ++fit) + renameFontFile(fit.value(), fit.key().path()); + for(; ait!=aend; ++ait) + renameFontFile(ait.value(), ait.key()); + } + } + emit status(pid, result); + + itsConnectionsTimer->start(constConnectionsTimeout); + itsFontListTimer->start(constFontListTimeout); +} + +void FontInst::addModifedSysFolders(const Family &family) +{ + StyleCont::ConstIterator style(family.styles().begin()), + styleEnd(family.styles().end()); + + for(; style!=styleEnd; ++style) + { + FileCont::ConstIterator file((*style).files().begin()), + fileEnd((*style).files().end()); + + for(; file!=fileEnd; ++file) + theFolders[FOLDER_SYS].addModifiedDir(Misc::getDir((*file).path())); + } +} + +void FontInst::checkConnections() +{ + KFI_DBUG; + QSet::ConstIterator it(itsConnections.begin()), + end(itsConnections.end()); + QSet remove; + + for(; it!=end; ++it) + if(0!=kill(*it, 0)) + remove.insert(*it); + itsConnections.subtract(remove); +} + +bool FontInst::findFontReal(const QString &family, const QString &style, EFolder folder, + FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st) +{ + KFI_DBUG; + Family f(family); + fam=theFolders[folder].fonts().find(f); + if(theFolders[folder].fonts().end()==fam) + return false; + + StyleCont::ConstIterator end((*fam).styles().end()); + for(st=(*fam).styles().begin(); st!=end; ++st) + if(FC::createStyleName((*st).value())==style) + return true; + + return false; +} + +bool FontInst::findFont(const QString &font, EFolder folder, + FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st, + bool updateList) +{ + KFI_DBUG; + QString family, + style; + + decompose(font, family, style); + + if(!findFontReal(family, style, folder, fam, st)) + { + if(updateList) + { + // Not found, so refresh font list and try again... + updateFontList(); + return findFontReal(family, style, folder, fam, st); + } + else + { + return false; + } + } + + return true; +} + +bool FontInst::findFontReal(const QString &family, quint32 style, EFolder folder, + FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st) +{ + KFI_DBUG; + fam=theFolders[folder].fonts().find(Family(family)); + + if(theFolders[folder].fonts().end()==fam) + return false; + else + { + st=(*fam).styles().find(style); + + return (*fam).styles().end()!=st; + } +} + +bool FontInst::findFont(const QString &family, quint32 style, EFolder folder, + FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st, + bool updateList) +{ + KFI_DBUG; + if(!findFontReal(family, style, folder, fam, st)) + { + if(updateList) + { + // Not found, so refresh font list and try again... + updateFontList(); + return findFontReal(family, style, folder, fam, st); + } + else + { + return false; + } + } + return true; +} + +int FontInst::performAction(const QVariantMap &args) +{ + KAuth::Action action("org.kde.fontinst.manage"); + + action.setHelperID("org.kde.fontinst"); + action.setArguments(args); + KFI_DBUG << "Call " << args["method"].toString() << " on helper"; + itsFontListTimer->stop(); + itsConnectionsTimer->stop(); + KAuth::ActionReply reply = action.execute(); + + switch(reply.type()) + { + case KAuth::ActionReply::KAuthError: + KFI_DBUG << "KAuth failed - error code:" << reply.errorCode(); + return KIO::ERR_COULD_NOT_AUTHENTICATE; + case KAuth::ActionReply::HelperError: + KFI_DBUG << "Helper failed - error code:" << reply.errorCode(); + return (int)reply.errorCode(); + } + + KFI_DBUG << "Success!"; + return STATUS_OK; +} + +} diff --git a/kcms/kfontinst/dbus/FontInst.h b/kcms/kfontinst/dbus/FontInst.h new file mode 100644 index 0000000000..1365efda5c --- /dev/null +++ b/kcms/kfontinst/dbus/FontInst.h @@ -0,0 +1,162 @@ +#ifndef FONTINST_H +#define FONTINST_H + +/* + * KFontInst - KDE Font Installer + * + * Copyright 2003-2009 Craig Drummond + * + * ---- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the 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 +#include +#include +#include +#include +#include "Family.h" +#include "Folder.h" +#include "FontinstIface.h" +#include "kfontinst_export.h" + +#define FONTINST_PATH "/FontInst" + +class QTimer; + +namespace KFI +{ + +class KFONTINST_EXPORT FontInst : public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.fontinst") + + public: + + enum EStatus + { + STATUS_OK=0, + STATUS_SERVICE_DIED = KJob::UserDefinedError+500, + STATUS_BITMAPS_DISABLED, + STATUS_ALREADY_INSTALLED, + STATUS_NOT_FONT_FILE, + STATUS_PARTIAL_DELETE, + STATUS_NO_SYS_CONNECTION + }; + + enum EFolder + { + FOLDER_SYS, + FOLDER_USER, + + FOLDER_COUNT + }; + + enum + { + SYS_MASK=0x01, + USR_MASK=0x02 + }; + + static void registerTypes() + { + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType

    &vl3$Mxu_()x8g#^bphEbnnCj<=~a2#DTP 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 SmBuL^?$B1(SF2WmNB$3&mQyJJ literal 0 HcmV?d00001 diff --git a/doc/kcontrol/khotkeys/shortcuts-action-command.png b/doc/kcontrol/khotkeys/shortcuts-action-command.png new file mode 100644 index 0000000000000000000000000000000000000000..2ed9b2bbbd55acb07e1bce021249bb31eb6cb22c GIT binary patch literal 64061 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