/usr/share/pyshared/synaptiks/kde/trayapplication.py is in kde-config-touchpad 0.8.1-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | # -*- coding: utf-8 -*-
# Copyright (c) 2010, 2011, Sebastian Wiesner <lunaryorn@googlemail.com>
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
"""
synaptiks.kde.trayapplication
=============================
Provides a simple system tray application to configure the touchpad.
.. moduleauthor:: Sebastian Wiesner <lunaryorn@googlemail.com>
"""
from __future__ import (print_function, division, unicode_literals,
absolute_import)
import sys
from functools import partial
from PyKDE4.kdecore import KCmdLineArgs, ki18nc, i18nc
from PyKDE4.kdeui import (KUniqueApplication, KStatusNotifierItem,
KConfigDialog, KShortcutsDialog, KMessageBox,
KShortcutsEditor, KShortcut,
KStandardAction, KToggleAction,
KHelpMenu, KIcon, KIconLoader,
KNotification, KConfigSkeleton)
from synaptiks.x11 import Display
from synaptiks.touchpad import Touchpad
from synaptiks.management import TouchpadManager
from synaptiks.config import TouchpadConfiguration, ManagerConfiguration
from synaptiks.kde import make_about_data
from synaptiks.kde.widgets.touchpad import TouchpadConfigurationWidget
from synaptiks.kde.widgets.management import TouchpadManagementWidget
class SynaptiksConfigDialog(KConfigDialog):
"""
Configuration dialog used by the system tray application.
"""
DIALOG_NAME = 'synaptiks-configuration'
def __init__(self, touchpad, touchpad_manager, tray_config, parent=None):
KConfigDialog.__init__(self, parent, self.DIALOG_NAME, tray_config)
self.touchpad_config = TouchpadConfiguration(touchpad)
self.management_config = ManagerConfiguration(touchpad_manager)
self.setFaceType(self.List)
self.touchpad_config_widget = TouchpadConfigurationWidget(
self.touchpad_config, self)
self.management_config_widget = TouchpadManagementWidget(
self.management_config, self)
self.config_widgets = [self.touchpad_config_widget,
self.management_config_widget]
for widget in self.config_widgets:
widget.configurationChanged.connect(self.settingsChangedSlot)
pages = [(self.management_config_widget, 'configure'),
(self.touchpad_config_widget, 'synaptiks')]
for page_widget, page_icon_name in pages:
page = self.addPage(page_widget, page_widget.windowTitle())
page.setIcon(KIcon(page_icon_name))
def hasChanged(self):
return (KConfigDialog.hasChanged(self) or
any(w.is_configuration_changed for w in self.config_widgets))
def isDefault(self):
return (KConfigDialog.isDefault(self) and
any(w.shows_defaults() for w in self.config_widgets))
def updateWidgetsDefault(self):
KConfigDialog.updateWidgetsDefault(self)
for widget in self.config_widgets:
widget.load_defaults()
def updateWidgets(self):
KConfigDialog.updateWidgets(self)
for widget in self.config_widgets:
widget.load_configuration()
def updateSettings(self):
KConfigDialog.updateSettings(self)
for widget in self.config_widgets:
widget.apply_configuration()
self.touchpad_config.save()
self.management_config.save()
class SynaptiksTrayConfiguration(KConfigSkeleton):
"""
Configuration specific for the tray application.
"""
def __init__(self, parent=None):
KConfigSkeleton.__init__(self, 'synaptiksrc', parent)
self.setCurrentGroup('General')
self.addItemBool('Autostart', False, False)
class SynaptiksNotifierItem(KStatusNotifierItem):
def __init__(self, parent=None):
KStatusNotifierItem.__init__(self, parent)
self.setTitle('synaptiks')
self.setIconByName('synaptiks')
self.setCategory(KStatusNotifierItem.Hardware)
self.setStatus(KStatusNotifierItem.Passive)
self.setup_actions()
self._config = SynaptiksTrayConfiguration(self)
try:
self.touchpad = Touchpad.find_first(Display.from_qt())
except Exception as error:
# show an error message
from synaptiks.kde.error import get_localized_error_message
error_message = get_localized_error_message(error)
options = KMessageBox.Options(KMessageBox.Notify |
KMessageBox.AllowLink)
KMessageBox.error(None, error_message, '', options)
# disable all touchpad related actions
for act in (self.touchpad_on_action, self.preferences_action):
act.setEnabled(False)
# disable synaptiks autostart, the user can still start synaptiks
# manually again, if the reason of the error is fixed
self._config.findItem('Autostart').setProperty(False)
self._config.writeConfig()
else:
self.activateRequested.connect(self.show_configuration_dialog)
# setup the touchpad manager
self.setup_manager(self.touchpad)
def setup_actions(self):
self.touchpad_on_action = KToggleAction(
i18nc('@action:inmenu', 'Touchpad on'), self.actionCollection())
self.actionCollection().addAction(
'touchpadOn', self.touchpad_on_action)
self.touchpad_on_action.setGlobalShortcut(
KShortcut(i18nc('Touchpad toggle shortcut', 'Ctrl+Alt+T')))
self.contextMenu().addAction(self.touchpad_on_action)
self.contextMenu().addSeparator()
shortcuts = self.actionCollection().addAction(
KStandardAction.KeyBindings, 'shortcuts')
shortcuts.triggered.connect(self.show_shortcuts_dialog)
self.contextMenu().addAction(shortcuts)
self.preferences_action = self.actionCollection().addAction(
KStandardAction.Preferences, 'preferences')
self.preferences_action.triggered.connect(
self.show_configuration_dialog)
self.contextMenu().addAction(self.preferences_action)
help_menu = KHelpMenu(self.contextMenu(), KCmdLineArgs.aboutData())
self.contextMenu().addMenu(help_menu.menu())
def setup_manager(self, touchpad):
self.touchpad_manager = TouchpadManager(touchpad, self)
ManagerConfiguration.load(self.touchpad_manager)
# transition upon touchpad_on_action
self.touchpad_manager.add_touchpad_switch_action(
self.touchpad_on_action)
# update checked state of touchpad_on_action
self.touchpad_manager.states['on'].assignProperty(
self.touchpad_on_action, 'checked', True)
self.touchpad_manager.states['off'].assignProperty(
self.touchpad_on_action, 'checked', False)
# update the overlay icon
self.touchpad_manager.states['on'].entered.connect(
partial(self.setOverlayIconByName, 'touchpad-off'))
self.touchpad_manager.states['on'].exited.connect(
partial(self.setOverlayIconByName, ''))
# only show notification if the touchpad is permanently switched
# off
self.touchpad_manager.states['off'].entered.connect(
partial(self.notify_touchpad_state, True))
self.touchpad_manager.states['off'].exited.connect(
partial(self.notify_touchpad_state, False))
# and eventually start managing the touchpad
self.touchpad_manager.start()
def notify_touchpad_state(self, is_off=None):
if is_off is None:
is_off = self.touchpad.off
# show a notification
if is_off:
event_id = 'touchpadOff'
text = i18nc('touchpad switched notification',
'Touchpad switched off')
else:
event_id = 'touchpadOn'
text = i18nc('touchpad switched notification',
'Touchpad switched on')
icon = KIconLoader.global_().loadIcon('synaptiks', KIconLoader.Panel)
KNotification.event(event_id, text, icon)
def show_shortcuts_dialog(self):
# The dialog is shown in non-modal form, and consequently must exists
# even after this method returns. So we bind the dialog to the
# instance to keep pythons GC out of business and manually delete the
# dialog once the user closed it
self.shortcuts_dialog = KShortcutsDialog(
KShortcutsEditor.GlobalAction,
KShortcutsEditor.LetterShortcutsDisallowed)
self.shortcuts_dialog.addCollection(self.actionCollection())
# delete the dialog manually once the user closed it, to avoid some
# mysterious crashes when quitting the application
self.shortcuts_dialog.finished.connect(
self.shortcuts_dialog.deleteLater)
self.shortcuts_dialog.configure()
def show_configuration_dialog(self):
self.config_dialog = SynaptiksConfigDialog(
self.touchpad, self.touchpad_manager, self._config)
self.config_dialog.finished.connect(self.config_dialog.deleteLater)
self.config_dialog.show()
class SynaptiksApplication(KUniqueApplication):
_first_instance = True
def newInstance(self):
if self._first_instance:
self.setQuitOnLastWindowClosed(False)
# create and show the status icon on first startup
self.icon = SynaptiksNotifierItem()
self.aboutToQuit.connect(self.icon.deleteLater)
self._first_instance = False
else:
# show the configuration dialog in an already running existing
# instance
self.icon.show_configuration_dialog()
return 0
def main():
about = make_about_data(ki18nc('tray application description',
'touchpad management application'))
KCmdLineArgs.init(sys.argv, about)
KUniqueApplication.addCmdLineOptions()
if not KUniqueApplication.start():
return
app = SynaptiksApplication()
app.exec_()
if __name__ == '__main__':
main()
|