You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepowersave/src/tdepowersave.cpp

2962 lines
90 KiB

/**************************************************************************
* Copyright (C) 2004 by Thomas Renninger *
* <trenn@suse.de> and *
* 2004-2007 by Danny Kukawka *
* <dkukawka@suse.de>, <danny.kukawka@web.de> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of version 2 of the GNU General Public License *
* 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. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// KDE headers:
#include <tdeaboutapplication.h>
#include <tdeapplication.h>
#include <kaudioplayer.h>
#include <tdeconfig.h>
#include <kiconloader.h>
#include <tdemessagebox.h>
#include <knotifyclient.h>
#include <knotifydialog.h>
#include <kpassivepopup.h>
#include <tdepopupmenu.h>
#include <kglobalaccel.h>
#include <khelpmenu.h>
// other TQt headers:
#include <tqcursor.h>
#include <tqevent.h>
#include <tqfile.h>
#include <tqimage.h>
#include <tqpixmap.h>
#include <tqtimer.h>
#include <tqtooltip.h>
// own headers:
#include "tdepowersave.h"
#include "infodialog.h"
/*!
* \file tdepowersave.cpp
* \brief This file contains the main functionality of the tdepowersave-applet.*/
/*!
* This is the default constructor of the class tdepowersave.
*/
tdepowersave::tdepowersave( bool force_acpi_check, bool trace_func ) : KSystemTray(0, "tdepowersave"),
DCOPObject("tdepowersaveIface") {
trace = trace_func;
kdDebugFuncIn(trace);
display = new screen();
settings = new Settings();
autoSuspend = new autosuspend(display);
autoDimm = new autodimm(display);
hwinfo = new HardwareInfo();
suspend = hwinfo->getSuspendSupport();
yast2 = NULL;
resume_result = 0;
config = TDEGlobal::config();
config->setGroup("General");
if(!config->readBoolEntry("AlreadyStarted", false) || force_acpi_check){
config->writeEntry("AlreadyStarted", true);
// check whether APM, ACPI, PMU, CPUFreq or Suspend2Disk/ram supported, otherwise end up
// and don't start tdepowersave ever again until force_acpi_check == true.
if (!hwinfo->hasACPI() && !hwinfo->hasAPM() && !hwinfo->hasPMU() && !hwinfo->supportCPUFreq() &&
!suspend.suspend2disk && !suspend.suspend2ram && !suspend.suspend_hybrid) {
config->writeEntry("Autostart", false);
config->sync();
kdError() << "This machine does not support ACPI, APM, PMU, CPUFreq, Suspend2Disk, "
<< "Suspend2RAM nor Hybrid Suspend. Please close tdepowersave now." << endl;
exit(-1);
}
}
// default init
if (hwinfo->getAcAdapter()) {
settings->load_scheme_settings( settings->ac_scheme);
} else {
settings->load_scheme_settings( settings->battery_scheme);
}
// set the battery warning levels
hwinfo->setPrimaryBatteriesWarningLevel(settings->batteryWarningLevel,
settings->batteryLowLevel,
settings->batteryCriticalLevel);
// connect to signals for changes
connect(hwinfo, TQT_SIGNAL(generalDataChanged()), this, TQT_SLOT(update()));
connect(hwinfo, TQT_SIGNAL(primaryBatteryChanged()), this, TQT_SLOT(update()));
connect(hwinfo, TQT_SIGNAL(ACStatus(bool)), this, TQT_SLOT(handleACStatusChange (bool)));
connect(hwinfo, TQT_SIGNAL(resumed(int)), this, TQT_SLOT(forwardResumeSignal(int)));
// connect to error messages
connect(autoSuspend, TQT_SIGNAL(displayErrorMsg(TQString)), this, TQT_SLOT(showErrorMessage(TQString)));
// connect to events
connect(hwinfo, TQT_SIGNAL(lidclosetStatus(bool)), this, TQT_SLOT(handleLidEvent(bool)));
connect(hwinfo, TQT_SIGNAL(powerButtonPressed()), this, TQT_SLOT (handlePowerButtonEvent()));
connect(hwinfo, TQT_SIGNAL(sleepButtonPressed()), this, TQT_SLOT (handleSuspendButtonEvent()));
connect(hwinfo, TQT_SIGNAL(s2diskButtonPressed()), this, TQT_SLOT (handleS2DiskButtonEvent()));
connect(hwinfo, TQT_SIGNAL(batteryWARNState(int,int)), this, TQT_SLOT(notifyBatteryStatusChange (int,int)));
connect(hwinfo, TQT_SIGNAL(desktopSessionIsActive(bool)), this, TQT_SLOT (handleSessionState(bool)));
connect(autoSuspend, TQT_SIGNAL(inactivityTimeExpired()), this, TQT_SLOT(do_autosuspendWarn()));
connect(autoDimm, TQT_SIGNAL(inactivityTimeExpired()), this, TQT_SLOT(do_downDimm()));
connect(autoDimm, TQT_SIGNAL(UserIsActiveAgain()), this, TQT_SLOT(do_upDimm()));
// connect to hotkeys
m_globalAccel = new TDEGlobalAccel( TQT_TQOBJECT(this) );
m_globalAccel->insert( "Power button", i18n( "Execute configured power button action"), TQString(),
TDEShortcut(TQString("XF86PowerOff")), TDEShortcut(TQString("XF86PowerOff")), TQT_TQOBJECT(this), TQT_SLOT( handlePowerButtonEvent() ) );
m_globalAccel->insert( "Suspend button", i18n( "Suspend configured power button action"), TQString(),
TDEShortcut(TQString("XF86Suspend")), TDEShortcut(TQString("XF86Suspend")), TQT_TQOBJECT(this), TQT_SLOT( handleSuspendButtonEvent() ) );
m_globalAccel->insert( "Hibernate button", i18n( "Hibernate configured power button action"), TQString(),
TDEShortcut(TQString("XF86Suspend")), TDEShortcut(TQString("XF86Suspend")), TQT_TQOBJECT(this), TQT_SLOT( handleS2DiskButtonEvent() ) );
m_globalAccel->readSettings();
m_globalAccel->updateConnections();
config->sync();
config_dialog_shown = false;
suspend_dialog_shown = false;
detailedIsShown = false;
icon_set_colored = false;
icon_BG_is_colored = false;
calledSuspend = -1;
countWhiteIconPixel = 0;
pixmap_name = "NONE";
suspendType = "NULL";
BAT_WARN_ICON_Timer = new TQTimer(this);
connect(BAT_WARN_ICON_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(do_setIconBG()));
AUTODIMM_Timer = new TQTimer(this);
initMenu();
update();
updateCPUFreqMenu();
setSchemeSettings();
kdDebugFuncOut(trace);
}
/*! This is the default destructor of class tdepowersave. */
tdepowersave::~tdepowersave(){
kdDebugFuncIn(trace);
delete hwinfo;
delete display;
delete settings;
delete autoSuspend;
#ifdef ENABLE_YAST_ENTRY
delete yast2;
#endif
}
/*!
* use this function to initalise the main kicker menu
*/
void tdepowersave::initMenu() {
kdDebugFuncIn(trace);
CONFIGURE_ID = this->contextMenu()->insertItem(SmallIcon("configure", TQIconSet::Automatic),
i18n("Configure TDEPowersave..."),
this, TQT_SLOT(showConfigureDialog()));
CONFIGURE_EVENTS_ID = this->contextMenu()->insertItem(SmallIcon("knotify", TQIconSet::Automatic),
i18n("Configure Notifications..."),
this, TQT_SLOT(showConfigureNotificationsDialog()));
#ifdef ENABLE_YAST_ENTRY
YAST_MODULE_MENU_ID = this->contextMenu()->insertItem(SmallIcon("yast", TQIconSet::Automatic),
i18n("Start YaST2 Power Management Module..."),
this, TQT_SLOT(do_config()));
#endif
SLEEP_SEPARATOR_MENU_ID = this->contextMenu()->insertSeparator();
FREEZE_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_ram", TQIconSet::Automatic),
i18n("Freeze"), this, TQT_SLOT(do_freeze()));
STANDBY_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("stand_by", TQIconSet::Automatic),
i18n("Standby"), this, TQT_SLOT(do_standby()));
SUSPEND2RAM_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_ram",
TQIconSet::Automatic), i18n("Suspend"), this, TQT_SLOT(do_suspend2ram()));
SUSPEND2DISK_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_disk",
TQIconSet::Automatic), i18n("Hibernate"), this, TQT_SLOT(do_suspend2disk()));
SUSPEND_HYBRID_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_disk",
TQIconSet::Automatic), i18n("Hybrid Suspend"), this, TQT_SLOT(do_suspend_hybrid()));
speed_menu = new TQPopupMenu(this, i18n("Set CPU Frequency Policy").utf8());
speed_menu->insertItem(i18n("Performance"), PERFORMANCE);
speed_menu->insertItem(i18n("Dynamic"), DYNAMIC);
speed_menu->insertItem(i18n("Powersave"), POWERSAVE);
CPUFREQ_SEPARATOR_MENU_ID = contextMenu()->insertSeparator();
CPUFREQ_MENU_ID = contextMenu()->insertItem(i18n("Set CPU Frequency Policy"), speed_menu);
connect(speed_menu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(do_setSpeedPolicy(int)));
connect(hwinfo, TQT_SIGNAL(currentCPUFreqPolicyChanged()), this, TQT_SLOT(updateCPUFreqMenu()));
SCHEME_SEPARATOR_MENU_ID = contextMenu()->insertSeparator();
scheme_menu = new TQPopupMenu(this, i18n("Set Active Scheme").utf8());
SCHEME_MENU_ID = contextMenu()->insertItem(i18n("Set Active Scheme"), scheme_menu);
connect(scheme_menu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(do_setActiveScheme(int)));
// menu entry for the autosuspend disable checkbox, disabled by default, only
// displayed if autosuspend for the current scheme is activated
AUTOSUSPEND_SEPARATOR_MENU_ID = contextMenu()->insertSeparator();
AUTOSUSPEND_MENU_ID = this->contextMenu()->insertItem( i18n("Disable Actions on Inactivity"),
this,TQT_SLOT(do_setAutosuspend()));
this->contextMenu()->setItemVisible(AUTOSUSPEND_SEPARATOR_MENU_ID, false);
this->contextMenu()->setItemVisible(AUTOSUSPEND_MENU_ID, false);
HELP_SEPARATOR_MENU_ID = contextMenu()->insertSeparator();
// Create help submenu
KHelpMenu *m_help = new KHelpMenu(this, TDEGlobal::instance()->aboutData(), false, actionCollection());
TDEPopupMenu *help = m_help->menu();
help->connectItem(KHelpMenu::menuHelpContents, this, TQT_SLOT(slotHelpContents()));
this->contextMenu()->insertItem(SmallIcon("help"), KStdGuiItem::help().text(), help);
connect(this, TQT_SIGNAL(quitSelected()), this, TQT_SLOT(_quit()));
kdDebugFuncOut(trace);
}
void tdepowersave::resizeEvent ( TQResizeEvent * )
{
// Honor Free Desktop specifications that allow for arbitrary system tray icon sizes
loadIcon(true);
drawIcon();
}
/*!
* This funtion load and manipulate the icons for the kickerapplet-section.
* The redraw interval depends on \ref icon_set_colored and \ref BAT_icon_BG_intervall.
*/
void tdepowersave::redrawPixmap(){
kdDebugFuncIn(trace);
// if colored icon_background: normal redraw intervall is set off.
// Icon (only) redrawed every BAT_icon_BG_intervall
if (icon_set_colored) {
if (icon_state_changed) {
loadIcon();
drawIcon();
}
}
else {
loadIcon();
drawIcon();
}
kdDebugFuncOut(trace);
}
/*!
* Starts the configure dialog of tdepowersave.
*/
void tdepowersave::showConfigureDialog() {
kdDebugFuncIn(trace);
if(!config_dialog_shown) {
if (settings->schemes.count() > 0){
configDlg = new ConfigureDialog(config, hwinfo, settings);
configDlg->show();
config_dialog_shown = true;
connect(configDlg, TQT_SIGNAL(destroyed()), this, TQT_SLOT(observeConfigDlg()));
connect(configDlg, TQT_SIGNAL(openHelp()), this, TQT_SLOT(slotHelp()));
connect(configDlg, TQT_SIGNAL(openKNotify()), this, TQT_SLOT(showConfigureNotificationsDialog()));
}
else {
KPassivePopup::message(i18n("WARNING"), i18n("Cannot find any schemes."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
}
} else {
configDlg->setWindowState((configDlg->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
configDlg->setActiveWindow();
}
kdDebugFuncOut(trace);
}
/*!
* Starts the notification configure dialog of tdepowersave.
*/
void tdepowersave::showConfigureNotificationsDialog() {
kdDebugFuncIn(trace);
KNotifyDialog::configure(this);
kdDebugFuncOut(trace);
}
/*!
* Load the icons (from filesystem) for the kicker applet to \ref pixmap .
* To reduce the systemload the icons are only reloaded if \ref pixmap_name
* is changed.
*/
void tdepowersave::loadIcon(bool forceReload){
kdDebugFuncIn(trace);
TQString pixmap_name_tmp = "NONE";
BatteryCollection *primary = hwinfo->getPrimaryBatteries();
if ( !hwinfo->isOnline() ) {
pixmap_name_tmp = TQString("ERROR");
}
else if (hwinfo->getAcAdapter() || primary->getBatteryState() == BAT_NONE) {
icon_set_colored = false;
if (primary->getBatteryState() == BAT_NONE || (primary->getRemainingPercent() < 0 ||
primary->getRemainingPercent() >= 99))
pixmap_name_tmp = TQString("laptoppower");
else
pixmap_name_tmp = TQString("laptopcharge");
}
else {
switch(primary->getBatteryState()) {
case BAT_CRIT:
case BAT_LOW:
if (icon_BG_is_colored) pixmap_name_tmp = TQString("laptopbattery");
else pixmap_name_tmp = TQString("laptopbatteryRED");
icon_BG_is_colored = !icon_BG_is_colored;
icon_set_colored = true;
break;
case BAT_WARN:
if (icon_BG_is_colored) pixmap_name_tmp = TQString("laptopbattery");
else pixmap_name_tmp = TQString("laptopbatteryORANGE");
icon_BG_is_colored = !icon_BG_is_colored;
icon_set_colored = true;
break;
default:
// if battery is discharging and not in warning, low or critical state
pixmap_name_tmp = TQString("laptopbattery");
icon_set_colored = false;
icon_BG_is_colored = false;
}
if (icon_set_colored){
icon_state_changed = false;
BAT_WARN_ICON_Timer->start(BAT_icon_BG_intervall, true);
}
}
// reload icon only if new icon selected
if ((pixmap_name_tmp != pixmap_name) || (forceReload)) {
pixmap_name = pixmap_name_tmp;
if (pixmap_name.startsWith("ERROR")) {
pixmap = SmallIcon("laptoppower", isShown() ? width() : 22, TDEIcon::DisabledState);
}
else {
pixmap = SmallIcon(pixmap_name, isShown() ? width() : 22);
}
}
kdDebugFuncOut(trace);
}
/*!
* This function draw the battery-capacity (colored field) to the icon.
* Here also counted the white pixel in the icon-files. Since the icons are
* the same and white pixel only in the rectangle of the icon, the white pixel
* stored in \ref countWhiteIconPixel only one time.
*/
void tdepowersave::drawIcon(){
kdDebugFuncIn(trace);
BatteryCollection *primary = hwinfo->getPrimaryBatteries();
TQImage image = pixmap.convertToImage();
int w = image.width();
int h = image.height();
int x, y;
countWhiteIconPixel = 0;
if((pixmap_name.contains("laptopbattery") || pixmap_name.contains("charge")) &&
countWhiteIconPixel == 0) {
for (x = 0; x < w; x++)
for (y = 0; y < h; y++)
if(TQColor(image.pixel(x, y)) == TQt::white) countWhiteIconPixel++;
}
int c = (countWhiteIconPixel * primary->getRemainingPercent()) / 100;
if (c > 0) {
uint ui;
TQRgb Rgb_set;
if (hwinfo->getAcAdapter()) {
Rgb_set = tqRgb(0x00, 0xff, 0x00); //green
}
else {
switch(primary->getBatteryState()) {
case BAT_CRIT:
case BAT_LOW:
Rgb_set = tqRgb(0xff, 0x00, 0x00);//red
break;
case BAT_WARN:
Rgb_set = tqRgb(0xff, 0x55, 0x00); //orange
break;
default:
Rgb_set = tqRgb(0x00, 0xff, 0x00); //green
}
}
if (image.depth() <= 8) {
ui = image.numColors();
image.setNumColors(ui + 1);
image.setColor(ui, Rgb_set);
}
ui = 0xff000000 | Rgb_set;
for (y = h - 1; y >= 0; y--) {
for (x = 0; x < w ; x++) {
if(TQColor(image.pixel(x, y)) == TQt::white) {
image.setPixel(x, y, ui);
c--;
if (c <= 0) goto quit;
}
}
}
}
quit:
if (isShown()) {
image = image.smoothScale(width(), height());
}
fullIcon.convertFromImage(image);
setPixmap(fullIcon);
kdDebugFuncOut(trace);
}
/*!
* By this function we fill and update the Tooltip for the icon in the kicker applet.
* The content of the tooltip alway updated, if something change.
* \todo Check if the tooltip also updated if mouse \b is over the icon, if not we maybe
* should implement this.\n If it is possible we should update the tooltip permanently
* while the mouse cursor is over the widget
*/
void tdepowersave::updateTooltip(){
kdDebugFuncIn(trace);
BatteryCollection *primary = hwinfo->getPrimaryBatteries();
int percent = primary->getRemainingPercent();
int minutes = primary->getRemainingMinutes();
int charging_state = primary->getChargingState();
TQString tmp, num3;
num3.setNum(minutes % 60);
num3 = num3.rightJustify(2, '0');
if ( !hwinfo->isOnline() ){
tmp = i18n("No information about battery and AC status available");
}
else if (hwinfo->getAcAdapter()) {
if (percent == 100) tmp = i18n("Plugged in -- fully charged");
// assume that no battery is there
else {
if ((percent < 0 && minutes < 0) || primary->getBatteryState() == BAT_NONE) {
tmp = i18n("Plugged in");
}
else if (minutes > 0){
if (charging_state == CHARGING)
tmp = i18n("Plugged in -- %1% charged (%2:%3 h until full "
"charged)").arg(percent).arg(minutes / 60).arg(num3);
else
tmp = i18n("Plugged in -- %1% charged (%2:%3 remaining hours)")
.arg(percent).arg(minutes / 60).arg(num3);
}
else if (charging_state == CHARGING && hwinfo->hasAPM()) {
tmp = i18n("Plugged in -- %1% charged").arg(percent);
}
else{
if (percent == -1) tmp = i18n("Plugged in -- no battery");
else tmp = i18n("Plugged in -- %1% charged").arg(percent);
}
}
} else{
if (minutes >= 0){
tmp = i18n("Running on batteries -- %1% charged (%2:%3 hours remaining)")
.arg(percent).arg(minutes / 60).arg(num3);
}
else {
tmp = i18n("Running on batteries -- %1% charged").arg(percent);
}
}
// add string whether battery is charging, but only if < 100% to avoid
// stupid tooltip message on machines which always with 100% and on AC
// are charging, as e.g. Sony Vaio FS vgn-fs115b
if (charging_state == CHARGING && percent < 100)
tmp += i18n(" -- battery is charging");
TQToolTip::add(this, tmp);
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to starts the Yast2-power-management module. This called by the menuentry
* with ID \ref YAST_MODULE_MENU_ID, named "Start YaST2 Power Management Module".
* It create a new TDEProcess and execute "/sbin/yast2 power-management" with tdesu.
*/
void tdepowersave::do_config(){
kdDebugFuncIn(trace);
#ifdef ENABLE_YAST_ENTRY
delete yast2;
yast2 = new TDEProcess;
*yast2 << "tdesu" << "--nonewdcop" << "/sbin/yast2" << "power-management";
connect(yast2, TQT_SIGNAL(processExited(TDEProcess *)),
TQT_SLOT(slotConfigProcessExited(TDEProcess *)));
if(!yast2->start(TDEProcess::NotifyOnExit))
{
delete yast2;
yast2 = NULL;
}
kdDebugFuncOut(trace);
#else
kdDebugFuncOut(trace);
return;
#endif
}
/*!
* \b TQT_SLOT to open the tdepowersave help
*/
void tdepowersave::slotHelp()
{
kapp->invokeHelp( "", "tdepowersave" );
}
/*!
* \b TQT_SLOT to open the tdepowersave About dialog
*/
void tdepowersave::slotAbout()
{
TDEAboutApplication a( this );
a.exec();
}
/*!
* \b TQT_SLOT to set the icon background on/off if battery is in critical, low or warning-state. Within
* this function we set \ref icon_state_changed to true and call \ref redrawPixmap() to redraw the
* kickerapplet icon and create a icon with blinking background. \n \n
* The slot called by the TQTimer \ref BAT_WARN_ICON_Timer . The interval of the timer is defined
* trough \ref BAT_icon_BG_intervall and starts here: \ref loadIcon() .
*/
void tdepowersave::do_setIconBG(){
kdDebugFuncIn(trace);
if (icon_set_colored) icon_state_changed = true;
redrawPixmap();
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to enable/disable the autosuspend.
*/
void tdepowersave::do_setAutosuspend(){
kdDebugFuncIn(trace);
if(!contextMenu()->isItemChecked(AUTOSUSPEND_MENU_ID)) {
autoSuspend->stop();
contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, true);
}
else {
if(settings->autoSuspend) {
contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, false);
setAutoSuspend(false);
}
else {
contextMenu()->setItemVisible(AUTOSUSPEND_MENU_ID, false);
contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, false);
contextMenu()->setItemVisible(AUTOSUSPEND_SEPARATOR_MENU_ID, false);
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT which called if the \ref configDlg is destroyed. We set within this SLOT
* \ref config_dialog_shown to false.
* TODO: check if we maybe should force here the current default scheme depending on the AC/battery state
*/
void tdepowersave::observeConfigDlg(){
kdDebugFuncIn(trace);
// reload general settings
settings->load_general_settings();
// set the battery warning levels - all other general settings don't need to
// get set, since we check the settings only on events.
hwinfo->setPrimaryBatteriesWarningLevel(settings->batteryWarningLevel,
settings->batteryLowLevel,
settings->batteryCriticalLevel);
// reload the maybe changed scheme settings
settings->load_scheme_settings( settings->currentScheme );
// set the scheme
setSchemeSettings();
config_dialog_shown=false;
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT which called from \ref do_config() if the 'tdesu yast2' TDEProcess exited.
* This function control the return value and display if needed a errormessage on failure.
*/
void tdepowersave::slotConfigProcessExited(TDEProcess *proc){
kdDebugFuncIn(trace);
#ifdef ENABLE_YAST_ENTRY
if (proc->normalExit()){
if (proc->exitStatus() != 0 && proc->exitStatus() != 16){
KPassivePopup::message( i18n("WARNING"),
i18n("Could not start YaST Power Management Module. "
"Check if it is installed."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning"), 15000);
}
}
else{
KPassivePopup::message( i18n("WARNING"),
i18n("Could not start YaST Power Management Module. "
"Check if it is installed."),
SmallIcon("messagebox_warning", 20), this, i18n("Warning"), 15000);
}
kdDebugFuncOut(trace);
#else
kdDebugFuncOut(trace);
return;
#endif
}
/*!
* \b TQT_SLOT to send the command for "suspend to disk" to TDE hardware library.
* If there is a error while "suspend to disk" the user get a messagebox.
* This function need a power management backend in TDE hardware library for "suspend to disk".
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or if powersaved not running
*/
bool tdepowersave::do_suspend2disk(){
kdDebugFuncIn(trace);
if (suspend.suspend2disk) {
if (suspend.suspend2disk_allowed || suspend.suspend2disk_allowed == -1) {
calledSuspend = SUSPEND2DISK;
if (!handleMounts(true)) {
kdWarning() << "Could not umount ..." << endl;
calledSuspend = -1;
kdDebugFuncOut(trace);
return false;
}
if(settings->lockOnSuspend) {
display->lockScreen( settings->lockmethod );
}
autoSuspend->stop();
autoDimm->stop();
notifySuspend(calledSuspend);
bool ret = hwinfo->suspend(SUSPEND2DISK);
if (ret) {
kdDebugFuncOut(trace);
return true;
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Hibernation failed"),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
kdDebugFuncOut(trace);
return false;
}
} else {
KPassivePopup::message( i18n("WARNING"),
i18n("Hibernation disabled by administrator."),
SmallIcon("messagebox_warning", 20),
this, i18n("Warning").utf8(), 15000);
this->contextMenu()->setItemEnabled(SUSPEND2DISK_MENU_ID, false);
kdDebugFuncOut(trace);
return false;
}
} else {
kdWarning() << "This machine does not provide hibernation state" << endl;
kdDebugFuncOut(trace);
return false;
}
}
/*!
* \b TQT_SLOT to send the command for "hybrid suspend" to TDE hardware library.
* If there is a error while "hybrid suspend" the user get a messagebox.
* This function need a power management backend in TDE hardware library for "hybrid suspend".
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or if powersaved not running
*/
bool tdepowersave::do_suspend_hybrid(){
kdDebugFuncIn(trace);
if (suspend.suspend_hybrid) {
if (suspend.suspend_hybrid_allowed || suspend.suspend_hybrid_allowed == -1) {
calledSuspend = SUSPEND_HYBRID;
if (!handleMounts(true)) {
kdWarning() << "Could not umount ..." << endl;
calledSuspend = -1;
kdDebugFuncOut(trace);
return false;
}
if(settings->lockOnSuspend) {
display->lockScreen( settings->lockmethod );
}
autoSuspend->stop();
autoDimm->stop();
notifySuspend(calledSuspend);
bool ret = hwinfo->suspend(SUSPEND_HYBRID);
if (ret) {
kdDebugFuncOut(trace);
return true;
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Hybrid Suspend failed"),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
kdDebugFuncOut(trace);
return false;
}
} else {
KPassivePopup::message( i18n("WARNING"),
i18n("Hybrid Suspend disabled by administrator."),
SmallIcon("messagebox_warning", 20),
this, i18n("Warning").utf8(), 15000);
this->contextMenu()->setItemEnabled(SUSPEND_HYBRID_MENU_ID, false);
kdDebugFuncOut(trace);
return false;
}
} else {
kdWarning() << "This machine does not provide hybrid suspend state" << endl;
kdDebugFuncOut(trace);
return false;
}
}
/*!
* \b TQT_SLOT to send the command for "suspend to RAM" to the TDE hardware library.
* If there is a error while "suspend to RAM" the user get a messagebox.
* This function need a power management backend in TDE hardware library for "suspend to RAM".
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or if powersaved not running
*/
bool tdepowersave::do_suspend2ram(){
kdDebugFuncIn(trace);
if (suspend.suspend2ram) {
if (suspend.suspend2ram_allowed || suspend.suspend2ram_allowed == -1) {
calledSuspend = SUSPEND2RAM;
if (!handleMounts(true)) {
kdWarning() << "Could not umount ..." << endl;
calledSuspend = -1;
kdDebugFuncOut(trace);
return false;
}
if(settings->lockOnSuspend) {
display->lockScreen( settings->lockmethod );
}
autoSuspend->stop();
autoDimm->stop();
notifySuspend(calledSuspend);
bool ret = hwinfo->suspend(SUSPEND2RAM);
if (ret) {
kdDebugFuncOut(trace);
return true;
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Suspend mode failed"),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
kdDebugFuncOut(trace);
return false;
}
} else {
KPassivePopup::message( i18n("WARNING"),
i18n("Suspend mode disabled by administrator."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
this->contextMenu()->setItemEnabled(SUSPEND2RAM_MENU_ID, false);
kdDebugFuncOut(trace);
return false;
}
} else {
kdWarning() << "This machine does not provide Suspend state" << endl;
kdDebugFuncOut(trace);
return false;
}
}
/*!
* \b TQT_SLOT to send the command for "freeze" to the TDE hardware library.
* If there is a error while "freeze" the user get e messagebox.
* This function need a power management backend in TDE hardware library for "freeze".
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or if powersaved not running
*/
bool tdepowersave::do_freeze(){
kdDebugFuncIn(trace);
if (suspend.freeze) {
if (suspend.freeze_allowed || suspend.freeze_allowed == -1) {
calledSuspend = FREEZE;
if (!handleMounts(true)) {
kdWarning() << "Could not umount ..." << endl;
calledSuspend = -1;
kdDebugFuncOut(trace);
return false;
}
if(settings->lockOnSuspend) {
display->lockScreen( settings->lockmethod );
}
autoSuspend->stop();
autoDimm->stop();
notifySuspend(calledSuspend);
bool ret = hwinfo->suspend(FREEZE);
if (ret) {
kdDebugFuncOut(trace);
return true;
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Freeze failed"),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
kdDebugFuncOut(trace);
return false;
}
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Freeze disabled by administrator."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
this->contextMenu()->setItemEnabled(FREEZE_MENU_ID, false);
kdDebugFuncOut(trace);
return false;
}
} else {
kdWarning() << "This machine does not provide freeze suspend state" << endl;
kdDebugFuncOut(trace);
return false;
}
}
/*!
* \b TQT_SLOT to send the command for "stand-by" to the TDE hardware library.
* If there is a error while "stand-by" the user get e messagebox.
* This function need a power management backend in TDE hardware library for "stand-by".
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or if powersaved not running
*/
bool tdepowersave::do_standby(){
kdDebugFuncIn(trace);
if (suspend.standby) {
if (suspend.standby_allowed || suspend.standby_allowed == -1) {
calledSuspend = STANDBY;
if (!handleMounts(true)) {
kdWarning() << "Could not umount ..." << endl;
calledSuspend = -1;
kdDebugFuncOut(trace);
return false;
}
if(settings->lockOnSuspend) {
display->lockScreen( settings->lockmethod );
}
autoSuspend->stop();
autoDimm->stop();
notifySuspend(calledSuspend);
bool ret = hwinfo->suspend(STANDBY);
if (ret) {
kdDebugFuncOut(trace);
return true;
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Standby failed"),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
kdDebugFuncOut(trace);
return false;
}
} else {
KPassivePopup::message( i18n("WARNING"),i18n("Standby disabled by administrator."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 15000);
this->contextMenu()->setItemEnabled(STANDBY_MENU_ID, false);
kdDebugFuncOut(trace);
return false;
}
} else {
kdWarning() << "This machine does not provide standby suspend state" << endl;
kdDebugFuncOut(trace);
return false;
}
}
/*!
* \b TQT_SLOT to send check if we should display the warning dialog and display
* the dialog if needed or call directly autosuspend after the signal
* \ref autosuspend::inactivityTimeExpired was recieved.
*/
void tdepowersave::do_autosuspendWarn() {
kdDebugFuncIn(trace);
// Verify that the desired suspend action is allowed before displaying the dialog
SuspendStates suspend = hwinfo->getSuspendSupport();
bool allowed = false;
if(settings->autoInactiveAction == "Hibernate") {
if ( suspend.suspend2disk && (suspend.suspend2disk_allowed || suspend.suspend2disk_allowed == -1)) {
allowed = true;
}
}
else if(settings->autoInactiveAction == "Hybrid Suspend") {
if ( suspend.suspend_hybrid && (suspend.suspend_hybrid_allowed || suspend.suspend_hybrid_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Suspend") {
if( suspend.suspend2ram && (suspend.suspend2ram_allowed || suspend.suspend2ram_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Freeze") {
if ( suspend.freeze && (suspend.freeze_allowed || suspend.freeze_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Standby") {
if ( suspend.standby && (suspend.standby_allowed || suspend.standby_allowed == -1)) {
allowed = true;
}
}
if (allowed) {
if (settings->autoSuspendCountdown && (settings->autoSuspendCountdownTimeout > 0)) {
// we have to display the warn dialog
if(!contextMenu()->isItemChecked(AUTOSUSPEND_MENU_ID)) {
TQString message;
countdown = new countDownDialog(settings->autoSuspendCountdownTimeout);
if(settings->autoInactiveAction == "Hibernate") {
countdown->setPixmap("suspend2disk");
} else if(settings->autoInactiveAction == "Hybrid Suspend") {
countdown->setPixmap("suspend2disk");
} else if (settings->autoInactiveAction == "Suspend") {
countdown->setPixmap("suspend2ram");
} else if (settings->autoInactiveAction == "Freeze") {
countdown->setPixmap("suspend2ram");
} else if (settings->autoInactiveAction == "Standby") {
countdown->setPixmap("standby");
} else {
countdown->setPixmap("tdepowersave");
}
// TODO: rework this after translation round for openSUSE 10.3 !
message = i18n("Inactivity detected.") + " " +
i18n("To stop the %1 press the 'Cancel' button before the countdown "
"expires.").arg(i18n("Autosuspend")) + "\n\n" +
i18n("The computer autosuspend in: ");
countdown->setMessageText(message);
connect(countdown, TQT_SIGNAL(dialogClosed(bool)), this, TQT_SLOT(do_autosuspend(bool)));
countdown->showDialog();
}
}
else {
// call directly autosuspend
do_autosuspend(false);
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to send the related suspend command for autosuspend
* \param cancel boolean with info if the autosuspend should get canceled
* \return boolean with the result of the operation
* \retval true if successful
* \retval false if command not supported or on any other error
* \todo add check if the requested command is supported before send and
* add message for this case to tell that maybe changed config!
*/
bool tdepowersave::do_autosuspend(bool cancel) {
kdDebugFuncIn(trace);
autoSuspend->stop();
if (!cancel) {
if(!settings->disableNotifications) {
KNotifyClient::event( this->winId(), "autosuspend_event",
i18n("System is going into suspend mode now"));
}
if(settings->autoSuspend && !contextMenu()->isItemChecked(AUTOSUSPEND_MENU_ID)) {
if(settings->autoInactiveAction == "Hibernate") {
return do_suspend2disk();
} else if(settings->autoInactiveAction == "Hybrid Suspend") {
return do_suspend_hybrid();
} else if (settings->autoInactiveAction == "Suspend") {
return do_suspend2ram();
} else if (settings->autoInactiveAction == "Freeze") {
return do_freeze();
} else if (settings->autoInactiveAction == "Standby") {
return do_standby();
} else {
return false;
}
} else {
return false;
}
} else {
kdDebug() << "The autosuspend was canceled (via the cancel dialog), start again." << endl;
setAutoSuspend(false);
return false;
}
}
/*!
* \b TQT_SLOT to dimm the display down to the configured level if the signal
* \ref autodimm::inactivityTimeExpired was recieved.
* \param
* \return boolean with the result of the operation
* \retval true if successful
* \retval false else
*/
void tdepowersave::do_downDimm() {
kdDebugFuncIn(trace);
if (hwinfo->supportBrightness()) {
if (!AUTODIMM_Timer->isActive()) {
int dimmToLevel = (int)((float)hwinfo->getMaxBrightnessLevel()*((float)settings->autoDimmTo/100.0));
// check if we really need to dimm down
if (dimmToLevel < hwinfo->getCurrentBrightnessLevel()) {
int steps = hwinfo->getCurrentBrightnessLevel() - dimmToLevel;
int timePerStep = (1500 / steps);
autoDimmDown = true;
AUTODIMM_Timer = new TQTimer(this);
connect(AUTODIMM_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(do_dimm()));
AUTODIMM_Timer->start(timePerStep, false);
} else {
kdWarning() << "Don't dimm down, current level is already lower than requested Level" << endl;
}
} else {
// wait until the timer is stopped, try later!
TQTimer::singleShot(1500, this, TQT_SLOT(do_downDimm()));
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to dimm the display up to the configured level if the signal
* \ref autodimm::UserIsActiveAgain was recieved.
* \param
* \return boolean with the result of the operation
* \retval true if successful
* \retval false else
*/
void tdepowersave::do_upDimm() {
kdDebugFuncIn(trace);
//NOTE we go back to the value of the scheme and not the last on, to reduce trouble with the scheme
if (hwinfo->supportBrightness()) {
if (!AUTODIMM_Timer->isActive()) {
int dimmToLevel = (int)((float)hwinfo->getMaxBrightnessLevel()*((float)settings->brightnessValue/100.0));
// check if we really need to dimm up
if (dimmToLevel > hwinfo->getCurrentBrightnessLevel()) {
int steps = dimmToLevel - hwinfo->getCurrentBrightnessLevel();
int timePerStep = (750 / steps);
autoDimmDown = false;
AUTODIMM_Timer = new TQTimer(this);
connect(AUTODIMM_Timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(do_dimm()));
AUTODIMM_Timer->start(timePerStep, false);
// start autodimm again
setAutoDimm(false);
} else {
kdWarning() << "Don't dimm up, current level is already above requested Level" << endl;
}
} else {
// wait until the timer is stopped, try later!
TQTimer::singleShot(750, this, TQT_SLOT(do_downDimm()));
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to dimm the display down
* \return boolean with the result of the operation
* \retval true if successful
* \retval false else
*/
void tdepowersave::do_dimm() {
kdDebugFuncIn(trace);
int current = hwinfo->getCurrentBrightnessLevel();
if (autoDimmDown) {
// dimm the display down
if (current > 0 &&
current > ((int)((float)hwinfo->getMaxBrightnessLevel()*((float)settings->autoDimmTo/100.0))-1)) {
hwinfo->setBrightness((current -1) , -1);
} else {
AUTODIMM_Timer->stop();
// start checking if the user get active again
// NOTE: we start this here because the X-Server detect brightness changes as
// User activity --> FUCKING STUPID PIECE OF SHIT
autoDimm->startCheckForActivity();
}
} else {
// dimm the display up
if (current < ((int)((float)hwinfo->getMaxBrightnessLevel()*((float)settings->brightnessValue/100.0))-1)) {
hwinfo->setBrightness((current +1) , -1);
} else {
AUTODIMM_Timer->stop();
}
}
kdDebugFuncOut(trace);
}
/*!
* Function handle umount/remount external storage media before/after
* suspend.
* \param suspend boolean with info if the machine go into suspend or not
* \return result of the operation
* \retval true if all was successful
* \retval false if not
*/
bool tdepowersave::handleMounts( bool suspend ) {
if (trace) kdDebug() << funcinfo << "IN: " << "called suspend: " << suspend << endl;
bool _ret = false;
TQString _errormsg;
if (settings->unmountExternalOnSuspend) {
TQString _method;
DCOPRef dcop_ref = DCOPRef( "kded", "mediamanager" );
if (suspend) {
_method = "unmountAllSuspend()";
} else {
_method = "remountAllResume()";
}
DCOPReply reply = dcop_ref.call(_method.latin1());
if ( reply.isValid() ) {
reply.get(_errormsg);
if (_errormsg.isEmpty()) {
kdDebugFuncOut(trace);
return true;
} else {
kdError() << "ERROR while umount/remount partitions: " << _errormsg << endl;
}
} else {
kdWarning() << "Could not umount external storage partitions." << endl;
}
} else {
kdDebugFuncOut(trace);
return true;
}
// this is only needed for suspend case and an error ...
// on resume a simple error msg should be enough
if (!_ret && suspend) {
// handle error case
TQString _msg;
TQString _e_msg;
TQString _suspend;
if (!_errormsg.isEmpty()) {
_e_msg = _errormsg;
} else {
_e_msg = i18n("Could not call DCOP interface to umount external media.");
}
// ugly: need qt-tags because mediamanager can return html formated strings !!!
_msg = "<qt>" +
i18n("Could not umount external media before suspend/standby. \n "
"(Reason: %1)\n \n Would you like to continue suspend/standby "
"anyway? \n(Warning: Continue suspend can cause data loss!)").arg(_e_msg) +
"</qt>";
_suspend = getSuspendString(calledSuspend);
int answer = KMessageBox::questionYesNo( 0, _msg,
i18n("Error while prepare %1").arg(_suspend),
i18n("Suspend anyway"), i18n("Cancel suspend"),
"ignoreMountOnSuspend");
if (answer == KMessageBox::Yes) {
_ret = true;
}
}
kdDebugFuncOut(trace);
return _ret;
}
/*!
* Handle the event for the power button and call the related action.
*/
void tdepowersave::handlePowerButtonEvent( ) {
kdDebugFuncIn(trace);
/* Only go to suspend on button event if we already resumed successful.
This should solve problems if we get may a event for the powerbutton
if there machine was waked up via power button. */
if (calledSuspend == -1) {
handleActionCall(settings->powerButtonAction, settings->powerButtonActionValue);
}
kdDebugFuncOut(trace);
}
/*!
* Handle the event for the suspend2ram/sleep button and call the related action.
*/
void tdepowersave::handleSuspendButtonEvent() {
kdDebugFuncIn(trace);
// Only go to suspend on button event if we already resumed successful.
if (calledSuspend == -1) {
handleActionCall(settings->sleepButtonAction, -1);
}
kdDebugFuncOut(trace);
}
/*!
* Handle the event for the suspend2disk (hibernater) button and call the related action.
*/
void tdepowersave::handleS2DiskButtonEvent() {
kdDebugFuncIn(trace);
// Only go to suspend on button event if we already resumed successful.
if (calledSuspend == -1) {
handleActionCall(settings->s2diskButtonAction, -1);
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to handle the lidclose event. If the screen get locked
* depends on the user specific settings.
* \param closed boolean with info if the lid is closed or not
*/
void tdepowersave::handleLidEvent( bool closed ){
if (trace) kdDebug() << funcinfo << "IN: " << "Lid closed? " << closed << endl;
if (closed) {
// get new general settings! This could maybe removed if we
// could be shure, that the settings are actuall
settings->load_general_settings();
// handle screen lock
if (settings->lidcloseAction < 0) {
if(settings->lockOnLidClose) {
if(!display->lockScreen( settings->lockmethod )) {
KPassivePopup::message( i18n("WARNING"),
i18n("Could not lock the screen. There may "
"be a problem with the selected \nlock "
"method or something else."),
SmallIcon("messagebox_warning", 20), this,
i18n("Warning").utf8(), 10000);
}
}
if(settings->forceDpmsOffOnLidClose) {
display->forceDPMSOff();
}
} else {
// handle lock action
if (hwinfo->currentSessionIsActive()) {
handleActionCall(settings->lidcloseAction, settings->lidcloseActionValue);
} else {
kdWarning() << "Session is not active, don't react on lidclose "
<< "event with a action call (like e.g. Suspend)!" << endl;
}
}
if(!settings->disableNotifications)
KNotifyClient::event( this->winId(), "lid_closed_event", i18n("The Lid was closed."));
} else {
if(settings->forceDpmsOffOnLidClose) {
// reset the scheme settings to avoid problems related to call xset on lidclose
setSchemeSettings();
}
if (settings->lockOnLidClose) {
activateLoginScreen();
}
if(!settings->disableNotifications)
KNotifyClient::event( this->winId(), "lid_opened_event", i18n("The Lid was opened."));
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to show the login dialog if the desktop was locked before the suspend.
*/
void tdepowersave::activateLoginScreen(){
kdDebugFuncIn(trace);
// get new general settings! This could maybe removed if we
// could be shure, that the settings are actuall
settings->load_general_settings();
if(settings->timeToFakeKeyAfterLock >= 0) {
TQTimer::singleShot(settings->timeToFakeKeyAfterLock, display, TQT_SLOT(fakeShiftKeyEvent()));
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT to set the current suspend type for later use.
*/
void tdepowersave::setSuspendType( TQString suspendtype){
kdDebugFuncIn(trace);
suspendType = suspendtype;
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT which called if tdepowersave is exited by the user. In this case the user
* is asked through a yes/no box if "tdepowersave start automatically on log in" and the
* result is written to the KDE configfile.
*/
void tdepowersave::_quit (){
kdDebugFuncIn(trace);
// set the KDE-Settings back to user default
if(getenv("TDE_FULL_SESSION")) {
// first try to call the KDE method via DCOP to reset, if not fall back
if (!display->resetKDEScreensaver()) {
settings->load_kde();
// reset to KDE screensaver settings
display->blankOnlyScreen(false);
if(!settings->kde->enabled) display->setScreenSaver(false);
else display->setScreenSaver(true);
if(!settings->kde->displayEnergySaving) display->setDPMS(false);
else display->setDPMS(true);
display->has_DPMS = display->setDPMSTimeouts( settings->kde->displayStandby,
settings->kde->displaySuspend,
settings->kde->displayPowerOff);
}
}
// set, if this is a GNOME session, XScreensaver settings back to user default
TQString session = getenv("DESKTOP_SESSION");
if(session.startsWith("gnome")) {
display->resetXScreensaver();
}
if(!settings->autostartNeverAsk) {
TQString tmp1 = i18n ("Start tdepowersave automatically when you log in?");
int tmp2 = KMessageBox::questionYesNo ( 0, tmp1, i18n("Question"),
i18n("Start Automatically"), i18n("Do Not Start"));
config->setGroup("General");
config->writeEntry ("Autostart", tmp2 == KMessageBox::Yes);
config->sync ();
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the user select a 'CPU Frequency Policy' from the menu ( \ref CPUFREQ_MENU_ID ).
*/
void tdepowersave::do_setSpeedPolicy(int menu_id){
if (trace) kdDebug() << funcinfo << "IN: " << "menu_id/set policy to: " << menu_id << endl;
if(!hwinfo->setCPUFreq((cpufreq_type)menu_id, settings->cpuFreqDynamicPerformance)) {
KPassivePopup::message(i18n("WARNING"),
i18n("CPU Freq Policy %1 could not be set.").arg(speed_menu->text(menu_id)),
SmallIcon("messagebox_warning", 20), this, i18n("Warning").utf8(), 10000);
} else {
hwinfo->checkCurrentCPUFreqPolicy();
update();
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the user select a scheme from the menu. If there is any errormessage
* while try to set the selected scheme, the user get a messagebox with info.
*/
void tdepowersave::do_setActiveScheme( int i ){
if (trace) kdDebug() << funcinfo << "IN: " << "set scheme to: " << i << endl;
if(!settings->schemes[i].isEmpty() && (settings->schemes[i] != settings->currentScheme)) {
for (int x = 0; x < (int) scheme_menu->count(); x++){
if (x == i)
scheme_menu->setItemChecked(x, true);
else
scheme_menu->setItemChecked(x, false);
}
settings->load_scheme_settings( settings->schemes[i]);
setSchemeSettings();
notifySchemeSwitch();
} else if (!settings->schemes[i]){
KPassivePopup::message( i18n("WARNING"),
i18n("Scheme %1 could not be activated.").arg(scheme_menu->text(i)),
SmallIcon("messagebox_warning", 20), this, i18n("Warning").utf8(), 5000);
}
kdDebugFuncOut(trace);
}
/*!
* This function is invoked if something has to be updated. This including also menu entries.
* If the battery is in warning state (and powersave set pdaemon->send_battery_state_change_message)
* the function pop-up a messagebox.
*/
void tdepowersave::update(){
kdDebugFuncIn(trace);
int redraw_pixmap = 0;
TQString justMins;
/* need to redraw pixmap in toolbar */
if (hwinfo->update_info_ac_changed){
redraw_pixmap = 1;
}
if (!hwinfo->isOnline()){
this->contextMenu()->setItemVisible(FREEZE_MENU_ID, false);
this->contextMenu()->setItemVisible(STANDBY_MENU_ID, false);
this->contextMenu()->setItemVisible(SUSPEND2RAM_MENU_ID, false);
this->contextMenu()->setItemVisible(SUSPEND2DISK_MENU_ID, false);
this->contextMenu()->setItemVisible(SUSPEND_HYBRID_MENU_ID, false);
this->contextMenu()->setItemVisible(SLEEP_SEPARATOR_MENU_ID, false);
this->contextMenu()->setItemVisible(SCHEME_SEPARATOR_MENU_ID, false);
this->contextMenu()->setItemVisible(SCHEME_MENU_ID, false);
this->contextMenu()->setItemVisible(HELP_SEPARATOR_MENU_ID, false);
this->contextMenu()->setItemVisible(CONFIGURE_ID, false);
this->contextMenu()->setItemVisible(CONFIGURE_EVENTS_ID, false);
if (!pixmap_name.startsWith("ERROR")) {
// dirty !!! but this work for the moment
hwinfo->update_info_cpufreq_policy_changed = true;
suspend = hwinfo->getSuspendSupport();
redraw_pixmap = 1;
}
}
else{
if (pixmap_name.startsWith("ERROR")) {
redraw_pixmap = 1;
hwinfo->update_info_cpufreq_policy_changed = true;
suspend = hwinfo->getSuspendSupport();
}
this->contextMenu()->setItemVisible(FREEZE_MENU_ID, true);
this->contextMenu()->setItemVisible(STANDBY_MENU_ID, true);
this->contextMenu()->setItemVisible(SUSPEND2RAM_MENU_ID, true);
this->contextMenu()->setItemVisible(SUSPEND2DISK_MENU_ID, true);
this->contextMenu()->setItemVisible(SUSPEND_HYBRID_MENU_ID, true);
this->contextMenu()->setItemVisible(SLEEP_SEPARATOR_MENU_ID, true);
this->contextMenu()->setItemVisible(SCHEME_SEPARATOR_MENU_ID, true);
this->contextMenu()->setItemVisible(SCHEME_MENU_ID, true);
this->contextMenu()->setItemVisible(HELP_SEPARATOR_MENU_ID, true);
this->contextMenu()->setItemVisible(CONFIGURE_ID, true);
this->contextMenu()->setItemVisible(CONFIGURE_EVENTS_ID, true);
if (suspend.suspend2disk && (suspend.suspend2disk_allowed ||
suspend.suspend2disk_allowed == -1)) {
this->contextMenu()->setItemEnabled(SUSPEND2DISK_MENU_ID, true);
} else {
if (!suspend.suspend2disk)
this->contextMenu()->setItemVisible(SUSPEND2DISK_MENU_ID, false);
else
this->contextMenu()->setItemEnabled(SUSPEND2DISK_MENU_ID, false);
}
if (suspend.suspend_hybrid && (suspend.suspend_hybrid_allowed ||
suspend.suspend_hybrid_allowed == -1)) {
this->contextMenu()->setItemEnabled(SUSPEND_HYBRID_MENU_ID, true);
} else {
if (!suspend.suspend_hybrid)
this->contextMenu()->setItemVisible(SUSPEND_HYBRID_MENU_ID, false);
else
this->contextMenu()->setItemEnabled(SUSPEND_HYBRID_MENU_ID, false);
}
if (suspend.suspend2ram && (suspend.suspend2ram_allowed ||
suspend.suspend2ram_allowed == -1)) {
this->contextMenu()->setItemEnabled(SUSPEND2RAM_MENU_ID, true);
} else {
if (!suspend.suspend2ram)
this->contextMenu()->setItemVisible(SUSPEND2RAM_MENU_ID, false);
else
this->contextMenu()->setItemEnabled(SUSPEND2RAM_MENU_ID, false);
}
if (suspend.freeze && (suspend.freeze_allowed || suspend.freeze_allowed == -1)) {
this->contextMenu()->setItemEnabled(FREEZE_MENU_ID, true);
} else {
if (!suspend.freeze)
this->contextMenu()->setItemVisible(FREEZE_MENU_ID, false);
else
this->contextMenu()->setItemEnabled(FREEZE_MENU_ID, false);
}
if (suspend.standby && (suspend.standby_allowed || suspend.standby_allowed == -1)) {
this->contextMenu()->setItemEnabled(STANDBY_MENU_ID, true);
} else {
if (!suspend.standby)
this->contextMenu()->setItemVisible(STANDBY_MENU_ID, false);
else
this->contextMenu()->setItemEnabled(STANDBY_MENU_ID, false);
}
}
if (hwinfo->update_info_cpufreq_policy_changed == true){
updateCPUFreqMenu();
}
BatteryCollection *primary = hwinfo->getPrimaryBatteries();
if (hwinfo->update_info_primBattery_changed == true){
justMins.setNum(primary->getRemainingMinutes() % 60);
justMins = justMins.rightJustify(2, '0');
redraw_pixmap = 1;
hwinfo->update_info_primBattery_changed = false;
}
updateSchemeMenu();
if (redraw_pixmap){
redrawPixmap();
}
kdDebugFuncOut(trace);
}
/*!
* This function is involved if the CPUFreqMenu must be updated.
*/
void tdepowersave::updateCPUFreqMenu(){
kdDebugFuncIn(trace);
if (hwinfo->supportCPUFreq() && hwinfo->isOnline() && hwinfo->isCpuFreqAllowed()) {
/* set CPU frequency menu entries *********/
/* speed menu has id 3 in context menu */
contextMenu()->setItemVisible(CPUFREQ_MENU_ID, true);
contextMenu()->setItemEnabled(CPUFREQ_MENU_ID, true);
contextMenu()->setItemVisible(CPUFREQ_SEPARATOR_MENU_ID, true);
switch (hwinfo->getCurrentCPUFreqPolicy()){
case PERFORMANCE:
speed_menu->setItemChecked(PERFORMANCE, true);
speed_menu->setItemChecked(DYNAMIC, false);
speed_menu->setItemChecked(POWERSAVE, false);
break;
case DYNAMIC:
speed_menu->setItemChecked(PERFORMANCE, false);
speed_menu->setItemChecked(DYNAMIC, true);
speed_menu->setItemChecked(POWERSAVE, false);
break;
case POWERSAVE:
speed_menu->setItemChecked(PERFORMANCE, false);
speed_menu->setItemChecked(DYNAMIC, false);
speed_menu->setItemChecked(POWERSAVE, true);
break;
}
} else {
/* there never were policies */
if (!speed_menu) {
return ;
} else if (hwinfo->supportCPUFreq() && (hwinfo->isCpuFreqAllowed() != 1)) {
contextMenu()->setItemEnabled(CPUFREQ_MENU_ID, false);
contextMenu()->setItemVisible(CPUFREQ_SEPARATOR_MENU_ID, true);
} else{
/* there were CPU freq policies, but they are not accessible any more */
/* delete speed_menu */
contextMenu()->setItemVisible(CPUFREQ_MENU_ID, false);
contextMenu()->setItemVisible(CPUFREQ_SEPARATOR_MENU_ID, false);
}
}
hwinfo->update_info_cpufreq_policy_changed = false;
kdDebugFuncOut(trace);
}
/*!
* The function used to update the scheme menu. A update is needed if
* if there is maybe new schemes or if the current scheme changed or switched
* By this way also set the settings for screensaver and other parameter
* related to the selected scheme.
*/
void tdepowersave::updateSchemeMenu(){
kdDebugFuncIn(trace);
if (settings->schemes.count() == 0 || !hwinfo->isOnline()){
/* there never were schemes */
if (!scheme_menu)
return ;
else{
/* there were schemes, but they are not accessible any more */
/* delete scheme_menu */
scheme_menu->clear();
contextMenu()->setItemVisible(SCHEME_MENU_ID, false);
contextMenu()->setItemVisible(SCHEME_SEPARATOR_MENU_ID, false);
return ;
}
}
/* redraw all scheme entries ... */
scheme_menu->clear();
// clear the list of real scheme names
org_schemenames.clear();
org_schemenames = settings->schemes;
int x = 0;
for ( TQStringList::iterator it = org_schemenames.begin(); it != org_schemenames.end(); ++it ) {
TQString _t = *it;
if ( *it == settings->ac_scheme ){
scheme_menu->insertItem( SmallIcon("scheme_power", TQIconSet::Automatic),
i18n( ((TQString)*it).utf8() ), x, x);
}
else{
if ( *it == settings->battery_scheme ){
scheme_menu->insertItem(SmallIcon("scheme_powersave", TQIconSet::Automatic),
i18n( (*it).utf8() ), x, x);
}
else{
if ((TQString)*it == "Acoustic"){
scheme_menu->insertItem(SmallIcon("scheme_acoustic",
TQIconSet::Automatic),
i18n("Acoustic"), x, x);
}
else if ((TQString)*it == "Presentation"){
scheme_menu->insertItem(SmallIcon("scheme_presentation",
TQIconSet::Automatic),
i18n("Presentation"), x, x);
}
else if((TQString)*it == "AdvancedPowersave") {
scheme_menu->insertItem(SmallIcon("scheme_advanced_powersave",
TQIconSet::Automatic),
i18n( "Advanced Powersave" ), x, x);
}
else {
scheme_menu->insertItem(i18n( (*it).utf8() ), x, x);
}
}
}
if ( *it == settings->currentScheme ) {
scheme_menu->setItemChecked(x, true);
}
++x;
}
if (x == 0 && scheme_menu){
// this should not happen, scheme_list should have been NULL before
// now we'd have an empty menu ...
}
else{
contextMenu()->setItemVisible(SCHEME_MENU_ID, true);
contextMenu()->setItemVisible(SCHEME_SEPARATOR_MENU_ID, true);
}
kdDebugFuncOut(trace);
}
/*!
* Reimplemented eventhandler for mouse enterEvent. This is called if the mouse cursor
* enters the widget. In this case if the user move the mouse cursor over the tdepowersave
* trayicon. \n \n
* We use this event to update the Tooltip with all needed information. The time beetween
* the event and the automatically popup of the TQToolTip should be long enought to collect
* the needed values and add a updated Tooltip.
*/
void tdepowersave::enterEvent( TQEvent */*qee*/ ){
updateTooltip();
}
/*!
* Event handler for mouse wheel events. If the system supports changing display
* brightness and changing brightness is enabled in the current scheme settings,
* this will raise the brightness by one level for wheel up events and lower the
* brightness by one level for wheel down events.
*/
void tdepowersave::wheelEvent (TQWheelEvent *qwe)
{
kdDebugFuncIn(trace);
if (!hwinfo->supportBrightness() && settings->brightness)
return;
if (qwe->orientation () == Qt::Vertical) {
if (qwe->delta() > 0) {
do_brightnessUp(5);
} else {
do_brightnessDown(5);
}
}
kdDebugFuncOut(trace);
}
/*!
* Reimplemented eventhandler for mousePressEvents which is involved if the user click
* on the icon on the kickerapplet. This was written to guarantee that a click with the
* right and the left mousebutton activate the menu. In the future this can also used
* to popup maybe a other menu.
*/
void tdepowersave::mousePressEvent(TQMouseEvent *qme){
kdDebugFuncIn(trace);
KSystemTray::mousePressEvent(qme);
if (hwinfo->isOnline()) {
if (qme->button() == Qt::RightButton){
// TODO check if maybe some rechecks needed
this->contextMenu()->exec(TQCursor::pos());
} else if (qme->button() == Qt::LeftButton) {
showDetailedDialog();
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the detaileddialog is closed. With this we prevent open
* the dialog twice, use this function to reset the used variables.
*/
void tdepowersave::closedetaileddialog() {
detailedIsShown = false;
}
/*!
* \b TQT_SLOT used to display messeges in tdepowersave. This function
* block all messeges which we have in tdepowersave!
*/
void tdepowersave::showErrorMessage( TQString msg ){
kdDebugFuncIn(trace);
if(settings->psMsgAsPassivePopup) {
KPassivePopup::message("tdepowersave", msg, SmallIcon("messagebox_warning", 20),
this, i18n("Warning").utf8(), 10000);
} else {
kapp->updateUserTimestamp();
// KMessageBox::error( 0, msg);
KMessageBox::queuedMessageBox(0, KMessageBox::Error, msg);
}
kdDebugFuncOut(trace);
}
/*!
* Use this function to set the SchemeSettings. This function currently set the
* e.g. the screensaver and dpms settings. Don't forget to call this function if
* a scheme is changed or if the settings changed.
*/
void tdepowersave::setSchemeSettings(){
kdDebugFuncIn(trace);
// --> check if there is a scheme set, if not, use defaults
if ( settings->currentScheme.isEmpty()) {
if (hwinfo->getAcAdapter()) {
settings->load_scheme_settings( settings->ac_scheme);
} else {
settings->load_scheme_settings( settings->battery_scheme);
}
}
// --> set autosuspend settings
if(settings->autoSuspend) {
setAutoSuspend(false);
}
else {
this->contextMenu()->setItemVisible(AUTOSUSPEND_MENU_ID, false);
this->contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, false);
this->contextMenu()->setItemVisible(AUTOSUSPEND_SEPARATOR_MENU_ID, false);
autoSuspend->stop();
}
// --> set autodimm settings
if (settings->autoDimm) {
setAutoDimm(true);
} else {
autoDimm->stop();
}
// --> set screensaver
if(settings->specSsSettings){
if(settings->disableSs) display->setScreenSaver(false);
else {
display->setScreenSaver(true);
if(settings->blankSs) display->blankOnlyScreen(true);
else {
display->blankOnlyScreen(false);
}
}
} // TODO: check if this really work !!!
else if(getenv("TDE_FULL_SESSION")) {
// try to reset the complete screensaver settings. Ff this fail, use own methodes
if (!display->resetKDEScreensaver()) {
settings->load_kde();
// Always disable blankOnly screensaver setting (default). KDE does
// not provide a GUI to configure it and most likely we are the
// only ones messing with it
display->blankOnlyScreen(false);
// reset to global screensaver settings
if(!settings->kde->enabled) display->setScreenSaver(false);
else {
display->setScreenSaver(true);
// What should we do with settings->kde->lock ?
// Maybe nothing ?!
}
}
} else if ((getenv("DESKTOP_SESSION") != NULL) && !strcmp(getenv("DESKTOP_SESSION"), "gnome")) {
// use this to set XScreensaver back to default settings this should
// also cover the DPMS settings for GNOME/XScreensaver
display->resetXScreensaver();
}
// --> set DPMS settings
if(settings->specPMSettings){
// set the new DPMS settings
if(settings->disableDPMS) {
display->setDPMS(false);
}
else {
display->setDPMS(true);
display->has_DPMS = display->setDPMSTimeouts( settings->standbyAfter,
settings->suspendAfter,
settings->powerOffAfter);
}
}
else if(getenv("TDE_FULL_SESSION")){
// try to reset the KDE screensaver/DPMS settings (if there are also
// no special screensaver settings) otherwise fall back and set values from files
if (!settings->specSsSettings && !display->resetKDEScreensaver()) {
settings->load_kde();
// reset to global screensaver settings
if(!settings->kde->displayEnergySaving) {
display->setDPMS(false);
}
else {
display->setDPMS(true);
display->has_DPMS = display->setDPMSTimeouts( settings->kde->displayStandby,
settings->kde->displaySuspend,
settings->kde->displayPowerOff);
}
}
}
// --> set brightness settings
if(settings->brightness && hwinfo->supportBrightness()) {
// set to given values
hwinfo->setBrightness (-1, settings->brightnessValue);
}
// --> set CPU Freq settings
if(hwinfo->supportCPUFreq() && hwinfo->isCpuFreqAllowed()) {
hwinfo->setCPUFreq( settings->cpuFreqPolicy, settings->cpuFreqDynamicPerformance);
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT which called to set and start the autosuspend monitoring.
* \param resumed boolean value which represent information if machine
* currently back from suspend/standby
*/
void tdepowersave::setAutoSuspend( bool resumed ){
if (trace) kdDebug() << funcinfo << "IN: " << "resumed? " << resumed << endl;
// Verify that the desired suspend action is allowed before enabling autosuspend
SuspendStates suspend = hwinfo->getSuspendSupport();
bool allowed = false;
if(settings->autoInactiveAction == "Hibernate") {
if ( suspend.suspend2disk && (suspend.suspend2disk_allowed || suspend.suspend2disk_allowed == -1)) {
allowed = true;
}
}
else if(settings->autoInactiveAction == "Hybrid Suspend") {
if ( suspend.suspend_hybrid && (suspend.suspend_hybrid_allowed || suspend.suspend_hybrid_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Suspend") {
if( suspend.suspend2ram && (suspend.suspend2ram_allowed || suspend.suspend2ram_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Freeze") {
if ( suspend.freeze && (suspend.freeze_allowed || suspend.freeze_allowed == -1)) {
allowed = true;
}
}
else if (settings->autoInactiveAction == "Standby") {
if ( suspend.standby && (suspend.standby_allowed || suspend.standby_allowed == -1)) {
allowed = true;
}
}
if (!allowed) {
settings->autoSuspend = false;
}
if(settings->autoInactiveActionAfter > 0 && settings->autoSuspend) {
int autoInactiveActionAfter = 0;
if( settings->autoInactiveAction.startsWith("_NONE_")) {
autoSuspend->stop();
return;
}
if (resumed) {
autoSuspend->stop();
delete autoSuspend;
autoSuspend = new autosuspend(display);
connect(autoSuspend, TQT_SIGNAL(inactivityTimeExpired()), this, TQT_SLOT(do_autosuspendWarn()));
}
if (settings->autoSuspendCountdown && (settings->autoSuspendCountdownTimeout > 0)) {
autoInactiveActionAfter = ((settings->autoInactiveActionAfter * 60) -
settings->autoSuspendCountdownTimeout);
} else {
autoInactiveActionAfter = settings->autoInactiveActionAfter * 60;
}
if(settings->autoInactiveSBlistEnabled) {
autoSuspend->start( autoInactiveActionAfter, settings->autoInactiveSBlist );
}
else {
autoSuspend->start( autoInactiveActionAfter, settings->autoInactiveGBlist );
}
this->contextMenu()->setItemVisible(AUTOSUSPEND_SEPARATOR_MENU_ID, true);
this->contextMenu()->setItemVisible(AUTOSUSPEND_MENU_ID, true);
}
else {
// if autosuspend is not NULL: stop autosuspend
if (autoSuspend) {
autoSuspend->stop();
}
this->contextMenu()->setItemVisible(AUTOSUSPEND_MENU_ID, false);
this->contextMenu()->setItemVisible(AUTOSUSPEND_SEPARATOR_MENU_ID, false);
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT which called to set and start the autodimm monitoring.
* \param resumed boolean value which represent information if machine
* currently back from suspend/standby
*/
void tdepowersave::setAutoDimm( bool resumed ){
if (trace) kdDebug() << funcinfo << "IN: " << "resumed? " << resumed << endl;
if(settings->autoDimmAfter > 0 && settings->autoDimm) {
if(settings->autoDimmTo < 0) {
autoDimm->stop();
kdWarning() << "Not allowed or set level for dimm" << endl;
} else {
if (resumed) {
// setup again
autoDimm->stop();
delete autoDimm;
autoDimm = new autodimm(display);
connect(autoDimm, TQT_SIGNAL(inactivityTimeExpired()), this, TQT_SLOT(do_downDimm()));
connect(autoDimm, TQT_SIGNAL(UserIsActiveAgain()), this, TQT_SLOT(do_upDimm()));
}
if (settings->autoDimmSBlistEnabled) {
autoDimm->start(settings->autoDimmAfter * 60, settings->autoDimmSBlist);
} else {
autoDimm->start(settings->autoDimmAfter * 60, settings->autoDimmGBlist);
}
}
} else {
if (autoDimm)
autoDimm->stop();
}
kdDebugFuncOut(trace);
}
// -------- start KNotify functions ------------- //
/*!
* \b TQT_SLOT called if a battery warning state reached and related signal recieved.
* Here we emit the related KNotify event, if not disabled.
* \param type integer with the type of the battery
* \param state integer represent the reached battery state
*/
void tdepowersave::notifyBatteryStatusChange ( int type, int state ) {
if (trace) kdDebug() << funcinfo << "IN: " << "type: " << type << "state: " << state << endl;
if (type == BAT_PRIMARY) {
BatteryCollection *primary = hwinfo->getPrimaryBatteries();
int min = primary->getRemainingMinutes();
if (primary->getChargingState() == CHARGING) {
kdDebug() << "tdepowersave::notifyBatteryStatusChange: Battery is charging, ignore event" << endl;
return;
}
if (hwinfo->getAcAdapter()) {
// the machine is on AC, no need to inform about battery state,
// this is maybe only a race condition with not directly actuall
// charge state
kdDebug() << "tdepowersave::notifyBatteryStatusChange: Machine is on AC, ignore event" << endl;
kdDebugFuncOut(trace);
return;
}
switch (state) {
case BAT_WARN:
if (!settings->disableNotifications)
KNotifyClient::event(this->winId(), "battery_warning_event",
i18n("Battery state changed to WARNING -- remaining time: "
"%1 hours and %2 minutes.").arg(min/60).arg(min%60));
// set/call related actions
handleActionCall(settings->batteryWarningLevelAction,
settings->batteryWarningLevelActionValue);
break;
case BAT_LOW:
if (!settings->disableNotifications)
KNotifyClient::event(this->winId(), "battery_low_event",
i18n("Battery state changed to LOW -- remaining time: "
"%1 hours and %2 minutes.").arg(min/60).arg(min%60));
// set/call related actions
handleActionCall(settings->batteryLowLevelAction,
settings->batteryLowLevelActionValue);
break;
case BAT_CRIT:
// handle carefully:
if (settings->batteryCriticalLevelAction == GO_SHUTDOWN) {
if (!settings->disableNotifications)
KNotifyClient::event(this->winId(), "battery_critical_event",
i18n("Battery state changed to CRITICAL -- "
"remaining time: %1 hours and %2 minutes.\n"
"Shut down your system or plug in the power "
"cable immediately. Otherwise the machine\n"
"will go shutdown in 30 seconds")
.arg(min/ 60).arg(min%60));
TQTimer::singleShot(30000, this, TQT_SLOT(handleCriticalBatteryActionCall()));
} else {
if (!settings->disableNotifications)
KNotifyClient::event(this->winId(), "battery_critical_event",
i18n("Battery state changed to CRITICAL -- "
"remaining time: %1 hours and %2 minutes.\n"
"Shut down your system or plug in the power "
"cable immediately.")
.arg(min/ 60).arg(min%60));
handleActionCall(settings->batteryCriticalLevelAction,
settings->batteryCriticalLevelActionValue);
}
break;
default:
break;
}
} else {
// TODO: add some code later for the other batteries
}
kdDebugFuncOut(trace);
}
/*!
* Function to call the action for battery critical event. This is ugly, but
* because of TQTimer::singleShot() can't take param ...
* NOTE: Use this only for SHUTDOWN atm
*/
void tdepowersave::handleCriticalBatteryActionCall () {
kdDebugFuncIn(trace);
handleActionCall(GO_SHUTDOWN, settings->batteryCriticalLevelActionValue, true, true);
kdDebugFuncOut(trace);
}
/*!
* Function to set a special action for a battery warning level.
* \param action integer with the type of the action from \ref action
* \param value integer value of the action as e.g. a brightness level
* \param checkAC bool if there should be a check for AC state befor call the action
*/
void tdepowersave::handleActionCall ( action action, int value , bool checkAC, bool batWarnCall ) {
if (trace) kdDebug() << funcinfo << "IN: " << "action: " << action << "value: " << value
<< "checkAC: " << checkAC << endl;
if (hwinfo->currentSessionIsActive()) {
switch (action) {
case GO_SHUTDOWN:
// confirm that we really need/want to shutdown
if ((checkAC && !hwinfo->getAcAdapter()) || !checkAC ) {
DCOPRef shutdown = DCOPRef( "ksmserver", "ksmserver" );
shutdown.send("logout", 0, 2, 2);
}
break;
case LOGOUT_DIALOG:
{
// Do not display the logout dialog if the screen saver/lock system is active
bool saving = true;
TQString _method;
DCOPRef dcop_ref = DCOPRef( "kdesktop", "KScreensaverIface" );
_method = "isBlanked()";
DCOPReply reply = dcop_ref.call(_method.latin1());
if ( reply.isValid() ) {
if (!reply.get(saving)) {
saving = false;
}
}
if (!saving) {
DCOPRef shutdown = DCOPRef( "ksmserver", "ksmserver" );
shutdown.send("logout", 1, 2, 2);
}
}
break;
case GO_SUSPEND2RAM:
TQTimer::singleShot(100, this, TQT_SLOT(do_suspend2ram()));
break;
case GO_SUSPEND2DISK:
TQTimer::singleShot(100, this, TQT_SLOT(do_suspend2disk()));
break;
case GO_SUSPEND_HYBRID:
TQTimer::singleShot(100, this, TQT_SLOT(do_suspend_hybrid()));
break;
case GO_FREEZE:
TQTimer::singleShot(100, this, TQT_SLOT(do_freeze()));
break;
case BRIGHTNESS:
hwinfo->setBrightness( -1, value );
break;
case CPUFREQ_POWERSAVE:
hwinfo->setCPUFreq( POWERSAVE );
break;
case CPUFREQ_DYNAMIC:
hwinfo->setCPUFreq( DYNAMIC, settings->cpuFreqDynamicPerformance );
break;
case CPUFREQ_PERFORMANCE:
hwinfo->setCPUFreq( PERFORMANCE );
break;
case SWITCH_SCHEME: // not supported atm
case UNKNOWN_ACTION:
case NONE:
default:
kdError() << "Could not set the requested Action: " << action << endl;
break;
}
} else if (batWarnCall) {
// FIXME
// Is there a way to check if is active power manager on currently active session?
if (true) {
switch (action) {
case GO_SHUTDOWN:
// to be sure if we really need the shutdown
if ((checkAC && !hwinfo->getAcAdapter()) || !checkAC ) {
DCOPRef shutdown = DCOPRef( "ksmserver", "ksmserver" );
shutdown.send("logout", 0, 2, 2);
}
break;
default:
kdError() << "Could not call requested action, inactive session: " << action << endl;
break;
}
}
} else {
kdError() << "Could not set the requested action, session is inactiv: " << action << endl;
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if ac stated changed. Here we emit the related KNotify event.
* and switch to the AC/battery scheme depending on the state of AC
* \param acstate boolean represent the state of AC (true == AC plugged in ...)
*/
void tdepowersave::handleACStatusChange ( bool acstate , bool notifyEvent ) {
if (trace) kdDebug() << funcinfo << "IN: " << "acstate: " << acstate << "notifyEvent: " << notifyEvent << endl;
int index;
if (hwinfo->currentSessionIsActive()) {
// emit notify event
if(notifyEvent && !settings->disableNotifications) {
if (acstate) {
KNotifyClient::event(this->winId(), "plug_event", i18n("AC adapter plugged in"));
} else {
KNotifyClient::event(this->winId(), "unplug_event", i18n("AC adapter unplugged"));
}
}
// handle switch to AC/battery default scheme
if (acstate) {
index = settings->schemes.findIndex(settings->ac_scheme);
} else {
index = settings->schemes.findIndex(settings->battery_scheme);
}
if (index != -1)
do_setActiveScheme(index);
// update applet
update();
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if scheme switched. Here we emit the related KNotify events
* if they are not disabled.
*/
void tdepowersave::notifySchemeSwitch() {
kdDebugFuncIn(trace);
if(!settings->disableNotifications) {
TQString _scheme = settings->currentScheme;
TQString eventType;
if( _scheme != "Performance" && _scheme != "Powersave" && _scheme != "Acoustic" &&
_scheme != "Presentation" && _scheme != "AdvancedPowersave" )
eventType = "scheme_Unknown";
else
eventType = "scheme_" + _scheme;
KNotifyClient::event( this->winId(), eventType,
i18n("Switched to scheme: %1").arg(i18n(_scheme.utf8())));
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the machine suspend. Here we emit the related KNotify events
* if they are not disabled.
*/
void tdepowersave::notifySuspend( int suspendType ) {
kdDebugFuncIn(trace);
if(!settings->disableNotifications) {
switch (suspendType) {
case SUSPEND2DISK:
KNotifyClient::event( this->winId(), "suspend2disk_event",
i18n("System is going into %1 now.").
arg(i18n("hibernation")));
break;
case SUSPEND_HYBRID:
KNotifyClient::event( this->winId(), "suspend_hybrid_event",
i18n("System is going into %1 now.").
arg(i18n("hybrid suspension")));
break;
case SUSPEND2RAM:
KNotifyClient::event( this->winId(), "suspend2ram_event",
i18n("System is going into %1 now.").
arg(i18n("sleep")));
break;
case FREEZE:
KNotifyClient::event( this->winId(), "freeze_event",
i18n("System is going into %1 now.").
arg(i18n("freeze")));
break;
case STANDBY:
KNotifyClient::event( this->winId(), "standby_event",
i18n("System is going into %1 now.").
arg(i18n("standby")));
break;
default:
break;
}
}
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called to independent handleResumeSignal() from event loop and
* to avoid problems with the QT3 D-Bus bindings
*/
void tdepowersave::forwardResumeSignal( int result ) {
if (trace) kdDebug() << funcinfo << "IN: " << "result: " << result << endl;
resume_result = result;
TQTimer::singleShot(100, this, TQT_SLOT(handleResumeSignal()));
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the machine suspend. Here we emit the related KNotify events
* if they are not disabled.
*/
void tdepowersave::handleResumeSignal() {
kdDebugFuncIn(trace);
// fake key to show the login dialog if we locked the screen
if(settings->lockOnSuspend) {
activateLoginScreen();
}
// reset autosuspend and autodimm
setAutoSuspend(true);
setAutoDimm(true);
// reset the CPU Freq Policy ... for more see https://bugzilla.novell.com/show_bug.cgi?id=223164
if(hwinfo->supportCPUFreq() && hwinfo->isCpuFreqAllowed()) {
hwinfo->setCPUFreq( settings->cpuFreqPolicy, settings->cpuFreqDynamicPerformance );
}
if(!settings->disableNotifications) {
switch (calledSuspend) {
case SUSPEND2DISK:
KNotifyClient::event( this->winId(), "resume_from_suspend2disk_event",
i18n("System is resumed from %1.").arg(
i18n("hibernation")));
break;
case SUSPEND_HYBRID:
KNotifyClient::event( this->winId(), "resume_from_suspend_hybrid_event",
i18n("System is resumed from %1.").arg(
i18n("hybrid suspension")));
break;
case SUSPEND2RAM:
KNotifyClient::event( this->winId(), "resume_from_suspend2ram_event",
i18n("System is resumed from %1.").arg(
i18n("sleep")));
break;
case FREEZE:
KNotifyClient::event( this->winId(), "resume_from_freeze_event",
i18n("System is resumed from %1.").arg(
i18n("freeze")));
break;
case STANDBY:
KNotifyClient::event( this->winId(), "resume_from_standby_event",
i18n("System is resumed from %1.").arg(
i18n("standby")));
break;
default:
kdError() << "called suspend type unknown" << endl;
break;
}
}
// handle result of the resume/suspend
// 1 is a valid return code; don't error out when it is received!
if ((resume_result == 0) || (resume_result == 1) || (resume_result == INT_MAX)) {
if ( resume_result == INT_MAX )
kdWarning() << "Unknown if we successful resumed, look like a D-Bus timeout since "
<< "elapsed time between suspend and resume is higher than 6 hours" << endl;
// successful resumed ... remount only in this case
if (!handleMounts(false)) {
KPassivePopup::message( i18n("WARNING"),
i18n("Could not remount (all) external storage"
" media."), SmallIcon("messagebox_warning", 20),
this, i18n("Warning").utf8(), 15000);
}
} else {
kdError() << "Unknown error while suspend. Errorcode: " << resume_result << endl;
TQString msg;
msg = i18n("An unknown error occurred while %1. The errorcode is: '%2'").
arg(getSuspendString(calledSuspend)).arg(resume_result);
#if defined(DISTRO_IS_SUSE) || defined(DISTRO_IS_SLES_SLED) || defined(DISTRO_IS_PARDUS)
// okay we know this system use pm-utils and log is under /var/log/pm-suspend.log
msg += "\n" + i18n("Do you want to have a look at the log file?");
int answer = KMessageBox::questionYesNo(0, msg, i18n("Error while %1").
arg(getSuspendString(calledSuspend)));
if (answer == KMessageBox::Yes) {
#if defined(DISTRO_IS_SLES_SLED)
switch (calledSuspend) {
case SUSPEND2DISK:
logview = new LogViewer ("/var/log/suspend2disk.log");
logview->show();
break;
case SUSPEND_HYBRID:
logview = new LogViewer ("/var/log/suspend_hybrid.log");
logview->show();
break;
case SUSPEND2RAM:
logview = new LogViewer ("/var/log/suspend2ram.log");
logview->show();
break;
case FREEZE:
logview = new LogViewer ("/var/log/freeze.log");
logview->show();
break;
case STANDBY:
logview = new LogViewer ("/var/log/standby.log");
logview->show();
break;
default:
break;
}
#else
logview = new LogViewer ("/var/log/pm-suspend.log");
logview->show();
#endif
}
#else
KMessageBox::error(0, msg, i18n("Error while %1").arg(getSuspendString(calledSuspend)));
#endif
}
// set back ... suspend is handled
calledSuspend = -1;
resume_result = 0;
kdDebugFuncOut(trace);
}
/*!
* \b TQT_SLOT called if the state of the current session change
* \param state boolean represent the state of the session
* TODO: fix scheme handling
* TODO: fix critical battery situations (see the todo file in the source)
*/
void tdepowersave::handleSessionState (bool state) {
kdDebugFuncIn(trace);
if (state) {
// session is active again
if (settings->autoSuspend) disableAutosuspend(false);
if (settings->autoDimm) setAutoDimm(false);
/* handle may missed/not set AC status changes while the
session was inactive and set them to the default schemes ?! */
handleACStatusChange(hwinfo->getAcAdapter(), false);
} else {
// session is now inactive
if (settings->autoSuspend) disableAutosuspend(true);
if (settings->autoDimm) autoDimm->stop();
}
kdDebugFuncOut(trace);
}
// -------- end KNotify functions ------------- //
// ------------ helper functions -------------- //
/*!
* Helper function to get a i18n name for a suspend type.
* \param type Integer value with the suspend type
* \return TQString with the translated name or NULL if it fail
*/
TQString tdepowersave::getSuspendString (int type) {
kdDebugFuncIn(trace);
switch (type) {
case SUSPEND2DISK:
return i18n("Hibernate");
break;
case SUSPEND_HYBRID:
return i18n("Hybrid Suspend");
break;
case SUSPEND2RAM:
return i18n("Suspend");
break;
case FREEZE:
return i18n("Freeze");
break;
case STANDBY:
return i18n("Standby");
break;
default:
return TQString();
}
kdDebugFuncOut(trace);
}
// --------- end helper functions ------------- //
// ------------ DCOP functions ---------------- //
/*!
* DCOP Interface funtion to lock the screen with the userdefined methode.
* \return boolean with the result of locking the screen
* \retval true if locking the screen was successful
* \retval false if locking the screen failed or the user don't wan't to lock
*/
bool tdepowersave::lockScreen(){
kdDebugFuncIn(trace);
settings->load_general_settings();
return display->lockScreen( settings->lockmethod );
kdDebugFuncOut(trace);
}
/*!
* DCOP Interface funtion to return the name of the current powersave scheme.
* \return TQString with the name of the current scheme
*/
TQString tdepowersave::currentScheme (){
kdDebugFuncIn(trace);
if(hwinfo->isOnline()) {
return settings->currentScheme;
} else {
return "ERROR: D-Bus not running";
}
kdDebugFuncOut(trace);
}
/*!
* DCOP Interface funtion to return the name of the current cpuFreqPolicy.
* \return TQString with the name of the current cpuFreqPolicy
*/
TQString tdepowersave::currentCPUFreqPolicy() {
kdDebugFuncIn(trace);
if(hwinfo->isOnline()) {
TQString _cpuFreq = "";
switch (hwinfo->getCurrentCPUFreqPolicy()){
case PERFORMANCE:
_cpuFreq = "PERFORMANCE";
break;
case DYNAMIC:
_cpuFreq = "DYNAMIC";
break;
case POWERSAVE:
_cpuFreq = "POWERSAVE";
break;
default:
_cpuFreq = "UNKNOWN";
break;
}
return _cpuFreq;
} else {
return "ERROR: DBus not running";
}
kdDebugFuncOut(trace);
}
/*!
* DCOP Interface funtion to send a list with the allowed
* CPU Frequency states.
* \return TQStringList with the supported CPUFreq states
*/
TQStringList tdepowersave::listCPUFreqPolicies() {
kdDebugFuncIn(trace);
TQStringList ret_list;
if (hwinfo->isCpuFreqAllowed()) {
ret_list.append("PERFORMANCE");
ret_list.append("DYNAMIC");
ret_list.append("POWERSAVE");
}
else {
ret_list.append("NOT SUPPORTED");
}
kdDebugFuncOut(trace);
return ret_list;
}
/*!
* DCOP Interface funtion to set the current CPUFreq policy
* \param policy TQString with the policy to set, only values from
* list_CPUFreqPolicies are allowed (except "NOT SUPPORTED")
* \return boolean with the result of set the requested CPUFreq policy
* \retval true if successful set
* \retval false if not supported or any other failure
*/
bool tdepowersave::do_setCPUFreqPolicy( TQString policy ) {
if (trace) kdDebug() << funcinfo << "IN: " << "policy: " << policy << endl;
bool ret = true;
/*
if (hwinfo->isCpuFreqAllowed() && hwinfo->isOnline()) {
if (policy == "PERFORMANCE") {
hwinfo->setCPUFreq(PERFORMANCE);
} else if (policy == "DYNAMIC") {
hwinfo->setCPUFreq(DYNAMIC, settings->cpuFreqDynamicPerformance);
} else if (policy == "POWERSAVE") {
hwinfo->setCPUFreq(POWERSAVE);
} else {
kdDebugFuncOut(trace);
ret = false;
}
} else {
ret = false;
}
*/
kdDebugFuncOut(trace);
return ret;
}
/*!
* DCOP Interface funtion to send a list with the supported and enabled
* sleeping states.
* \return TQStringList with the supported spleeping states
*/
TQStringList tdepowersave::allowed_sleepingStates(){
kdDebugFuncIn(trace);
TQStringList sleepList;
if(hwinfo->isOnline()) {
if (suspend.suspend2disk && (suspend.suspend2disk_allowed ||
suspend.suspend2disk_allowed == -1)){
sleepList.append("suspendToDisk");
}
if (suspend.suspend_hybrid && (suspend.suspend_hybrid_allowed ||
suspend.suspend_hybrid_allowed == -1)){
sleepList.append("suspendHybrid");
}
if (suspend.suspend2ram && (suspend.suspend2ram_allowed ||
suspend.suspend2ram_allowed == -1)){
sleepList.append("suspendToRAM");
}
if (suspend.freeze && (suspend.freeze_allowed || suspend.freeze_allowed == -1)){
sleepList.append("freeze");
}
if (suspend.standby && (suspend.standby_allowed || suspend.standby_allowed == -1)){
sleepList.append("standBy");
}
if(sleepList.isEmpty()){
sleepList.append("NO_SLEEPING_STATES_SUPPORTED");
}
}
else {
sleepList.append("ERROR: D-Bus not running");
}
kdDebugFuncOut(trace);
return sleepList;
}
/*!
* DCOP Interface funtion to send a list with the all schemes.
* \return TQStringList with all schemes
*/
TQStringList tdepowersave::listSchemes(){
kdDebugFuncIn(trace);
TQStringList _schemeList;
if(hwinfo->isOnline()) {
if (settings->schemes.count() > 0){
_schemeList = settings->schemes;
}
}
else {
_schemeList.append("ERROR: D-Bus not running");
}
kdDebugFuncOut(trace);
return _schemeList;
}
/*!
* DCOP Interface funtion to set the current scheme.
* \return boolean with the result of set the requested scheme
* \retval false if failed (e.g. scheme is not in the list)
* \retval true if scheme found and set
* \param _scheme TQString with the scheme to set, scheme should be
* named as list from list_schemes()
*/
bool tdepowersave::do_setScheme( TQString /*_scheme*/ ) {
kdDebugFuncIn(trace);
/* int index;
index = settings->schemes.findIndex(_scheme);
if (index != -1) {
do_setActiveScheme(index);
kdDebugFuncOut(trace);
return true;
}
else {
kdDebugFuncOut(trace);
return false;
}
*/
kdDebugFuncOut(trace);
return false;
}
/*!
* DCOP Interface funtion to send the suspend to disk command to powersave.
* \return boolean with the result of calling do_suspend2disk()
* \retval true if successful
* \retval false if not supported or powersaved not running
*/
bool tdepowersave::do_suspendToDisk(){
kdDebugFuncIn(trace);
kdDebugFuncOut(trace);
return do_suspend2disk();
}
/*!
* DCOP Interface funtion to send the hybrid suspend command to powersave.
* \return boolean with the result of calling do_suspend_hybrid()
* \retval true if successful
* \retval false if not supported or powersaved not running
*/
bool tdepowersave::do_suspendHybrid(){
kdDebugFuncIn(trace);
kdDebugFuncOut(trace);
return do_suspend_hybrid();
}
/*!
* DCOP Interface funtion to send the suspend to disk command to powersave.
* \return boolean with the result of calling do_suspend2ram()
* \retval true if successful
* \retval false if not supported or powersaved not running
*/
bool tdepowersave::do_suspendToRAM(){
kdDebugFuncIn(trace);
kdDebugFuncOut(trace);
return do_suspend2ram();
}
/*!
* DCOP Interface funtion to send the freeze command to powersave.
* \return boolean with the result of calling do_freeze()
* \retval true if successful
* \retval false if not supported or powersaved not running
*/
bool tdepowersave::do_suspendFreeze(){
kdDebugFuncIn(trace);
kdDebugFuncOut(trace);
return do_freeze();
}
/*!
* DCOP Interface funtion to send the standby command to powersave.
* \return boolean with the result of calling do_standby()
* \retval true if successful
* \retval false if not supported or powersaved not running
*/
bool tdepowersave::do_standBy(){
kdDebugFuncIn(trace);
kdDebugFuncOut(trace);
return do_standby();
}
//! dcop function to set the brightness up
bool tdepowersave::do_brightnessUp(int percentageStep) {
kdDebugFuncIn(trace);
bool retval = false;
if(hwinfo->isOnline()) {
retval = hwinfo->setBrightnessUp(percentageStep);
}
kdDebugFuncOut(trace);
return retval;
}
//! dcop function to set the brightness down
bool tdepowersave::do_brightnessDown(int percentageStep) {
kdDebugFuncIn(trace);
bool retval = false;
if(hwinfo->isOnline()) {
retval = hwinfo->setBrightnessDown(percentageStep);
}
kdDebugFuncOut(trace);
return retval;
}
/*!
* DCOP Interface funtion to stop/start the Autosuspend
* \param disable boolean which tell if the autosuspend should be stopped (true)
* or started (false).
*/
void tdepowersave::disableAutosuspend( bool disable ){
kdDebugFuncIn(trace);
if(settings->autoSuspend && settings->autoInactiveActionAfter > 0) {
if (disable) {
if ( !contextMenu()->isItemChecked(AUTOSUSPEND_MENU_ID)) {
autoSuspend->stop();
contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, true);
}
}
else {
contextMenu()->setItemChecked(AUTOSUSPEND_MENU_ID, false);
setAutoSuspend(true);
}
}
kdDebugFuncOut(trace);
}
/*!
* DCOP Interface funtion to open/close the detailed dialog.
*/
void tdepowersave::showDetailedDialog( ){
kdDebugFuncIn(trace);
if (detailedIsShown) {
detailedDlg->close();
delete(detailedDlg);
closedetaileddialog();
return;
}
detailedDlg = new detaileddialog(hwinfo, &fullIcon, settings);
if (detailedDlg) {
detailedDlg->show();
detailedIsShown = true;
}
connect(detailedDlg, TQT_SIGNAL(destroyed()), this, TQT_SLOT(closedetaileddialog()));
kdDebugFuncOut(trace);
}
/*!
* DCOP Interface funtion to open the configure dialog.
* \return boolean with the result of open the dialog
* \retval false if failed
* \retval true if correct opend
*/
bool tdepowersave::openConfigureDialog (){
kdDebugFuncIn(trace);
if(hwinfo->isOnline()) {
showConfigureDialog();
kdDebugFuncOut(trace);
return config_dialog_shown;
} else {
kdDebugFuncOut(trace);
return false;
}
}
/*!
* DCOP Interface funtion to find out if the current
* scheme manages DPMS
* \return boolean
* \retval false if current scheme does not overwrite DPMS
* \retval true if current scheme does
*/
bool tdepowersave::currentSchemeManagesDPMS () {
kdDebugFuncIn(trace);
return settings->specPMSettings;
kdDebugFuncOut(trace);
}
//! dcop funtion to get the current brightness level
int tdepowersave::brightnessGet() {
kdDebugFuncIn(trace);
int retval = -1;
if (hwinfo->supportBrightness()) {
retval = (int)(100.0 * hwinfo->getCurrentBrightnessLevel() / hwinfo->getMaxBrightnessLevel());
}
kdDebugFuncOut(trace);
return retval;
}
//! dcop funtion to set the brightness level
void tdepowersave::brightnessSet(int percentage)
{
kdDebugFuncIn(trace);
if (hwinfo->supportBrightness() && percentage >= 0 && percentage <= 100)
{
hwinfo->setBrightness(-1, percentage);
}
kdDebugFuncOut(trace);
}
#include "tdepowersave.moc"