diff options
Diffstat (limited to 'powermanager/guidance-power-manager.py')
-rwxr-xr-x | powermanager/guidance-power-manager.py | 1147 |
1 files changed, 0 insertions, 1147 deletions
diff --git a/powermanager/guidance-power-manager.py b/powermanager/guidance-power-manager.py deleted file mode 100755 index aeccf2f..0000000 --- a/powermanager/guidance-power-manager.py +++ /dev/null @@ -1,1147 +0,0 @@ -#!/usr/bin/python -# -*- coding: UTF-8 -*- -""" -Copyright 2006-2007 Sebastian Kügler, Canonical Ltd, Luka Renko - -Authors: - Sebastian Kügler <sebas@kde.org> - Jonathan Riddell <jriddell@ubuntu.com> - Luka Renko <lure@kubuntu.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. - -""" - -""" -A frontend to HAL's power features for KDE. -Supports screen brightness, battery level, plugged/unplugged notices, laptop lid closing actions -Specification at https://wiki.kubuntu.org/KubuntuPowerManagement - -Issues: - - We have to keep polling HAL rather than listening for signals because the Python DBUS bindings - don't have TQt mainloop integration - - Written in Python so will be slow to load up, will probably port to C++ TQt 4.2 in future - - Should also handle UPS and bluetooth batteries - - systray applet should be hidden if no battery, but then how do you suspend if no battery? - (ksmserver integration please) - - Needs lots more testing - - Use KUniqueApplication again as soon as dcop problem is sorted outc - - dcop calls need patch to dcopexport.py, already submitted upstream -""" - -import sys -import os -import os.path -# Trinity-specific paths -tqt_modules = [] -for m_path in sys.path: - if os.path.exists(os.path.join(m_path, 'sip4_tqt')): - m_sip_dir = os.path.join(m_path, 'sip4_tqt') - tqt_modules.insert(0, m_sip_dir) - if os.path.exists(os.path.join(m_path, 'python_tqt')): - m_pyqt_dir = os.path.join(m_path, 'python_tqt') - tqt_modules.insert(0, m_pyqt_dir) -for m_path in tqt_modules: - sys.path.insert(0, m_path) - -import subprocess -import dbus - -from qt import * -from tdecore import * -from tdeui import * - -from dcopext import DCOPClient, DCOPApp # used to lock the screen -from dcopexport import DCOPExObj - -from guidance_power_manager_ui import PowerManagerUI -from notify import NotifyWidget -from tooltip import ToolTip - -from powermanage import * - -POLL_INTERVAL = 5000 # in milliseconds - -class Notify(NotifyWidget): - """ Pop up a passive notication windows. """ - - def __init__(self,parent,msg,icon,caption=None): - NotifyWidget.__init__(self,parent,"notify") - self.setIcon(icon) - self.setText(msg) - if caption: - self.Caption(caption) - - def setIcon(self,pixmap): - """ Set an icon to be displayed in the notification. """ - if pixmap: - self.Icon.setPixmap(pixmap) - - def setCaption(self,caption): - """ Text to show in bold letters. """ - self.Caption.setText(TQString("<b>")+caption+QString("</b>")) - - def setText(self,msg): - """" Set actual notification message. """ - self.Text.setText(msg) - - -class PowerManager(PowerManagerUI): - """ Our configuration dialog. """ - - def __init__ (self, parent, name): - PowerManagerUI.__init__(self, parent, name) - TDEGlobal.iconLoader().addAppDir("guidance") - - # The systray icon should show and hide the KDialogBase, not only this widget, - # therefore, it gets our parent as parent. - self.systray = KSystemTray(parent) - self.icon = "battery-charging-100" - self.systray.setPixmap(TQPixmap(UserIcon(self.icon))) - self.connect(self.systray, SIGNAL("quitSelected()"), self.quit) - - # Configuration filename - self.config = TDEConfig("power-managerrc") - - self.powermanager = PowerManage() - - def prepare(self): - """ Prepare UI. """ - self._initBrightness() - self._initLid() - self._initBattery() - self.lastidlesec = 0 - - self._initConfigKeywords() - - self._initUI(self.parent()) - - self.configToUi() - - # Polling: evil. can't receive signals in python-dbus unless we have a glib mainloop, - # so we need to poll - self.pollTimer = TQTimer(self) - self.connect(self.pollTimer, SIGNAL("timeout()"), self.poll) - self.pollTimer.start(POLL_INTERVAL) # 5 second poll, maybe make this configurable - self.poll(False) - - # check CPU freq policy and notify if it was changed - msg = self.checkCpuFreq() - if msg != "": - self.notify(msg) - - self.systray.show() - - def _initBrightness(self): - """ Check for brightness support and disable widgets if it's not there. """ - if not self.powermanager.hasBrightness: - self.PoweredBrightnessLabel.hide() - self.PoweredBrightnessSlider.hide() - self.BatteryBrightnessLabel.hide() - self.BatteryBrightnessSlider.hide() - - def _initLid(self): - """ Check for lid support and disable widgets if it's not there. """ - if not self.powermanager.hasLid: - self.LaptopLidRadios.setEnabled(False) - - def _initCB(self, combo, options, values): - """ Initialize TQComboBox with proper values from provided options. """ - combo.clear() - for option in options: - combo.insertItem(values[option]) - - def _getCB(self, combo, options): - """ Get current item from TQComboBox from config file (string) value. """ - try: - return options[combo.currentItem()] - except IndexError: - return "" - - def _setCB(self, combo, options, default, value): - """ Set current item in TQComboBox from string value. """ - try: - num = options.index(value) - except ValueError: - num = default - pass - combo.setCurrentItem(num) - - def _getRB(self, radios, options): - """ Get current item from TQRadioButton from config file (string) value. """ - try: - return options[radios.selectedId()] - except IndexError: - return "" - - def _setRB(self, radios, options, default, value): - """ Set current item in TQRadioButton from string value. """ - try: - num = options.index(value) - except ValueError: - num = default - pass - radios.setButton(num) - - def _checkOldConfig(self, value, blank): - """ Convert old numerical values to keywords. """ - try: - num_val = int(value) - except ValueError: - return value - if blank: - if num_val == 0: return 'nothing' - if num_val == 1: return 'blank' - if num_val == 2: return 'suspend' - if num_val == 3: return 'hibernate' - if num_val == 4: return 'shutdown' - else: - if num_val == 0: return 'nothing' - if num_val == 1: return 'suspend' - if num_val == 2: return 'hibernate' - if num_val == 3: return 'shutdown' - return value - - - def _initConfigKeywords(self): - """ Define helper maps used with config file keywords. """ - # map action keyword to displayed name (l10n) - self.act_name = {} - self.act_name['nothing'] = i18n("Do nothing") - self.act_name['blank'] = i18n("Blank screen") - self.act_name['suspend'] = i18n("Suspend") - self.act_name['hibernate'] = i18n("Hibernate") - self.act_name['shutdown'] = i18n("Shutdown") - - # map action keyword to action methods - self.act_call = {} - self.act_call['nothing'] = None - self.act_call['blank'] = self.blankScreen - self.act_call['suspend'] = self.suspend - self.act_call['hibernate'] = self.hibernate - self.act_call['shutdown'] = self.shutdown - - # map action keyword to notification description (l10n) - self.act_notify = {} - self.act_notify['nothing'] = i18n("doing nothing") - self.act_notify['blank'] = i18n("blanking screen") - self.act_notify['suspend'] = i18n("suspending") - self.act_notify['hibernate'] = i18n("hibernating") - self.act_notify['shutdown'] = i18n("shutting down") - - # map action keyword to action icon used in notification window - self.act_icon = {} - self.act_icon['nothing'] = None - self.act_icon['blank'] = None - self.act_icon['suspend'] = SmallIcon("suspend") - self.act_icon['hibernate'] = SmallIcon("hibernate") - self.act_icon['shutdown'] = SmallIcon("exit") - - # map policy keyword to displayed name (l10n) - self.freq_name = {} - self.freq_name['dynamic'] = i18n("Dynamic") - self.freq_name['powersave'] = i18n("Powersave") - self.freq_name['performance'] = i18n("Performance") - - # map policy keyword to policy change methods - self.freq_call = {} - self.freq_call['dynamic'] = self.setCpuPolicyDynamic - self.freq_call['powersave'] = self.setCpuPolicyPowersave - self.freq_call['performance'] = self.setCpuPolicyPerformance - - - def _initUI(self, parent): - """ Build dynamic parts of the UI: context menu and tooltip. """ - self.canSuspend = self.powermanager.canSuspend and not self.config.readBoolEntry("disableSuspend", False) - self.canHibernate = self.powermanager.canHibernate and not self.config.readBoolEntry("disableHibernate", False) - - # Connect some signals. Updates in the dialogue apply instantly - self.connect(self.PoweredBrightnessSlider, SIGNAL("valueChanged(int)"), self.changePoweredBrightness) - self.connect(self.BatteryBrightnessSlider, SIGNAL("valueChanged(int)"), self.changeBatteryBrightness) - - #Add a blank tooltip, the tooltipgroup signals are then used for our KPassivePopup - toolTipGroup = TQToolTipGroup(self.systray) - TQToolTip.add(self.systray, "", toolTipGroup, "blah") - self.connect(toolTipGroup, SIGNAL("showTip(const TQString&)"), self.showTip) - self.connect(toolTipGroup, SIGNAL("removeTip()"), self.hideTip) - - # Popup tooltip showing battery level - self.popup = KPassivePopup(self.systray) - - self.tooltip = ToolTip(self.popup) - - self._addBatteryWidgets() - - self._addCpuWidgets() - self.popup.setView(self.tooltip) - - # fill actions for LID - self.lid_act = ['nothing', 'blank', 'suspend', 'hibernate', 'shutdown'] - self.lid_act_def = 0 - # hide LID close actions that are not supported - if not self.canSuspend: - self.laptopClosedSuspend.hide() - if not self.canHibernate: - self.laptopClosedHibernate.hide() - - # fill in only CPU policies that are supported by HW - self.cb_freq = [] # list of supported cpu freq policies - self.cb_freq_def = 0 # always use first policy as default - if self.powermanager.hasCpuFreqGovernors: - self.cb_freq = self.powermanager.getSupportedCpuPolicies() - if len(self.cb_freq) > 0: - self._initCB(self.PoweredFreqCombo, self.cb_freq, self.freq_name) - self._initCB(self.BatteryFreqCombo, self.cb_freq, self.freq_name) - else: - self.PoweredFreqLabel.hide() - self.PoweredFreqCombo.hide() - self.BatteryFreqLabel.hide() - self.BatteryFreqCombo.hide() - - # fill actions in Idle/Critical battery combo boxes - self.cb_act = ['nothing'] # list of supported actions (keywords) - self.cb_act_def_critical = 0 # default action when critical battery - if self.canSuspend: - self.cb_act.append('suspend') - if self.canHibernate: - self.cb_act.append('hibernate') - self.cb_act_def_critical = len(self.cb_act) - 1 # hibernate - self.cb_act.append('shutdown') - if self.cb_act_def_critical == 0: - self.cb_act_def_critical = len(self.cb_act) - 1 # shutdown - self._initCB(self.PoweredIdleCombo, self.cb_act, self.act_name) - self._initCB(self.BatteryIdleCombo, self.cb_act, self.act_name) - self._initCB(self.BatteryCriticalCombo, self.cb_act, self.act_name) - - self.connect(self.PoweredIdleCombo,SIGNAL("activated(int)"),self.slotPoweredIdleActivated) - self.connect(self.BatteryIdleCombo,SIGNAL("activated(int)"),self.slotBatteryIdleActivated) - self.connect(self.BatteryCriticalCombo,SIGNAL("activated(int)"),self.slotBatteryCriticalActivated) - - # add suspend/hibernate to tray's context menu - menu = self.systray.contextMenu() - if self.canSuspend: - action = TDEAction( i18n("Suspend"), TDEShortcut(), self.suspend, - self.systray.actionCollection(), "suspend") - action.setIcon("suspend") - action.plug(menu) - if self.canHibernate: - action = TDEAction( i18n("Hibernate"), TDEShortcut(), self.hibernate, - self.systray.actionCollection(), "hibernate") - action.setIcon("hibernate") - action.plug(menu) - - # add list of governators - if self.powermanager.hasCpuFreqGovernors and len(self.cb_freq) > 0: - submenu = TDEPopupMenu(menu) - for policy in self.cb_freq: - action = TDERadioAction(self.freq_name[policy], TDEShortcut(), - self.freq_call[policy], - self.systray.actionCollection(), policy) - action.setExclusiveGroup("freqs") - action.plug(submenu) - - policy = self.powermanager.getCpuPolicy() - if policy in self.cb_freq: - self.systray.actionCollection().action(policy).setChecked(True); - menu.insertItem(i18n("CPU policy"), submenu) - - - # TDEGlobalAccel crashes the application in pytde - # see http://mats.gmd.de/pipermail/pytde/2006-May/013224.html - #self.globalActions = TDEGlobalAccel(self) - #self.suspendShortcut = TDEShortcut("XF86Sleep") - #self.hibernateShortcut = TDEShortcut("XF86Standby") - #self.hshutdownShortcut = TDEShortcut("XF86PowerOff") - #self.globalActions.insert("suspend", i18n("Suspend"), i18n("what's this?"), self.suspendShortcut, #self.suspendShortcut, self.suspend) - #self.globalActions.updateConnections() - - def _initBattery(self): - """ Remove non-battery-related widgets if there's no battery bay. """ - if not self.powermanager.hasBattery: - # Disable the Batterybox in the config dialogue, - self.BatteryBox.setEnabled(False) - # And change the icon in the systray, remove the restore option - # This way, we're basically becoming a systray applet, you can - # hibernate and suspend from - self.systray.setPixmap(TQPixmap(UserIcon(self.icon))) - if self.powermanager.hasAC: - self.wasOnBattery = self.powermanager.onBattery() - - def configToUi(self): - """ Setup the the values from the config file in the UI.""" - # brightness. - if self.powermanager.hasBrightness: - brightness_high = self.powermanager.brightness_levels - self.BatteryBrightnessSlider.setMaxValue(self.powermanager.brightness_levels-1) - self.PoweredBrightnessSlider.setMaxValue(self.powermanager.brightness_levels-1) - self.BatteryBrightnessSlider.setValue(self.config.readNumEntry("batteryBrightness", int(brightness_high/2))) #default middle - self.PoweredBrightnessSlider.setValue(self.config.readNumEntry("poweredBrightness", brightness_high)) #default highest - - tt_text = "Every step increases or decreases the brightness by %i%%" % int(100/brightness_high) - TQToolTip.add(self.BatteryBrightnessSlider, tt_text) - TQToolTip.add(self.PoweredBrightnessSlider, tt_text) - - self.lockScreenOnResume.setChecked(self.config.readBoolEntry("lockOnResume", True)) - - # Idletime-related configuration - self._setCB(self.PoweredIdleCombo, self.cb_act, 0, str(self.config.readEntry("poweredIdleAction"))) - self.PoweredIdleTime.setValue(self.config.readNumEntry("poweredIdleTime", 60)) - self._setCB(self.BatteryIdleCombo, self.cb_act, 0, str(self.config.readEntry("batteryIdleAction"))) - self.BatteryIdleTime.setValue(self.config.readNumEntry("batteryIdleTime", 10)) - - self._setCB(self.PoweredFreqCombo, self.cb_freq, self.cb_freq_def, str(self.config.readEntry("poweredFreqPolicy"))) - self._setCB(self.BatteryFreqCombo, self.cb_freq, self.cb_freq_def, str(self.config.readEntry("batteryFreqPolicy"))) - - self.BatteryIdleTime.setValue(self.config.readNumEntry("batteryIdleTime", 10)) # default Do nothing - # battery critical and lid actions. - self._setCB(self.BatteryCriticalCombo, self.cb_act, self.cb_act_def_critical, self._checkOldConfig(self.config.readEntry("batteryCriticalAction", ""), False)) - self._setRB(self.LaptopLidRadios, self.lid_act, self.lid_act_def, self._checkOldConfig(self.config.readEntry("laptopLidAction", ""), True)) - self.CriticalRemainTime.setValue(self.config.readNumEntry("criticalRemainTime", BATTERY_CRITICAL_MINUTES)) - self.criticalLevel = self.CriticalRemainTime.value() - - # Call some slots to disable various spinboxes if necessary - self.slotBatteryCriticalActivated() - self.slotPoweredIdleActivated() - self.slotBatteryIdleActivated() - - - def uiToConfig(self): - """ Read all values from the UI and write them to the config file. """ - self.config.writeEntry("poweredBrightness", self.PoweredBrightnessSlider.value()) - self.config.writeEntry("batteryBrightness", self.BatteryBrightnessSlider.value()) - - self.config.writeEntry("poweredIdleTime", self.PoweredIdleTime.value()) - self.config.writeEntry("poweredIdleAction", self._getCB(self.PoweredIdleCombo, self.cb_act)) - self.config.writeEntry("batteryIdleTime", self.BatteryIdleTime.value()) - self.config.writeEntry("batteryIdleAction", self._getCB(self.BatteryIdleCombo, self.cb_act)) - self.config.writeEntry("poweredFreqPolicy", self._getCB(self.PoweredFreqCombo, self.cb_freq)) - self.config.writeEntry("batteryFreqPolicy", self._getCB(self.BatteryFreqCombo, self.cb_freq)) - - self.config.writeEntry("batteryCriticalAction", self._getCB(self.BatteryCriticalCombo, self.cb_act)) - self.config.writeEntry("criticalRemainTime", self.CriticalRemainTime.value()) - - self.config.writeEntry("laptopLidAction", self._getRB(self.LaptopLidRadios, self.lid_act)) - self.config.writeEntry("lockOnResume", self.lockScreenOnResume.isChecked()) - - self.criticalLevel = self.CriticalRemainTime.value() - - self.config.sync() - - def quit(self): - """ TQuit application. """ - kapp.quit() - - def showTip(self, text=""): - """ Pop up the tooltip showing battery data and CPU frequencies. """ - self.popup.show() - - - def showBrightnessPopup(self): - if self.powermanager.onBattery(): - value=self.BatteryBrightnessSlider.value()*100/self.BatteryBrightnessSlider.maxValue() - else: - value=self.PoweredBrightnessSlider.value()*100/self.PoweredBrightnessSlider.maxValue() - self.brightnessPopup = KPassivePopup.message('<b>Brightness:</b> '+str(value)+'%', self.systray) - """pop.setTimeout(3000)""" - self.brightnessPopup.show() - - def setBrightnessUp(self): - """Increments slider value by 10%""" - if self.powermanager.onBattery(): - self.BatteryBrightnessSlider.setValue(float(self.BatteryBrightnessSlider.value())+max(float(self.BatteryBrightnessSlider.maxValue())/float(10),1)) - else: - self.PoweredBrightnessSlider.setValue(float(self.PoweredBrightnessSlider.value())+max(float(self.PoweredBrightnessSlider.maxValue())/float(10),1)) - self.showBrightnessPopup() - - def setBrightnessDown(self): - """Decrements slider value by 10%""" - if self.powermanager.onBattery(): - self.BatteryBrightnessSlider.setValue(float(self.BatteryBrightnessSlider.value())-max(float(self.BatteryBrightnessSlider.maxValue())/float(10),1)) - else: - self.PoweredBrightnessSlider.setValue(float(self.PoweredBrightnessSlider.value())-max(float(self.PoweredBrightnessSlider.maxValue())/float(10),1)) - self.showBrightnessPopup() - - def getBrightness(self): - """Work with percentages - it's a bit nicer""" - if self.powermanager.onBattery(): - value=self.BatteryBrightnessSlider.value()*100/self.BatteryBrightnessSlider.maxValue() - else: - value=self.PoweredBrightnessSlider.value()*100/self.PoweredBrightnessSlider.maxValue() - return TQString(str(value)) - - def hideTip(self): - """ Hide the tooltip.""" - self.popup.hide() - - def lockScreen(self): - """ locks the screen using kdesktop """ - # create a new DCOP-Client: - client = DCOPClient() - # connect the client to the local DCOP-server: - client.attach() - # create a DCOP-Application-Object to talk to kdesktop: - kdesktop = DCOPApp('kdesktop', client) - # call a DCOP-function: - try: - ok, foo = kdesktop.KScreensaverIface.lock() - except: - print "Unable to lock the screen. The KDE Screensaver does not seem to be running." - def suspend(self): - """ Lock the screen and initiate a suspend to RAM (S3). """ - if self.config.readBoolEntry("lockOnResume", True): - self.lockScreen() - try: - self.warningPopup.hide() - except AttributeError: - pass # No warningpopup, that's OK. - self.powermanager.suspend() - self.powermanager.resetIdleSeconds() - - def hibernate(self): - """ Lock the screen and initiate a suspend to disk (S4). """ - if self.config.readBoolEntry("lockOnResume", True): - self.lockScreen() - try: - self.warningPopup.hide() - except AttributeError: - pass # No warningpopup, that's OK. - self.powermanager.hibernate() - self.powermanager.resetIdleSeconds() - - def shutdown(self): - """ Perform system shutdown. """ - self.powermanager.shutdown() - - def setCpuPolicyDynamic(self): - """Change frequ for all cpu""" - self.powermanager.setCpuPolicy('dynamic') - self.notify(i18n("CPU frequency policy changed to %1.").arg(self.freq_name['dynamic'])) - - def setCpuPolicyPerformance(self): - """Change frequ for all cpu""" - self.powermanager.setCpuPolicy('performance') - self.notify(i18n("CPU frequency policy changed to %1.").arg(self.freq_name['performance'])) - - def setCpuPolicyPowersave(self): - """Change frequ for all cpu""" - self.powermanager.setCpuPolicy('powersave') - self.notify(i18n("CPU frequency policy changed to %1.").arg(self.freq_name['powersave'])) - - def trySuspend(self): - """ If supported, lock the screen and initiate a suspend to RAM (S3). """ - if self.canSuspend: - self.suspend() - else: - print "Warning: DCOP suspend() called, but not supported." - - def tryHibernate(self): - """ If supported, lock the screen and initiate a suspend to disk (S4). """ - if self.canHibernate: - self.hibernate() - else: - print "Warning: DCOP hibernate() called, but not supported." - - def blankScreen(self): - """ Lock and blank screen. """ - if self.config.readBoolEntry("lockOnResume", True): - self.lockScreen() - self.powermanager.blankScreen() - - def _getIcon(self): - """ Set systray icon depending on battery status/level. """ - if self.powermanager.hasBattery: - if self.batt_state == "not present": - self.icon = "ac-adapter" - if self.batt_state == "charged": - self.icon = "battery-charging-100" - elif self.batt_state == "discharging": - if self.batt_level >= 95: - self.icon = "battery-discharging-100" - elif self.batt_level < 95 and self.batt_level >= 85: - self.icon = "battery-discharging-090" - elif self.batt_level < 85 and self.batt_level >= 75: - self.icon = "battery-discharging-070" - elif self.batt_level < 75 and self.batt_level >= 60: - self.icon = "battery-discharging-060" - elif self.batt_level < 65 and self.batt_level >= 45: - self.icon = "battery-discharging-050" - elif self.batt_level < 45 and self.batt_level >= 30: - self.icon = "battery-discharging-040" - elif self.batt_level < 30 and self.batt_level >= 20: - self.icon = "battery-discharging-030" - elif self.batt_level < 20 and self.batt_level >= 10: - self.icon = "battery-discharging-020" - elif self.batt_level < 10 and self.batt_level >= 5: - self.icon = "battery-discharging-010" - else: - self.icon = "battery-discharging-000" - elif self.batt_state == "charging": - if self.batt_level >= 95: - self.icon = "battery-charging-100" - elif self.batt_level < 95 and self.batt_level >= 85: - self.icon = "battery-charging-090" - elif self.batt_level < 85 and self.batt_level >= 75: - self.icon = "battery-charging-070" - elif self.batt_level < 75 and self.batt_level >= 60: - self.icon = "battery-charging-060" - elif self.batt_level < 65 and self.batt_level >= 45: - self.icon = "battery-charging-050" - elif self.batt_level < 45 and self.batt_level >= 30: - self.icon = "battery-charging-040" - elif self.batt_level < 30 and self.batt_level >= 20: - self.icon = "battery-charging-030" - elif self.batt_level < 20 and self.batt_level >= 10: - self.icon = "battery-charging-020" - elif self.batt_level < 10 and self.batt_level >= 5: - self.icon = "battery-charging-010" - else: - self.icon = "battery-charging-000" - else: - self.icon = "ac-adapter" - return self.icon - - def getIcon(self): - """ Return current icon.""" - return UserIcon(self.icon) - - def setIcon(self): - """ Change the systray/tooltip icon.""" - oldIcon = self.icon - self.icon = self._getIcon() - if self.icon != oldIcon: - self.systray.setPixmap(TQPixmap(UserIcon(self.icon))) - self.BattPixmap.setPixmap(TQPixmap(UserIcon(self.icon))) - - def notify(self, msg, icon=None): - """ Send a notification popup. """ - if icon: - icon = TQPixmap(icon) - else: - icon = TQPixmap(SmallIcon("messagebox_info")) - try: - del self.warningPopup - except: - pass - self.warningPopup = KPassivePopup(self.systray) - label = Notify(self.warningPopup, msg, icon) - self.warningPopup.setView(label) - position = TQPoint(5,5) - self.warningPopup.show(position) - - def poll(self,notify=True): - """ Check for changes in plugged in status, battery status and laptop lid closed status. """ - debug( "------------ POLL ---------------") - - self.powermanager.checkHAL() - # Battery stuff: - # check for last state, and run plugged / unplugged message if the state changed. - if self.powermanager.hasBattery: - plugged_num = 0 - self.batt_state = "not present" # unknown yet - self.batt_level = self.batt_remain = 0 - self.batt_rate = self.batt_charge = self.batt_full = 0 - for batt in self.powermanager.batteries: - state, level, remain, rate, current, full = self.powermanager.getBatteryState(batt) - self._updateBatteryWidget(batt, state, level, remain, rate) - - ## notify plugged/unplugged batteries - if state == "not present": - if self.powermanager.batteryIsPresent[batt]: - self.notify(i18n("The battery has been removed.")) - self.powermanager.batteryIsPresent[batt] = False - else: # battery present - if not self.powermanager.batteryIsPresent[batt]: - self.notify(i18n("The battery has been inserted.")) - self.powermanager.batteryIsPresent[batt] = True - - ## get cumulative charge levels/rate - self.batt_rate += rate - self.batt_charge += current - self.batt_full += full - - ## calculate overall level (average of present batteries) - self.batt_remain += remain - self.batt_level += level - plugged_num += 1 - - ## calculate overall state (charging/discharging/charged) - if state in ("charging","discharging"): - self.batt_state = state - elif not self.batt_state in ("charging, discharging"): - self.batt_state = state - - # if we know charge and full -> recalculate overall level - if self.batt_full > 0 and self.batt_charge > 0: - self.batt_level = 100 * self.batt_charge / self.batt_full - else: - # if more than one battery present, we need to calculate average level - if plugged_num > 1: - self.batt_level /= plugged_num - - # if rate is reported, calculate remaining time on our own - if self.batt_rate > 0: - if self.batt_state == "charging": - self.batt_remain = 3600 * (float(self.batt_full - self.batt_charge) / self.batt_rate) - if self.batt_state == "discharging": - self.batt_remain = 3600 * (float(self.batt_charge) / self.batt_rate) - - remain_h = self.batt_remain/3600 - remain_m = (self.batt_remain/60)%60 - - blabel = i18n("<b>Battery:</b>") - if self.batt_state == "charged": - blabel += i18n(" fully charged") - elif self.batt_state == "charging": - blabel += i18n(" %i:%02ih to charge" % (remain_h,remain_m)) - elif self.batt_state == "discharging": - blabel += i18n(" %i:%02ih remaining" % (remain_h,remain_m)) - self.BattMainLabel.setText(blabel) - - # update tray icon if needed - self.setIcon() - - # check battery state - self.checkBatteryCritical() - - # check Idletime - self.checkIdletime() - - # CPU stuff - self._updateCpuWidgets() - - if self.powermanager.hasBattery: - on_battery = self.powermanager.onBattery() - if self.powermanager.wasOnBattery != on_battery: - self.powermanager.wasOnBattery = on_battery - debug("poll: states differ") - if not on_battery: - debug("poll: Now on AC") - if notify: - self.powerHasBeenPlugged() - else: - debug("poll: Now on battery") - if notify: - self.powerHasBeenUnplugged() - else: - debug("poll: state is the same") - - # Lid stuff - if self.powermanager.hasLid: - if self.powermanager.getLidClosedState(): - if not self.powermanager.lidClosedState: - self.powermanager.lidClosedState = True - - action = self._getRB(self.LaptopLidRadios, self.lid_act) - if not self.act_name.has_key(action): - action = self.act_name[self.lid_act_def] - - if self.act_call[action] != None: - note = i18n("Laptop lid is closed, %1 now.").arg(self.act_notify[action]) - self.notify(note, self.act_icon[action]) - TQTimer.singleShot(2000, self.act_call[action]) - else: - self.powermanager.lidClosedState = False - - def _addBatteryWidgets(self): - """ Adds progressbars to show battery status to the tooltip.""" - BattLayout = TQHBoxLayout(None,0,6,"BattLayout") - - self.BattPixmap = TQLabel(self.tooltip,"BattLabLayout") - self.BattPixmap.setSizePolicy(TQSizePolicy(TQSizePolicy.Fixed,TQSizePolicy.Fixed,0,0,self.BattPixmap.sizePolicy().hasHeightForWidth())) - self.BattPixmap.setPixmap(TQPixmap(UserIcon(self.icon))) - self.BattPixmap.setScaledContents(1) - BattLayout.addWidget(self.BattPixmap) - self.BattMainLabel = TQLabel(self.tooltip,"BattMainLabel") - self.BattMainLabel.setText(i18n("<b>Battery:</b>")) - BattLayout.addWidget(self.BattMainLabel) - - # Add to tooltip - self.tooltip.layout().addLayout(BattLayout) - - # Create a progressbar and a label for every battery found, and add it to tooltip - self.BattLabel = {} - self.BattLayout = {} - self.BattProgress = {} - i = 1 - for batt in self.powermanager.batteries: - self.BattLayout[batt] = TQHBoxLayout(None,0,6,"BattBarLayout") - self.BattLabel[batt] = TQLabel(self.tooltip,"BattLabel") - if len(self.powermanager.batteries) > 1: - self.BattLabel[batt].setText(i18n("Battery %i" % i)) - self.BattLayout[batt].addWidget(self.BattLabel[batt]) - self.BattProgress[batt] = KProgress(self.tooltip,"BattProgress") - self.BattProgress[batt].setMinimumSize(TQSize(200,0)) - self.BattLayout[batt].addWidget(self.BattProgress[batt]) - self.tooltip.layout().addLayout(self.BattLayout[batt]) - i += 1 - - - def _updateBatteryWidget(self, batt, state, level, remain, rate): - """ Retrieve battery information and update the related widgets accordingly. """ - self.BattProgress[batt].setEnabled(True) - self.BattProgress[batt].setTotalSteps(100) - self.BattProgress[batt].setProgress(level) - if state == "not present": - self.BattProgress[batt].setFormat(i18n("not present")) - elif state == "charging": - self.BattProgress[batt].setFormat(i18n("Charging (%p%)")) - elif state == "discharging": - if rate > 0: - showrate = rate/1000 - self.BattProgress[batt].setFormat(i18n("Discharging (%p%)") + " - %.d W" % showrate) - else: - self.BattProgress[batt].setFormat(i18n("Discharging (%p%)")) - else: - self.BattProgress[batt].setFormat("%p%") - - def _addCpuWidgets(self): - """ Adds progressbars to show CPU frequencies to the tooltip.""" - if not SHOW_CPUFREQ: - return - if len(self.powermanager.cpus) == 0: - return - - LabelLayout = TQHBoxLayout(None,0,6,"layout5") - - self.CpuPixmap = TQLabel(self.tooltip,"CpuPixmap") - self.CpuPixmap.setSizePolicy(TQSizePolicy(TQSizePolicy.Fixed,TQSizePolicy.Fixed,0,0,self.CpuPixmap.sizePolicy().hasHeightForWidth())) - self.CpuPixmap.setPixmap(TQPixmap(UserIcon("processor"))) - self.CpuPixmap.setScaledContents(1) - LabelLayout.addWidget(self.CpuPixmap) - self.CpuMainLabel = TQLabel(self.tooltip,"CpuMainLabel") - self.CpuMainLabel.setText(i18n("<b>CPU Frequency:</b>")) - LabelLayout.addWidget(self.CpuMainLabel) - - # Add to tooltip - self.tooltip.layout().addLayout(LabelLayout) - - # Create a progressbar and a label for every CPU found, and add it to tooltip - self.CpuLabel = {} - self.CpuLayout = {} - self.CpuProgress = {} - i = 1 - for cpu in self.powermanager.cpus: - self.CpuLayout[cpu] = TQHBoxLayout(None,0,6,"layout2") - self.CpuLabel[cpu] = TQLabel(self.tooltip,"CpuLabel") - if len(self.powermanager.cpus) > 1: - self.CpuLabel[cpu].setText(i18n("Processor %i" % i)) - self.CpuLayout[cpu].addWidget(self.CpuLabel[cpu]) - self.CpuProgress[cpu] = KProgress(self.tooltip,"CpuProgress") - self.CpuProgress[cpu].setFormat("%v MHz") - self.CpuLayout[cpu].addWidget(self.CpuProgress[cpu]) - self.tooltip.layout().addLayout(self.CpuLayout[cpu]) - i += 1 - - def slotPoweredIdleActivated(self, index=False): - """ Signal slot for activated powered idle action. """ - if not index: - index = self.PoweredIdleCombo.currentItem() - self.PoweredIdleTime.setEnabled(index != 0) - - def slotBatteryIdleActivated(self, index=False): - """ Signal slot for activated battery idle action. """ - if not index: - index = self.BatteryIdleCombo.currentItem() - self.BatteryIdleTime.setEnabled(index != 0) - - def slotBatteryCriticalActivated(self, index=False): - """ Signal slot for activated battery critical action. """ - if not index: - index = self.BatteryCriticalCombo.currentItem() - self.CriticalRemainTime.setEnabled(index != 0) - - def _updateCpuWidgets(self): - """ Retrieve CPU freq information and update the related widgets accordingly. """ - if not SHOW_CPUFREQ: - return - if len(self.powermanager.cpus) == 0: - return - - clabel = i18n("<b>CPU Frequency:</b>") + " " - policy = self.powermanager.getCpuPolicy() - if self.freq_name.has_key(policy): - clabel += self.freq_name[policy] # get l10n name - else: - clabel += policy - self.CpuMainLabel.setText(clabel) - - for cpu in self.powermanager.cpus: - cpustate = self.powermanager.getCpuState(cpu) - if not cpustate['online']: - self.CpuProgress[cpu].setEnabled(False) - else: - self.CpuProgress[cpu].setEnabled(True) - self.CpuProgress[cpu].setTotalSteps(cpustate['max']) - self.CpuProgress[cpu].setProgress(cpustate['cur']) - if policy != "": - self.systray.actionCollection().action(policy).setChecked(True) - if policy in self.cb_freq: - self.systray.actionCollection().action(policy).setChecked(True) - - def changePoweredBrightness(self, level=None): - """ Mains-powered brigthness slider has been moved. """ - # Check if the state applies and adjust brightness immediately. - if not self.powermanager.onBattery() and self.powermanager.hasBrightness: - if not level: - level = self.PoweredBrightnessSlider.value() - self.powermanager.adjustBrightness(level) - - def changeBatteryBrightness(self, level=None): - """ Battery-powered brigthness slider has been moved. """ - # Check if the state applies and adjust brightness immediately. - if self.powermanager.onBattery() and self.powermanager.hasBrightness: - if not level: - level = self.BatteryBrightnessSlider.value() - self.powermanager.adjustBrightness(level) - - - - - def checkCpuFreq(self): - """ Adjust CPU frequency policy according to current state """ - if not self.powermanager.hasCpuFreqGovernors: - return "" - - if self.powermanager.onBattery(): - policy = str(self.config.readEntry("batteryFreqPolicy")) - else: - policy = str(self.config.readEntry("poweredFreqPolicy")) - if policy == "": - policy = 'dynamic' - - # check if specified policy is supported by HW - if not policy in self.cb_freq: - print "Warning: policy from config file not supported: ", policy - return "" - - current_policy = self.powermanager.getCpuPolicy() - if current_policy != policy: - debug("Switching CPU policy from %s to %s." % (current_policy, policy)) - self.powermanager.setCpuPolicy(policy) - return i18n("CPU frequency policy changed to %1.").arg(self.freq_name[policy]) - elif current_policy == 'dynamic': - debug("Dynamic policy -> update policy (conservative/ondemand)") - self.powermanager.setCpuPolicy(policy) - - debug("CPU policy will stay %s" % current_policy) - return "" - - def powerHasBeenUnplugged(self): - """ Actions to perform when the plug has been pulled.""" - if self.powermanager.hasBrightness: - self.powermanager.adjustBrightness(self.BatteryBrightnessSlider.value()) - self.powermanager.setPowerSave(True) - self.checkBatteryCritical() - self.changeBatteryBrightness() - self.powermanager.setScreensaverBlankOnly(True) - self.powermanager.resetIdleSeconds() - msg = self.checkCpuFreq() - if self.powermanager.hasAC: - self.notify(i18n("The AC adapter has been unplugged, switching to battery mode.")+"\n"+msg, self.getIcon()) - - def powerHasBeenPlugged(self): - """ Actions to perform when AC adapter has been plugged in. """ - if self.powermanager.hasBrightness: - self.powermanager.adjustBrightness(self.PoweredBrightnessSlider.value()) - self.powermanager.setPowerSave(False) - self.changePoweredBrightness() - self.powermanager.setScreensaverBlankOnly(False) - msg = self.checkCpuFreq() - self.powermanager.resetIdleSeconds() - self.notify(i18n("The AC adapter has been plugged in, switching to AC mode.")+"\n"+msg, self.getIcon()) - - def checkBatteryCritical(self): - """ Check for warning and critical battery label and notify-warn or - initiate the configured action. """ - - if not self.powermanager.hasBattery: - return - - if self.batt_state == "discharging": - currentLevel = int(self.batt_remain/60) - - warningLevel = self.criticalLevel + 5 # warn five minutes before critical - criticalLevel = self.criticalLevel - - debug("CurrentBat: %i, WarningBat: %i, CriticalBat: %i" % (currentLevel, warningLevel, criticalLevel)) - # We only want to suspend if the chargelevel is above a certain threshold, - # it sometimes takes some time for HAL to report remaining time correctly - if currentLevel <= criticalLevel and self.batt_level < CHARGE_LEVEL_THRESHOLD: - if not self.powermanager.criticalBatteryState and self.powermanager.onBattery(): - self.powermanager.criticalBatteryState = True - - action = str(self.config.readEntry("batteryCriticalAction")) - if not self.act_name.has_key(action): - action = self.act_name[self.cb_act_def_critical] - - note = i18n("You are about to run out of battery power, %1 now.").arg(self.act_notify[action]) - self.notify(note, self.act_icon[action]) - if self.act_call[action] != None: - TQTimer.singleShot(2000, self.act_call[action]) - else: - self.powermanager.criticalBatteryState = False - if currentLevel <= warningLevel and self.batt_level < CHARGE_LEVEL_THRESHOLD: - if not self.powermanager.warningBatteryState: - self.powermanager.warningBatteryState = True - self.notify(i18n("You are low on battery power."), self.getIcon()) - else: - self.powermanager.warningBatteryState = False - - def checkIdletime(self): - """ Reads the idle time and does some action. """ - idlesec = round(self.powermanager.getIdleSeconds()/60, 2) - if self.powermanager.onBattery(): - idleTime = self.config.readNumEntry("batteryIdleTime", 10) - action = str(self.config.readEntry("batteryIdleAction")) - else: - idleTime = self.config.readNumEntry("poweredIdleTime", 60) - action = str(self.config.readEntry("poweredIdleAction")) - if not self.act_name.has_key(action): - action = 'nothing' - - if idlesec - self.lastidlesec > 100: - debug("last: %u" % (idlesec - self.lastidlesec)) - return # probably bogus idleseconds right after suspend - self.lastidlesec = idlesec - if self.act_call[action] == None: - return # doing nothing anyway - if idlesec > idleTime: - note = i18n("System idle for at least %1 minutes, %2 now.").arg(idleTime).arg(self.act_notify[action]) - self.notify(note, self.act_icon[action]) - TQTimer.singleShot(2000, self.act_call[action]) - - - -def doDcop(kapp): - """ Register kvandale in dcop, so it can be controlled from outside. """ - my_dcop = kapp.dcopClient() - #my_dcop.attach() - #my_dcop.registerAs("power-manager") - - -class DcopIface (DCOPExObj): - """ Add some interface so we can use powermanager from the outside. """ - def __init__ (self, app, id='power-manager'): - DCOPExObj.__init__ (self, id) - # addMethod (<signature>, <Python method>) - #self.addMethod ('QString getQuery()', gvd.getZoekbegrip) - - # PM related. - self.addMethod ('void suspend ()', app.trySuspend) - self.addMethod ('void hibernate ()', app.tryHibernate) - self.addMethod ('void shutdown ()', app.shutdown) - - # UI related. - self.addMethod ('void showTip ()', app.showTip) - #self.addMethod ('void show ()', app.parent().show) - #self.addMethod ('void hide ()', app.parent().hide) - - #self.addMethod ('void plugged ()', app.powerHasBeenPlugged) - #self.addMethod ('void unplugged ()', app.powerHasBeenUnplugged) - self.addMethod ('bool onBattery ()', app.powermanager.onBattery) - - self.addMethod('void brightnessUp ()', app.setBrightnessUp) - self.addMethod('void brightnessDown ()', app.setBrightnessDown) - self.addMethod('QString getBrightness ()', app.getBrightness) - - #self.addMethod ('QString getCurrentResult()', gvd.getRawResult) - - -class PowermanagerApp(KDialogBase): - """ The KDialog providing the OK, Apply and Cancel buttons.""" - - def __init__(self,parent=None,name=None): - """ Initialise dialog and set mainwidget. """ - TDEGlobal.locale().insertCatalogue("guidance") - TDEGlobal.iconLoader().addAppDir("guidance") - - # We would like to use a KUniqueApplication, but that breaks dcop due to some - # strange bug. The following line is the revenge code for this bug, it is - # intentionally ugly. - if len(os.popen("dcop |grep guidance-").readlines()) > 1: - print "There is already an instance of power manager running. Exiting." - sys.exit(0) - - # Which buttons do we want? - KDialogBase.__init__(self,KJanusWidget.Swallow,i18n("Power Manager"), - KDialogBase.Ok|KDialogBase.Apply|KDialogBase.Cancel|KDialogBase.User1, KDialogBase.Close) - self.pmwidget = PowerManager(self,name) - self.setButtonText(KDialogBase.User1, i18n("About")) - - if not self.pmwidget.powermanager.isLaptop(): - print "This is not a laptop, quitting ... " - sys.exit(1) - - self.pmwidget.prepare() - - self.setMainWidget(self.pmwidget) - self.aboutus = TDEAboutApplication(self) - - def slotOk(self): - """ The OK button has been pressed, save configuration and pass on do whatever - needs to be done by KDialog. """ - self.pmwidget.uiToConfig() - self.pmwidget.checkCpuFreq() - KDialogBase.slotOk(self) - - def slotApply(self): - """ The Apply button has been pressed, save configuration and pass on do whatever - needs to be done by KDialog. """ - self.pmwidget.uiToConfig() - self.pmwidget.checkCpuFreq() - KDialogBase.slotApply(self) - - def slotCancel(self): - """ The Cancel button has been pressed, reset some values and hide dialogue. """ - # In case brightness has changed, we reset it to the configured value. - if self.pmwidget.powermanager.hasBrightness: - brightness_high = self.pmwidget.powermanager.brightness_levels - if not self.pmwidget.powermanager.onBattery(): - level = self.pmwidget.config.readNumEntry("poweredBrightness", brightness_high) - else: - level = self.pmwidget.config.readNumEntry("batteryBrightness", int(brightness_high/2)) - self.pmwidget.powermanager.adjustBrightness(level) - self.pmwidget.configToUi() - KDialogBase.slotCancel(self) - - def slotUser1(self): - self.aboutus.show() - -# There's a bug in KUniqueApplication that shows the pid in the dcop name, -# this fugly hack works around it. -class PMApp(TDEApplication): - - def name(self): - return "power-manager" - - -if __name__ == "__main__": - aboutdata = TDEAboutData("guidance", "Power Manager", "0.8.0", - "Handles battery, display and suspend modes for your computer.", TDEAboutData.License_GPL, - "(C) 2006-2007 Sebastian Kügler, Canonical Ltd, Luka Renko", - None, None, "jriddell@ubuntu.com") - aboutdata.addAuthor("Sebastian Kügler", "Developer", "sebas@kde.org","http://vizZzion.org") - aboutdata.addAuthor("Jonathan Riddell", "Developer", "jriddell@ubuntu.com") - aboutdata.addAuthor("Luka Renko", "Developer", "lure@kubuntu.org") - aboutdata.setProgramLogo(TQImage("power-manager.png")) - TDECmdLineArgs.init(sys.argv, aboutdata) - #kapp = KUniqueApplication(True, True, False) - #kapp = TDEApplication() - kapp = PMApp(True, True) - mainWindow = PowermanagerApp(None, "main window") - doDcop(kapp) - dcop_iface = DcopIface(mainWindow.pmwidget) - """Start helper module / button listener""" - try: - helperPid = os.spawnl(os.P_NOWAIT, os.path.dirname(__file__)+'/gpmhelper.py', 'gpmhelper.py') - except: - """Non-fatal if this fails""" - print "Unable to start button-listener" - - kapp.exec_loop() - - """Kill helper module / button listener""" - os.system('kill '+str(helperPid)) |