/**************************************************************************
 *   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.          *
 ***************************************************************************/

// 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>

// 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();
	autoDimm = new autodimm();
	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){
			config->writeEntry("Autostart", false);
			config->sync();
			kdError() << "This machine does not support ACPI, APM, PMU, CPUFreq, Suspend2Disk nor "
			          << "Suspend2RAM. 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 mesages
	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 (handleSleepButtonEvent()));
	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( "Sleep button", i18n( "Sleep configured power button action"), TQString(),
			TDEShortcut(TQString("XF86Sleep")), TDEShortcut(TQString("XF86Sleep")), TQT_TQOBJECT(this), TQT_SLOT( handleSleepButtonEvent() ) );
	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();
	SUSPEND2DISK_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_disk",
								TQIconSet::Automatic),
								i18n("Suspend to Disk"), this,
								TQT_SLOT(do_suspend2disk()));
	SUSPEND2RAM_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("suspend_to_ram",
							       TQIconSet::Automatic),
							       i18n("Suspend to RAM"), this,
							       TQT_SLOT(do_suspend2ram()));
	STANDBY_MENU_ID = this->contextMenu()->insertItem( SmallIconSet("stand_by", TQIconSet::Automatic),
							   i18n("Standby"), this, TQT_SLOT(do_standby()));

	speed_menu = new TQPopupMenu(this, i18n("Set CPU Frequency Policy").ascii());
	speed_menu->insertItem(i18n("Performance"), PERFORMANCE);
	speed_menu->insertItem(i18n("Dynamic"), DYNAMIC);
	speed_menu->insertItem(i18n("Powersave"), POWERSAVE);

	CPUFRETQ_SEPARATOR_MENU_ID = contextMenu()->insertSeparator();

	CPUFRETQ_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").ascii());
	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();

	help_menu = new TQPopupMenu(this, i18n("&Help").ascii());

	help_menu->insertItem( SmallIcon("help", TQIconSet::Automatic), i18n("&TDEPowersave Handbook"),
			       this, TQT_SLOT(slotHelp()));
	help_menu->insertSeparator();
	help_menu->insertItem( i18n("&Report a bug ..."), this, TQT_SLOT(slotReportBug()));
	help_menu->insertItem( SmallIcon("tdepowersave", TQIconSet::Automatic),
			       i18n("&About TDEPowersave"), this, TQT_SLOT(slotAbout()));

	HELP_MENU = contextMenu()->insertItem(SmallIcon("help", TQIconSet::Automatic),
							i18n("&Help"), help_menu);

	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").ascii(), 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", width(), TDEIcon::DisabledState);
		}
		else
			pixmap = SmallIcon(pixmap_name, width());
	}

	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:
	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 open the website to report bugs
 */
void tdepowersave::slotReportBug()
{
#ifdef DISTRO_IS_SUSE
 #ifdef DISTRO_IS_SLES_SLED
	kapp->invokeBrowser("https://bugzilla.novell.com/");
 #else
	kapp->invokeBrowser("http://en.opensuse.org/Submitting_Bug_Reports");
 #endif
#else
 #ifdef DISTRO_IS_ALTLINUX
	kapp->invokeBrowser("http://bugzilla.altlinux.org/");
 #else
  #ifdef DISTRO_IS_UBUNTU
	kapp->invokeBrowser("https://launchpad.net/distros/ubuntu/+bugs");
  #else
   #ifdef DISTRO_IS_PARDUS
	kapp->invokeBrowser("http://bugs.pardus.org.tr/");
   #else
	kapp->invokeBrowser("http://sourceforge.net/tracker/?group_id=124576&atid=700009");
   #endif
  #endif
 #endif
#endif
}

