/*
	mmainwindow.cpp - The main window
	Copyright (C) 2003  Konrad Twardowski <kdtonline@poczta.onet.pl>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "appobserver.h"
#include "configuration.h"
#include "confirmation.h"
#include "extras.h"
#include "miscutils.h"
#include "mmainwindow.h"
#include "mmessagedialog.h"
#include "msettingsdialog.h"
#include "mstatstab.h"
#include "msystemtray.h"
#include "progressbar.h"
#include "systemconfig.h"

#include <tqdatetimeedit.h>
#include <tqfile.h>
#include <tqhbox.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqtimer.h>
#include <tqtooltip.h>
#include <tqvgroupbox.h>
#include <tqwhatsthis.h>

#include <dcopclient.h>
#include <tdeaction.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kglobalaccel.h>
#include <kkeydialog.h>
#include <tdelocale.h>
#include <tdemenubar.h>
#include <tdemessagebox.h>
#include <knotifydialog.h>
#include <tdepopupmenu.h>
#include <kpushbutton.h>
#include <twin.h>
#include <kdesktopfile.h>
#include <kmimetype.h>

MMainWindow *MMainWindow::_instance = 0;

MMainWindow::MMainWindow()
	// Iface
	: DCOPObject("KShutdownIface"),
	TDEMainWindow(0, "MMainWindow", WStyle_ContextHelp),
	_showMinimizeInfo(true),
	_oldSec(-1),
	_delayType(DelayType_Now)
{
	_instance = this;
	connect(kapp, TQ_SIGNAL(aboutToQuit()), TQ_SLOT(slotAboutToQuit()));

	// init date/time
	dt_end = TQDateTime();
	dt_start = TQDateTime();

	// action timeout timer
	_timer = new TQTimer(this);
	connect(_timer, TQ_SIGNAL(timeout()), TQ_SLOT(slotCheckTime()));

	// init widgets
	setCentralWidget(initWidgets());
	initActions();
	initMainMenu();

	// init DCOP
	DCOPClient *client = kapp->dcopClient();
	client->registerAs(kapp->name(), false);
	client->setDefaultObject(objId()); // KShutdownIface

	TDEConfig *config = kapp->config();
	config->setGroup("Extras");
	TQString extrasCommand = config->readEntry("Command", TQString::null);
	TQString extrasDescription = config->readEntry("Description", TQString::null);
	if (!extrasCommand.isEmpty() || TQFile::exists(extrasCommand)) {
		setAction(Action::Extras);

		TQIconSet extrasIcon;
		TQString mimeType;
		mimeType = KMimeType::findByPath(extrasCommand)->name();
		if (mimeType != "application/x-desktop")
			extrasIcon = TQIconSet(KMimeType::pixmapForURL(KURL::fromPathOrURL(extrasCommand)));
		else {
			// application/x-desktop
			KDesktopFile *desktopFile = new KDesktopFile(extrasCommand, true);
			if (desktopFile->getConfigState() != TDEConfigBase::NoAccess)
				extrasIcon = TQIconSet(SmallIcon(desktopFile->readIcon()));
			delete desktopFile;
		}
		ks_extras->setAction(extrasCommand, extrasDescription, &extrasIcon);
	}
	else {
		setAction((Action::Type)kshutdownrc->generalAction);
	}
	setDelayType((DelayType)kshutdownrc->generalDelayType);

	MSystemTray::setMode((MSystemTray::Mode)kshutdownrc->systemTray);

	setCaptions();
	slotUpdateTimeInfo();

	setFixedHeight(layout()->minimumSize().height());
}

MMainWindow::~MMainWindow()
{
	TDEConfig *config = kapp->config();
	config->setGroup("Extras");
	config->writeEntry("Command", ks_extras->fileToExecute());
	config->writeEntry("Description", ks_extras->getActionDescription());

// TODO: 2.0: remember/restore time
	kshutdownrc->generalAction = ks_actions->current();
	kshutdownrc->generalDelayType = cb_delayTypes->currentItem();
	kshutdownrc->writeConfig();
}

void MMainWindow::setDelayType(const DelayType value)
{
	// kdDebug() << "MMainWindow::setDelayType: " << value << endl;

	if (MiscUtils::isRestricted("tab_time"))
	{
		_delayType = DelayType_Now;
		cb_delayTypes->setEnabled(false);
	}
	else
	{
		_delayType = value;
		cb_delayTypes->setEnabled(true);
	}

	cb_delayTypes->setCurrentItem(_delayType);

	switch (_delayType)
	{
		case DelayType_Now:
			_dateTimeEdit->dateEdit()->setEnabled(false);
			_dateTimeEdit->timeEdit()->setEnabled(false);
			_dateTimeEdit->show();
			_appObserver->hide();
			l_statusLine->hide();
			break;
		case DelayType_TimeFromNow:
			TQWhatsThis::add(_dateTimeEdit, i18n("Enter hour and minute."));
			_dateTimeEdit->dateEdit()->setEnabled(false);
			_dateTimeEdit->timeEdit()->setEnabled(true);
			_dateTimeEdit->timeEdit()->setDisplay(TQTimeEdit::Hours | TQTimeEdit::Minutes);
			_dateTimeEdit->timeEdit()->setTime(TQTime());
			_dateTimeEdit->show();
			_appObserver->hide();
			l_statusLine->show();
			break;
		case DelayType_DateTime:
			TQWhatsThis::add(_dateTimeEdit, i18n("Enter date and time."));
			_dateTimeEdit->dateEdit()->setEnabled(true);
			_dateTimeEdit->timeEdit()->setEnabled(true);
			_dateTimeEdit->timeEdit()->setDisplay(
				TDEGlobal::locale()->use12Clock()
				? (TQTimeEdit::Hours | TQTimeEdit::Minutes | TQTimeEdit::AMPM)
				: (TQTimeEdit::Hours | TQTimeEdit::Minutes)
			);
			_dateTimeEdit->dateEdit()->setDate(TQDate::currentDate());
			_dateTimeEdit->timeEdit()->setTime(TQTime::currentTime());
			_dateTimeEdit->show();
			_appObserver->hide();
			l_statusLine->show();
			break;
		case DelayType_OnAppExit:
			_dateTimeEdit->hide();
			_appObserver->show();
			_appObserver->refresh();
			l_statusLine->hide();
			break;
	}
}

void MMainWindow::setTime(const TQTime &time)
{
	_dateTimeEdit->timeEdit()->setTime(TQTime(time.hour(), time.minute(), 0));
}

void MMainWindow::setAction(const Action::Type action)
{
	// kdDebug() << "MMainWindow::setAction: " << ks_actions->getName(action) << endl;

	if (!ks_actions->isEnabled(action))
	{
// FIXME: 2.0: "Start" button incorectly disabled/enabled after config change
// FIXME: 2.0: confusing
		_startAction->setEnabled(false);

		return;
	}
	_startAction->setEnabled(true);

	ks_actions->setCurrent(action);
	cb_actions->setCurrentItem(action - 1);
	switch (action)
	{
		case Action::Nothing:
		case Action::ShutDown:
		case Action::Reboot:
		case Action::LockScreen:
		case Action::Logout:
			ks_extras->button()->hide();
			break;
		case Action::Extras:
			ks_extras->button()->show();
			break;
	}
}

void MMainWindow::setDate(const TQDate &date)
{
	_dateTimeEdit->dateEdit()->setDate(date);
}

void MMainWindow::start(const bool confirmation) {
	if (ks_actions->active())
		return;

	// kdDebug() << "MMainWindow::start" << endl;

	// check if selected process still exists
	if ((_delayType == DelayType_OnAppExit) && !_appObserver->isValid())
		return;

	// display information if user didn't selected any "extras" command
	if ((ks_actions->current() == Action::Extras) && ks_extras->fileToExecute().isNull())
	{
		KMessageBox::information(
			this,
			MiscUtils::HTML(i18n("Click the <b>Select a command...</b> button first."))
		);

		return;
	}

	if (confirmation)
	{
		if (!Confirmation::confirm(ks_actions->current(), getTimeInfo()))
			return; // action not confirmed by user; do nothing
	}

	// immediate action
	if (
		(_delayType == DelayType_Now) ||
		(
			(_delayType == DelayType_TimeFromNow) &&
			(_dateTimeEdit->timeEdit()->time().hour() == 0) &&
			(_dateTimeEdit->timeEdit()->time().minute() == 0)
		)
	)
	{
		ks_actions->execCurrent();

		return;
	}

	ks_actions->setActive(true);

	MSystemTray::setMode((MSystemTray::Mode)kshutdownrc->systemTray);

	setWidgetsEnabled(false); // disable widgets

	slotUpdateTimeInfo();

	_oldSec = -1;

	if (MSystemTray::isInstance())
		ks_tray->setActive(true);

	if ((_delayType != DelayType_OnAppExit) && (dt_end < dt_start))
	{
		TQString selDT = i18n("Selected date/time: %1").arg("<b>" + TDEGlobal::locale()->formatDateTime(dt_end, false, true)+ "</b>");
		TQString curDT = i18n("Current date/time: %1").arg("<b>" + TDEGlobal::locale()->formatDateTime(dt_start, false, true) + "</b>");

		cancel();
		KMessageBox::error(
			0,
			MiscUtils::HTML(
				i18n("Selected date/time is earlier than current date/time!") +
				"<br><br>" +
				selDT + "<br>" +
				curDT + "<br>" \
				"<br>" +
				i18n("Action cancelled!")
			)
		);

		return;
	}

	int secsTo = dt_start.secsTo(dt_end);

	// setup progress bar
	if (kshutdownrc->progressBarEnabled) {
		ProgressBar *progressBar = ProgressBar::getInstance();
		progressBar->setValues(0, secsTo);
		progressBar->show();
	}

	if (_delayType == DelayType_OnAppExit)
	{
		_timer->start(2000);
		setCaptions(TQString::null, _appObserver->getInfo());
	}
	else
	{
		_timer->start(500); // this timer value is good ..
		updateTimeInfo(secsTo);
	}
}

void MMainWindow::cancel()
{
	MMessageDialog::cancel();

	if (!ks_actions->active() && (_delayType != DelayType_OnAppExit))
		return;

	// kdDebug() << "MMainWindow::cancel" << endl;

	ks_actions->setActive(false);
	MSystemTray::setMode((MSystemTray::Mode)kshutdownrc->systemTray);

	_timer->stop();
	setCaptions();
	if (MSystemTray::isInstance())
		ks_tray->setActive(false);

	ProgressBar::freeInstance();

	setWidgetsEnabled(true);
// TODO: 2.0: MiscUtils::customMessage(i18n("Action cancelled!"));
}

bool MMainWindow::shutDown()
{
	return ks_actions->exec(Action::ShutDown);
}

bool MMainWindow::shutdown()
{
	return shutDown();
	//.........^^
}

bool MMainWindow::reboot()
{
	return ks_actions->exec(Action::Reboot);
}

bool MMainWindow::lockScreen()
{
	return ks_actions->exec(Action::LockScreen, false);
}

bool MMainWindow::logout()
{
	return ks_actions->exec(Action::Logout);
}

void MMainWindow::configure()
{
	if (MSettingsDialog::isActive())
		return;

	new MSettingsDialog(this);
	MSettingsDialog::freeInstance();

	_showMinimizeInfo = true;
}

TQString MMainWindow::getStatusInfo()
{
	return caption();
}

void MMainWindow::makeInvisible() {
	if (MSystemTray::isInstance())
		ks_tray->hide();
	hide();
}

void MMainWindow::makeVisible()
{
	MSystemTray::setMode((MSystemTray::Mode)kshutdownrc->systemTray);
	show();
	WId id = winId();
	KWin::setOnDesktop(id, KWin::currentDesktop());
	KWin::deIconifyWindow(id);
	raise();
}

void MMainWindow::setTestMode(bool yes)
{
	if (ks_actions->testMode() == yes)
		return;

	ks_actions->setTestMode(yes);
	setCaptions(); // add/remove "[ TEST MODE ]" to/from window caption.
	MiscUtils::customMessage(ks_actions->testMode() ? i18n("Test mode enabled") : i18n("Test mode disabled"));
}

TQString MMainWindow::getTimeInfo()
{
	// start time = now
	dt_start.setDate(TQDate::currentDate());
	dt_start.setTime(TQTime::currentTime());
	// end time = start time
	dt_end.setDate(dt_start.date());
	dt_end.setTime(dt_start.time());

	// round down msec
	int ms = dt_end.time().msec();
	if (ms > 0)
		dt_end.setTime(dt_end.time().addMSecs(-ms));

	switch (_delayType)
	{
		case DelayType_Now:
		case DelayType_OnAppExit:
			break;
		case DelayType_TimeFromNow:
			// end time = start time + delay time
			dt_end = dt_end.addSecs(
				(_dateTimeEdit->timeEdit()->time().hour() * 3600) +
				(_dateTimeEdit->timeEdit()->time().minute() * 60)
			);
			break;
		case DelayType_DateTime:
			// end time = selected date/time
			dt_end.setDate(_dateTimeEdit->dateEdit()->date());
			dt_end.setTime(_dateTimeEdit->timeEdit()->time());
			break;
	}

	if (_delayType == DelayType_Now)
		return i18n("No Delay");

	if (_delayType == DelayType_OnAppExit)
		return TQString::null;

	return MiscUtils::formatDateTime(dt_end.addSecs(1));
}

void MMainWindow::initMainMenu()
{
	KMenuBar *mainMenu = menuBar();

	// file
	TDEPopupMenu *pm_file = new TDEPopupMenu(this);
	_statisticsAction->plug(pm_file);
	pm_file->insertSeparator();
	if (MiscUtils::isRestricted("tab_stats"))
		_statisticsAction->setEnabled(false);

// TODO: 2.0: improve kiosk support
	KStdAction::quit(this, TQ_SLOT(slotQuit()), actionCollection())->plug(pm_file);
	mainMenu->insertItem(i18n("&File"), pm_file);

	// actions
	TDEPopupMenu *pm_actions = new TDEPopupMenu(this);
	pm_actions->insertTitle(SmallIcon("messagebox_warning"), i18n("No Delay"));
	_shutDownAction->plug(pm_actions);
	_rebootAction->plug(pm_actions);
	_lockScreenAction->plug(pm_actions);
	_logoutAction->plug(pm_actions);
	pm_actions->insertSeparator();
	_cancelAction->plug(pm_actions);
	mainMenu->insertItem(i18n("&Actions"), pm_actions);

	// settings
	TDEPopupMenu *pm_settings = new TDEPopupMenu(this);
	_checkSystemConfigurationAction->plug(pm_settings);
	pm_settings->insertSeparator();
	pm_settings->insertItem(SmallIcon("configure_shortcuts"), i18n("Configure Global Shortcuts..."), this, TQ_SLOT(slotConfigureGlobalShortcuts()));
	KStdAction::keyBindings(this, TQ_SLOT(slotConfigureShortcuts()), actionCollection())->plug(pm_settings);
	pm_settings->insertSeparator();
	KStdAction::configureNotifications(this, TQ_SLOT(slotConfigureNotifications()), actionCollection())->plug(pm_settings);
	_configureKShutDownAction->plug(pm_settings);
	mainMenu->insertItem(i18n("&Settings"), pm_settings);

	// help
	mainMenu->insertItem(SmallIcon("help"), i18n("&Help"), helpMenu());
}

void MMainWindow::initActions()
{
	// shut down actions

	ac_shutDown = new TDEActionCollection(this, this);

	_lockScreenAction = new TDEAction(
		ks_actions->getName(Action::LockScreen),
		ks_actions->getIcon(Action::LockScreen), TDEShortcut(),
		ks_actions, TQ_SLOT(slotLockScreen()),
		ac_shutDown, "kshutdown_lockscreen"
	);

	_logoutAction = new TDEAction(
		ks_actions->getName(Action::Logout),
		ks_actions->getIcon(Action::Logout), TDEShortcut(),
		ks_actions, TQ_SLOT(slotLogout()),
		ac_shutDown, "kshutdown_logout"
	);

	_rebootAction = new TDEAction(
		ks_actions->getName(Action::Reboot),
		ks_actions->getIcon(Action::Reboot), TDEShortcut(),
		ks_actions, TQ_SLOT(slotReboot()),
		ac_shutDown, "kshutdown_reboot"
	);

	_shutDownAction = new TDEAction(
		ks_actions->getName(Action::ShutDown),
		ks_actions->getIcon(Action::ShutDown), TDEShortcut(),
		ks_actions, TQ_SLOT(slotShutDown()),
		ac_shutDown, "kshutdown_shutdown"
	);

	// standard actions

	_cancelAction = new TDEAction(
		i18n("C&ancel"),
		"cancel", TDEShortcut(Key_Escape),
		this, TQ_SLOT(slotCancel()),
		actionCollection(), "kshutdown_cancelaction"
	);
	_cancelAction->setEnabled(false);

	_checkSystemConfigurationAction = new TDEAction(
		i18n("Check &System Configuration"),
		"button_ok", TDEShortcut(),
		this, TQ_SLOT(slotCheckSystemConfig()),
		actionCollection(), "kshutdown_checksystemconfiguration"
	);

	_configureKShutDownAction = KStdAction::preferences(this, TQ_SLOT(slotConfigureKShutDown()), actionCollection());

	_startAction = new TDEAction(
		i18n("&Start"),
		"button_ok", TDEShortcut(Key_Return),
		this, TQ_SLOT(slotStart()),
		actionCollection(), "kshutdown_startaction"
	);
	MiscUtils::plug(_startAction, b_startStop);

	_statisticsAction = new TDEAction(
		i18n("&Statistics"),
		TDEShortcut(Key_F2),
		this, TQ_SLOT(slotStats()),
		actionCollection(), "kshutdown_statistics"
	);

	actionCollection()->readShortcutSettings();
	ac_shutDown->readShortcutSettings();

	// init global actions/shortcuts
	_globalAccel = new TDEGlobalAccel(this);
	_globalAccel->insert(
		"kshutdown_shutdown",
		ks_actions->getName(Action::ShutDown),
		TQString(),
		0, 0, ks_actions, TQ_SLOT(slotShutDown())
	);
	_globalAccel->insert(
		"kshutdown_reboot",
		ks_actions->getName(Action::Reboot),
		TQString(),
		0, 0, ks_actions, TQ_SLOT(slotReboot())
	);
	_globalAccel->insert(
		"kshutdown_lockscreen",
		ks_actions->getName(Action::LockScreen),
		TQString(),
		0, 0, ks_actions, TQ_SLOT(slotLockScreen())
	);
	_globalAccel->insert(
		"kshutdown_logout",
		ks_actions->getName(Action::Logout),
		TQString(),
		0, 0, ks_actions, TQ_SLOT(slotLogout())
	);
	_globalAccel->readSettings();
	_globalAccel->updateConnections();
}

TQWidget *MMainWindow::initWidgets()
{
	TQWidget *w = new TQWidget(this);
	TQVBoxLayout *l = new TQVBoxLayout(w, 5);

	TQVGroupBox *gb_actions = new TQVGroupBox(i18n("Select an &action to perform"), w);
	gb_actions->setInsideSpacing(0);
	// actions combo box
	cb_actions = new TQComboBox(gb_actions, "TQComboBox::cb_actions");
	cb_actions->setFocusPolicy(StrongFocus);
	cb_actions->insertItem(ks_actions->getIcon(Action::ShutDown), ks_actions->getName(Action::ShutDown));
	cb_actions->insertItem(ks_actions->getIcon(Action::Reboot), ks_actions->getName(Action::Reboot));
	cb_actions->insertItem(ks_actions->getIcon(Action::LockScreen), ks_actions->getName(Action::LockScreen));
	cb_actions->insertItem(ks_actions->getIcon(Action::Logout), ks_actions->getName(Action::Logout));
	cb_actions->insertItem(ks_actions->getIcon(Action::Extras), i18n("Extras"));
	TQWhatsThis::add(cb_actions, i18n("Select an action to perform at the selected time."));
	connect(cb_actions, TQ_SIGNAL(activated(int)), TQ_SLOT(slotActionChange(int)));

	// extras
	ks_extras->createButton(gb_actions);

	TQVGroupBox *gb_delayValues = new TQVGroupBox(i18n("S&elect a time"), w);
	gb_delayValues->setInsideSpacing(0);

	// delay type combo box
	cb_delayTypes = new TQComboBox(gb_delayValues, "TQComboBox::cb_delayTypes");
	cb_delayTypes->setFocusPolicy(StrongFocus);
	cb_delayTypes->insertItem(SmallIcon("messagebox_warning"), i18n("No Delay"));
	cb_delayTypes->insertItem(SmallIcon("clock"), i18n("Time From Now (HH:MM)"));
	cb_delayTypes->insertItem(SmallIcon("date"), i18n("At Date/Time"));
	cb_delayTypes->insertItem(SmallIcon("misc"), i18n("When selected application exit"));
	if (MiscUtils::isRestricted("tab_time"))
		TQWhatsThis::add(cb_delayTypes, i18n("Disabled by the Administrator."));
	else
		TQWhatsThis::add(cb_delayTypes, i18n("Select the type of delay."));
	connect(cb_delayTypes, TQ_SIGNAL(activated(int)), TQ_SLOT(slotDelayTypeChange(int)));

	// date/time edit
	_dateTimeEdit = new TQDateTimeEdit(gb_delayValues, "TQDateTimeEdit::_dateTimeEdit");
	_dateTimeEdit->setAutoAdvance(true);
	_dateTimeEdit->dateEdit()->setMinValue(TQDate::currentDate());
	setDate(TQDate::currentDate());
	connect(_dateTimeEdit, TQ_SIGNAL(valueChanged(const TQDateTime &)), TQ_SLOT(slotUpdateTimeInfo()));

	// app observer/killer
	_appObserver = new AppObserver(gb_delayValues);

	// status line
	l_statusLine = new TQLabel(gb_delayValues);
	TQWhatsThis::add(l_statusLine, i18n("Selected time."));

	l->addWidget(gb_actions);
	l->addWidget(gb_delayValues);
	l->addStretch(5);

	// start/stop action button
	b_startStop = new KPushButton(w, "KPushButton::b_startStop");
	b_startStop->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::Fixed));
	b_startStop->setDefault(true); // enter key
	l->addWidget(b_startStop);

	return w;
}

void MMainWindow::setCaptions(const TQString &remainingTime, const TQString &selectedTime)
{
	// window tool tip
	TQString s;
	if (ks_actions->active())
	{
		if (remainingTime.isNull())
			s = selectedTime + " > " + ks_actions->getCurrentName();
		else
			s = remainingTime + " > " + selectedTime + " - " + ks_actions->getCurrentName();
	}
	if (ks_actions->testMode())
		s += " [" + i18n("TEST MODE") + "]";
	setCaption(s);

	// system tray tool tip
	if (ks_actions->active()) {
		s = "<br>";
		s += i18n("Remaining time: <b>%1</b>").arg(remainingTime.isNull() ? i18n("Unknown") : remainingTime) + "<br>";
		s += i18n("Selected time: <b>%1</b>").arg(selectedTime) + "<br>";
		s += i18n("Selected action: <b>%1</b>").arg(ks_actions->getCurrentName()) + "<br>";
		if (ks_actions->testMode())
		{
			s += "<br>" + i18n("<b>Note: </b> The test mode is enabled") + "<br>";
		}
	}
	else {
		s = "";
	}
	if (MSystemTray::isInstance()) {
		TQToolTip::add(
			ks_tray,
			MiscUtils::HTML("<b>KShutDown</b><br>" + s)
		);
	}
	if (ProgressBar::isInstance()) {
		TQToolTip::add(
			ProgressBar::getInstance(),
			MiscUtils::HTML("<b>KShutDown</b><br>" + s)
		);
	}
}

void MMainWindow::setWidgetsEnabled(const bool yes)
{
	cb_delayTypes->setEnabled(yes);
	_dateTimeEdit->setEnabled(yes);
	cb_actions->setEnabled(yes);
	ks_extras->button()->setEnabled(yes);
	_appObserver->setWidgetsEnabled(yes);

	// actions
	_cancelAction->setEnabled(!yes);
	_startAction->setEnabled(yes);
	if (yes)
		MiscUtils::plug(_startAction, b_startStop);
	else
		MiscUtils::plug(_cancelAction, b_startStop);
}

void MMainWindow::updateTimeInfo(const int secs)
{
	setCaptions(
		MiscUtils::formatDateTime(secs),
		TDEGlobal::locale()->formatDateTime(dt_end, true, true)
	);

	// update progress bar
	if (ProgressBar::isInstance()) {
		ProgressBar *progressBar = ProgressBar::getInstance();
		progressBar->setProgress(secs);
	}
}

void MMainWindow::slotCancel()
{
	cancel();
}

void MMainWindow::slotStart() {
	start(true);
}

void MMainWindow::slotQuit()
{
	ks_actions->setTotalExit(true); // do not hide window in the system tray
	close();
}

void MMainWindow::slotAboutToQuit()
{
	ks_actions->setTotalExit(true);
}

void MMainWindow::slotCheckTime()
{
	// check process
	if (_delayType == DelayType_OnAppExit)
	{
		if (!_appObserver->isSelectedProcessRunning()) {
			// restore window
			makeVisible();
			// show warning message
			if (kshutdownrc->warningMessageEnabled)
			{
				cancel();
				if (MMessageDialog::show(30))
					ks_actions->execCurrent();
			}
			else
			{
				ks_actions->totalExec();
			}
		}

		return;
	}

	// check timeout

	TQDateTime now = TQDateTime::currentDateTime();

	int curSec = now.time().second();

	if (curSec == _oldSec)
		return; // time not changed since last check

	_oldSec = curSec;

	// timeout
	if (now >= dt_end)
	{
		// restore window
		makeVisible();

		ks_actions->totalExec();

		return;
	}

	int secsTo = now.secsTo(dt_end);
	updateTimeInfo(secsTo);

	// show warning message
	if (
		kshutdownrc->warningMessageEnabled &&
		(secsTo <= (kshutdownrc->warningMessageDelay * 60))
	)
	{
		// restore window
		makeVisible();
		// show warning message dialog
		cancel();
		if (MMessageDialog::show(secsTo))
			ks_actions->execCurrent();

		return;
	}

	MiscUtils::notifyUser(secsTo);
}

void MMainWindow::slotDelayTypeChange(int index) {
	setDelayType((DelayType)index);
	slotUpdateTimeInfo();
}

void MMainWindow::slotConfigureGlobalShortcuts() {
	if (KKeyDialog::configure(_globalAccel, false, this)) {
		_globalAccel->writeSettings(0, true);
		_globalAccel->updateConnections();
	}
}

void MMainWindow::slotConfigureKShutDown() {
	configure();
}

void MMainWindow::slotConfigureNotifications() {
	KNotifyDialog::configure(this);
}

void MMainWindow::slotConfigureShortcuts()
{
	KKeyDialog *dialog = new KKeyDialog(false, this);
	dialog->insert(actionCollection());
	dialog->insert(ac_shutDown);
	dialog->configure(true);
	delete dialog;

	actionCollection()->writeShortcutSettings();
	ac_shutDown->writeShortcutSettings();
}

void MMainWindow::slotActionChange(int index)
{
	setAction((Action::Type)(index + 1)); // 0 = What_Nothing
	if (ks_actions->current() != Action::Extras)
		ks_extras->setAction(TQString::null, TQString::null);
}

void MMainWindow::slotCheckSystemConfig()
{
	SystemConfig::check(this);
}

void MMainWindow::slotStats()
{
	if (!MiscUtils::isRestricted("tab_stats"))
		MStatsTab::getInstance()->show();
}

void MMainWindow::slotUpdateTimeInfo()
{
	l_statusLine->setText("<b>" + getTimeInfo() + "</b>");
}

bool MMainWindow::queryClose()
{
	// exit
	if (ks_actions->totalExit() || kapp->sessionSaving())
		return true;

	// MSystemTray::Always
	if (kshutdownrc->systemTray == MSystemTray::Always)
	{
		if (_showMinimizeInfo) {
			MiscUtils::passiveMessage(
				i18n("KShutDown has been minimized"),
				ks_tray
			);
			_showMinimizeInfo = false;
		}
		ks_tray->flashIcon();
		hide();

		return false;
	}

	// MSystemTray::IfActive
	if (kshutdownrc->systemTray == MSystemTray::IfActive)
	{
		if (ks_actions->active())
		{
			if (_showMinimizeInfo) {
				MiscUtils::passiveMessage(
					i18n("KShutDown has been minimized"),
					ks_tray
				);
				_showMinimizeInfo = false;
			}
			ks_tray->flashIcon();
			hide();

			return false;
		}
		else {
// FIXME: 2.0: quit message
			MiscUtils::passiveMessage(i18n("KShutDown has quit"));

			return true;
		}
	}

	// MSystemTray::Never
	if (kshutdownrc->systemTray == MSystemTray::Never) {
// FIXME: 2.0: quit message
		MiscUtils::passiveMessage(i18n("KShutDown has quit"));

		return true;
	}

	return true;
}

bool MMainWindow::queryExit()
{
	ks_actions->setTotalExit(true);

	return true; // ok to exit
}
#include "mmainwindow.moc"