/*!
 * \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 HAL daemon.
 * If there is a error while "suspend to disk" the user get e messagebox.
 * This function need a running HAL daemon 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("Suspend to disk failed"),
							SmallIcon("messagebox_warning", 20), this,
							i18n("Warning").ascii(), 15000);
				kdDebugFuncOut(trace);
				return false;
			}
		} else {
			KPassivePopup::message( i18n("WARNING"),
						i18n("Suspend to disk disabled by administrator."),
						SmallIcon("messagebox_warning", 20),
						this, i18n("Warning").ascii(), 15000);
			this->contextMenu()->setItemEnabled(SUSPEND2DISK_MENU_ID, false);
			kdDebugFuncOut(trace);
			return false;
		}
	} else {
		kdWarning() << "This machine does not provide suspend2disk via HAL" << endl;
		kdDebugFuncOut(trace);
		return false;
	}
}

/*!
 * \b TQT_SLOT to send the command for "suspend to RAM" to the HAL daemon.
 * If there is a error while "suspend to RAM" the user get e messagebox.
 * This function need a running HAL daemon 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 to RAM failed"),
							SmallIcon("messagebox_warning", 20), this,
							i18n("Warning").ascii(), 15000);
				kdDebugFuncOut(trace);
				return false;
			}
		} else {
			KPassivePopup::message( i18n("WARNING"),
						i18n("Suspend to RAM disabled by administrator."),
						SmallIcon("messagebox_warning", 20), this,
						i18n("Warning").ascii(), 15000);
			this->contextMenu()->setItemEnabled(SUSPEND2RAM_MENU_ID, false);
			kdDebugFuncOut(trace);
			return false;
		}
	} else {
		kdWarning() << "This machine does not provide suspend2ram via HAL" << endl;
		kdDebugFuncOut(trace);
		return false;
	}
}

/*!
 * \b TQT_SLOT to send the command for "stand-by" to the HAL daemon.
 * If there is a error while "stand-by" the user get e messagebox.
 * This function need a running HAL daemon 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").ascii(), 15000);
				kdDebugFuncOut(trace);
				return false;
			}
		} else {
			KPassivePopup::message( i18n("WARNING"),i18n("Standby disabled by administrator."),
						SmallIcon("messagebox_warning", 20), this,
						i18n("Warning").ascii(), 15000);
			this->contextMenu()->setItemEnabled(STANDBY_MENU_ID, false);
			kdDebugFuncOut(trace);
			return false;
		}
	} else {
		kdWarning() << "This machine does not provide suspend2ram via HAL" << 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 == "Suspend to Disk") {
		if ( suspend.suspend2disk && (suspend.suspend2disk_allowed || suspend.suspend2disk_allowed == -1)) {
			allowed = true;
		}
	}
	else if (settings->autoInactiveAction == "Suspend to RAM") {
		if( suspend.suspend2ram && (suspend.suspend2ram_allowed || suspend.suspend2ram_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 == "Suspend to Disk") {
					countdown->setPixmap("suspend2disk");
				} else if (settings->autoInactiveAction == "Suspend to RAM") {
					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  chancel boolean with info if the autosuspend should get chanceld
 * \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 befor send and
 *		add message for this case to tell that maybe changed config!
 */
bool tdepowersave::do_autosuspend(bool chancel) {
	kdDebugFuncIn(trace);

	// TODO: check if this is really needed, it get called also on the suspend methodes
	autoSuspend->stop();

	if (!chancel) {
		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 == "Suspend to Disk") {
				return do_suspend2disk();
			} else if (settings->autoInactiveAction == "Suspend to RAM") {
				return do_suspend2ram();
			} else if (settings->autoInactiveAction == "Standby") {
				return do_standby();
			} else {
				return false;
			}
		} else {
			return false;
		}
	} else {
		kdDebug() << "The autosuspend was chanceled (via the chancel 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::handleSleepButtonEvent() {
	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").ascii(), 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 CPUFRETQ_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").ascii(), 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").ascii(), 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(SUSPEND2DISK_MENU_ID, false);
		this->contextMenu()->setItemVisible(SUSPEND2RAM_MENU_ID, false);
		this->contextMenu()->setItemVisible(STANDBY_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(SUSPEND2DISK_MENU_ID, true);
		this->contextMenu()->setItemVisible(SUSPEND2RAM_MENU_ID, true);
		this->contextMenu()->setItemVisible(STANDBY_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.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.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(CPUFRETQ_MENU_ID, true);
		contextMenu()->setItemEnabled(CPUFRETQ_MENU_ID, true);
		contextMenu()->setItemVisible(CPUFRETQ_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(CPUFRETQ_MENU_ID, false);
			contextMenu()->setItemVisible(CPUFRETQ_SEPARATOR_MENU_ID, true);
		} else{
			/* there were CPU freq policies, but they are not accessible any more */
			/* delete speed_menu */
			contextMenu()->setItemVisible(CPUFRETQ_MENU_ID, false);
                        contextMenu()->setItemVisible(CPUFRETQ_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).ascii() ), x, x);
		}
		else{
			if ( *it == settings->battery_scheme ){
				scheme_menu->insertItem(SmallIcon("scheme_powersave", TQIconSet::Automatic),
							i18n( (*it).ascii() ), 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).ascii() ), 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").ascii(), 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);
		}
	}

	// call setPowerSave() depending on AC state
	if (settings->callSetPowerSaveOnAC) {
		if (hwinfo->getAcAdapter())
			hwinfo->setPowerSave(false);
		else
			hwinfo->setPowerSave(true);
	}

	// --> 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->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 == "Suspend to Disk") {
		if ( suspend.suspend2disk && (suspend.suspend2disk_allowed || suspend.suspend2disk_allowed == -1)) {
			allowed = true;
		}
	}
	else if (settings->autoInactiveAction == "Suspend to RAM") {
		if( suspend.suspend2ram && (suspend.suspend2ram_allowed || suspend.suspend2ram_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();
			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();
				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 BRIGHTNESS:
				hwinfo->setBrightness( -1, value );
				break;
			case CPUFRETQ_POWERSAVE:
				hwinfo->setCPUFreq( POWERSAVE );
				break;
			case CPUFRETQ_DYNAMIC:
				hwinfo->setCPUFreq( DYNAMIC, settings->cpuFreqDynamicPerformance );
				break;
			case CPUFRETQ_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) {
		if (!hwinfo->isPolicyPowerIfaceOwned()) {
			switch (action) {
				case GO_SHUTDOWN:
					// to be shure 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.ascii())).ascii());
	}

	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("Suspend to Disk")));
				break;
			case SUSPEND2RAM:
				KNotifyClient::event( this->winId(), "suspend2ram_event",
						      i18n("System is going into %1 now.").
						      arg(i18n("Suspend to RAM")));
				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->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("Suspend to Disk")));
				break;
			case SUSPEND2RAM:
				KNotifyClient::event( this->winId(), "resume_from_suspend2ram_event",
					      	      i18n("System is resumed from %1.").arg(
						      i18n("Suspend to RAM")));
				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").ascii(), 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 SUSPEND2RAM:
					logview = new LogViewer ("/var/log/suspend2ram.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("Suspend to Disk");
			break;
		case SUSPEND2RAM:
			return i18n("Suspend to RAM");
			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 and/or HAL 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: HAL or/and 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.suspend2ram && (suspend.suspend2ram_allowed ||
		    suspend.suspend2ram_allowed == -1)){
			sleepList.append("suspendToRAM");
		}
		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 and/or HAL 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 and/or HAL 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 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 suspend to disk 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 (e.g. D-Bus or HAL is not running)
 * \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)(((float)hwinfo->getCurrentBrightnessLevel() / (float)hwinfo->getMaxBrightnessLevel()-1) * 100.0);
	}

	kdDebugFuncOut(trace);

	return retval;
}

#include "tdepowersave.moc"