/*

Shutdown dialog

Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
Copyright (C) 2000-2003,2005 Oswald Buddenhagen <ossi@kde.org>


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

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.

*/

#include "kdmshutdown.h"
#include "kdm_greet.h"
#include "utils.h"


#include <QDialog> //<kdialog.h>
//#include <klocale.h>
#include <QProcess> //<kprocess.h>
#include <QFrame> //<kseparator.h>
//#include <kstandarddirs.h>
//#include <KStandardGuiItem>
#include <myuser.h>

#include <QAction>
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDateTime>
#include <QFrame>
#include <QGroupBox>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QStylePainter>
#include <QStyle>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QMovie> //alex

#include <stdlib.h>

#ifdef WITH_POWER_MANAGEMENT
#include <fly/dbus_iface.h> /*alex*/
#endif

#include <fly/flymisc.h> /*alex*/


int KDMShutdownBase::curPlugin = -1;
PluginList KDMShutdownBase::pluginList;

KDMShutdownBase::KDMShutdownBase(int _uid, QWidget *_parent)
    : inherited(_parent)
    , box(new QVBoxLayout(this))
#ifdef HAVE_VTS
    , willShut(true)
#endif
    , mayNuke(false)
    , doesNuke(false)
    , mayOk(true)
    , maySched(false)
#ifdef WITH_POWER_MANAGEMENT
    , willSuspend( false ) /*alex*/
#endif
    , rootlab(nullptr)
    , verify(nullptr)
    , needRoot(-1)
    , uid(_uid)
{
    okButton=cancelButton=nullptr;
}

KDMShutdownBase::~KDMShutdownBase()
{
    hide();
    if (verify) delete verify;
}

void
KDMShutdownBase::complete(QWidget *prevWidget)
{
    QSizePolicy fp(QSizePolicy::Fixed, QSizePolicy::Fixed);

    if (!isUserInGroup("astra-admin",uid) &&
        ((willShut && _allowShutdown == SHUT_ROOT) ||
#ifdef WITH_POWER_MANAGEMENT
             ( willSuspend && _allowSuspend == SUSP_ROOT ) || /*alex*/
#endif
         (mayNuke && _allowNuke == SHUT_ROOT)))
    {
        //alex: get member of astra-admin group, else - 'root'------------
        QString	adminName;
        int adminNum  = MyUser::groupMemberNum("astra-admin");
        if (adminNum==1) {
            if (adminName.isEmpty()) adminName = MyUser::groupMember("astra-admin", 0); 
            if (adminName.isEmpty()) adminName = MyUser::rootLoginName();
            if (adminName.isEmpty()) adminName="root"; //dummy fallback
        }
        else adminName="";
        //-----------------------------------------------------------------

        rootlab = new QLabel(tr("Root authorization required."), this);
        box->addWidget(rootlab);
        if (curPlugin < 0) {
            curPlugin = 0;
            pluginList = KGVerify::init(_pluginsShutdown);
        }
        verify = new KGStdVerify(this, this,
                                 prevWidget, adminName,
                                 pluginList, KGreeterPlugin::Authenticate,
                                 KGreeterPlugin::Shutdown);
        verify->selectPlugin(curPlugin);
        box->addLayout(verify->getLayout());
        QAction *action = new QAction(this);
        action->setShortcut(Qt::ALT + Qt::Key_A);
        connect(action, SIGNAL(triggered(bool)), SLOT(slotActivatePlugMenu()));
    }
    QFrame *sep=new QFrame(this); sep->setFrameStyle(QFrame::HLine);
    box->addWidget(sep/*new KSeparator( Qt::Horizontal, this)*/);

    QBoxLayout *hlay = new QHBoxLayout();
    box->addLayout(hlay);
    hlay->addStretch(1);
    if (mayOk) {
        okButton = new QPushButton(/*KStandardGuiItem::ok()*/tr("Ok"), this);
        okButton->setSizePolicy(fp);
        okButton->setDefault(true);
        hlay->addWidget(okButton);
        hlay->addStretch(1);
        connect(okButton, SIGNAL(clicked()), SLOT(accept()));
    }
    if (maySched) {
        QPushButton *schedButton =
            new QPushButton(/*KGuiItem( i18nc("@action:inmenu verb",*/tr("&Schedule..."), this);
        schedButton->setSizePolicy(fp);
        hlay->addWidget(schedButton);
        hlay->addStretch(1);
        connect(schedButton, SIGNAL(clicked()), SLOT(slotSched()));
    }
    cancelButton = new QPushButton(/*KStandardGuiItem::cancel()*/tr("Cancel"), this);
    cancelButton->setSizePolicy(fp);
    if (!mayOk)
        cancelButton->setDefault(true);
    hlay->addWidget(cancelButton);
    hlay->addStretch(1);
    connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));

    updateNeedRoot();

    adjustSize();
    layout()->activate();
}

void
KDMShutdownBase::slotActivatePlugMenu()
{
    if (needRoot) {
        QMenu *cmnu = verify->getPlugMenu();
        if (!cmnu)
            return;
        QSize sh(cmnu->sizeHint() / 2);
        cmnu->exec(geometry().center() - QPoint(sh.width(), sh.height()));
    }
}

void
KDMShutdownBase::accept()
{
    if (needRoot == 1) {

        QString userName = verify->getEntity();
        if (!isUserInGroup("astra-admin", userName.toLocal8Bit().data())) {
            QMessageBox::warning(0,tr("Error"),tr("Not astra admin!"));
            verify->reject();
            return;
        }

        verify->accept();
    } else
        accepted();
}

void
KDMShutdownBase::slotSched()
{
    done(Schedule);
}

void
KDMShutdownBase::updateNeedRoot()
{
    int nNeedRoot = !isUserInGroup("astra-admin",uid) &&
        (((willShut && _allowShutdown == SHUT_ROOT) ||
#ifdef WITH_POWER_MANAGEMENT
         ( willSuspend && _allowSuspend == SUSP_ROOT ) || /*alex*/
#endif
          (_allowNuke == SHUT_ROOT && doesNuke)));
    if (verify && nNeedRoot != needRoot) {
        if (needRoot == 1)
            verify->abort();
        needRoot = nNeedRoot;
        rootlab->setEnabled(needRoot);
        verify->setEnabled(needRoot);
        if (needRoot)
            verify->start();
    }
}

void
KDMShutdownBase::accepted()
{
    inherited::done(needRoot ? (int)Authed : (int)Accepted);
}

void
KDMShutdownBase::verifyPluginChanged(int id)
{
    curPlugin = id;
    adjustSize();
}

void
KDMShutdownBase::verifyOk()
{
    accepted();
}

void
KDMShutdownBase::verifyFailed()
{
    okButton->setEnabled(false);
    cancelButton->setEnabled(false);
}

void
KDMShutdownBase::verifyRetry()
{
    okButton->setEnabled(true);
    cancelButton->setEnabled(true);
}

void
KDMShutdownBase::verifySetUser(const QString &)
{
}


static void
doShutdown(int type, const QString &os)
{
    gSet(1);
    gSendInt(G_Shutdown);
    gSendInt(type);
    gSendInt(0);
    gSendInt(0);
    gSendInt(SHUT_FORCE);
    gSendInt(0); /* irrelevant, will timeout immediately anyway */
    gSendStr(os.toUtf8().data());
    gSet(0);
}


static bool
getBootOptions(QStringList *options, int *defaultTarget, int *oldTarget)
{
    bool ret = false;
    gSet(1);
    gSendInt(G_ListBootOpts);
    if (gRecvInt() == BO_OK) {
        *options = qStringList(gRecvStrArr(nullptr));
        *defaultTarget = gRecvInt();
        *oldTarget = gRecvInt();
        ret = true;
    }
    gSet(0);
    return ret;
}

KDMShutdown::KDMShutdown(int _uid, QWidget *_parent)
    : inherited(_uid, _parent)
{
    QSizePolicy fp(QSizePolicy::Fixed, QSizePolicy::Fixed);

    QHBoxLayout *hlay = new QHBoxLayout();
    box->addLayout(hlay);

    howGroup = new QGroupBox(tr("Shutdown Type"), this);
    hlay->addWidget(howGroup, 0, Qt::AlignTop);

    QRadioButton *rb;
    rb = new KDMRadioButton(tr("&Turn off computer"), howGroup);
    rb->setChecked(true);
    rb->setFocus();

    restart_rb = new KDMRadioButton(tr("&Restart computer"), howGroup);

    QBoxLayout *hwlay = new QVBoxLayout(howGroup);
    hwlay->addWidget(rb);
    hwlay->addWidget(restart_rb);
/*alex: double click in radio button?  inevident behaviour!
    connect(rb, SIGNAL(doubleClicked()), SLOT(accept()));
    connect(restart_rb, SIGNAL(doubleClicked()), SLOT(accept()));
*/
    QStringList options;
    int defaultTarget;
    if (getBootOptions(&options, &defaultTarget, &oldTarget)) { /* XXX show dialog on failure */
        targets = new QComboBox();
        targets->addItems(options);
        targets->setCurrentIndex(oldTarget == -1 ? defaultTarget : oldTarget);
        QHBoxLayout *hb = new QHBoxLayout();
        hwlay->addLayout(hb);
        hb->addSpacing(
            style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)
            + hb->spacing());
        hb->addWidget(targets);
        connect(targets, SIGNAL(activated(int)), SLOT(slotTargetChanged()));
    }

    howGroup->setSizePolicy(fp);

    schedGroup = new QGroupBox(/*i18nc("@title:group ... of shutdown",*/tr("Scheduling"), this);
    hlay->addWidget(schedGroup, 0, Qt::AlignTop);

    le_start = new QLineEdit(schedGroup);
	le_start->setToolTip(tr("When start to try shutdown:\n"
	"date string, keyword <b>now</b> or <b>+n</b> seconds after now"));
    QLabel *lab1 = new QLabel(tr("&Start:"), schedGroup);
    lab1->setBuddy(le_start);

    le_timeout = new QLineEdit(schedGroup);
	le_timeout->setToolTip(tr("When stop to try shutdown:\n"
	"date string, keyword <b>inf</b> or <b>+n</b> seconds after start"));
    QLabel *lab2 = new QLabel(tr("T&imeout:"), schedGroup);
    lab2->setBuddy(le_timeout);

    cb_force = new QCheckBox(tr("&Force after timeout"), schedGroup);
    if (_allowNuke != SHUT_NONE) {
        //connect(cb_force, SIGNAL(clicked()), SLOT(slotWhenChanged()));
        connect(cb_force, SIGNAL(stateChanged(int)), SLOT(slotWhenChanged()));
        mayNuke = true;
    } else {
        cb_force->setEnabled(false);
    }

    QGridLayout *grid = new QGridLayout(schedGroup);
    grid->addWidget(lab1, 0, 0, Qt::AlignRight);
    grid->addWidget(le_start, 0, 1);
    grid->addWidget(lab2, 1, 0, Qt::AlignRight);
    grid->addWidget(le_timeout, 1, 1);
    grid->addWidget(cb_force, 2, 0, 1, 2);

    schedGroup->setSizePolicy(fp);

    le_start->setText("0");
    if (_defSdMode == SHUT_SCHEDULE) {
        le_timeout->setText("-1");
    } else {
        le_timeout->setText("0");
        if (_defSdMode == SHUT_FORCENOW && cb_force->isEnabled())
            cb_force->setChecked(true);
    }

    complete(schedGroup);
}

static int
getDate(const char *str)
{
/*  KProcess prc;
    prc.setOutputChannelMode(KProcess::OnlyStdoutChannel);
    prc << "/bin/date" << "+%s" << "-d" << str;
    if (prc.execute())
        return -1;*/
	//alex: ------------
    QStringList pra; pra << "+%s" << "-d" << QString::fromUtf8(str);
	QProcess prc;
	prc.setReadChannel(QProcess::StandardOutput);
	prc.start("/bin/date",pra,QIODevice::ReadOnly);
    if (!prc.waitForFinished(5000) || 
		 prc.exitStatus()!=QProcess::NormalExit) return -1;
	//------------------
    return prc.readAll().simplified().toInt();
}

void
KDMShutdown::accept()
{
    if (le_start->text() == "0" || le_start->text() == "now") {
        sch_st = time(nullptr);
    } else if (le_start->text()[0] == '+') {
        sch_st = time(nullptr) + le_start->text().toInt();
    } else if ((sch_st = getDate(le_start->text().toLatin1())) < 0) {
        KFMsgBox::box(this, errorbox, tr("Entered start date is invalid."));
        le_start->setFocus();
        return;
    }
    if (le_timeout->text() == "-1" || le_timeout->text().startsWith("inf")) {
        sch_to = TO_INF;
    } else if (le_timeout->text()[0] == '+') {
        sch_to = sch_st + le_timeout->text().toInt();
    } else if ((sch_to = getDate(le_timeout->text().toLatin1())) < 0) {
        KFMsgBox::box(this, errorbox, tr("Entered timeout date is invalid."));
        le_timeout->setFocus();
        return;
    }
    if (!inherited::isNeedRoot()) //alex
    {
        QList<DpySpec> sess = fetchSessions(lstRemote | lstTTY);
        if (!sess.isEmpty() || _allowNuke == SHUT_ROOT)
        {
            foreach (const DpySpec &session, sess) 
            {
                if (!(session.flags & isSelf))
                {
                    KFMsgBox::box(this, sorrybox, tr("Can't stop active sessions without admin password!"));
                    if (cb_force && cb_force->isEnabled())
                    {
                        cb_force->setChecked(1);
                        return;
                    }
                }
            }
        }
    }
    inherited::accept();
}

void
KDMShutdown::slotTargetChanged()
{
    restart_rb->setChecked(true);
}

void
KDMShutdown::slotWhenChanged()
{
    doesNuke = cb_force->isChecked();
    updateNeedRoot();
}

void
KDMShutdown::accepted()
{
    gSet(1);
    gSendInt(G_Shutdown);
    gSendInt(restart_rb->isChecked() ? SHUT_REBOOT : SHUT_HALT);
    gSendInt(sch_st);
    gSendInt(sch_to);
    gSendInt(cb_force->isChecked() ? SHUT_FORCE : SHUT_CANCEL);
    gSendInt(_allowShutdown == SHUT_ROOT ? 0 : -2);
    gSendStr((restart_rb->isChecked() &&
              targets && targets->currentIndex() != oldTarget) ?
             targets->currentText().toLocal8Bit().data() : nullptr);
    gSet(0);
    inherited::accepted();
}

void
KDMShutdown::scheduleShutdown(QWidget *_parent)
{
    gSet(1);
    gSendInt(G_QueryShutdown);
    int how = gRecvInt();
    int start = gRecvInt();
    int timeout = gRecvInt();
    int force = gRecvInt();
    int uid = gRecvInt();
    char *os = gRecvStr();
    gSet(0);
    if (how) {
        int ret =
            KDMCancelShutdown(how, start, timeout, force, uid, QString::fromUtf8(os),
                              _parent).exec();
        if (!ret)
            return;
        doShutdown(0, QString());
        uid = ret == Authed ? 0 : -1;
    } else {
        uid = -1;
    }
    if (os) free(os); //alex
    KDMShutdown(uid, _parent).exec();
}


KDMRadioButton::KDMRadioButton(const QString &label, QWidget *parent)
    : inherited(label, parent)
{
}

void
KDMRadioButton::mouseDoubleClickEvent(QMouseEvent *)
{
    emit doubleClicked();
}


KDMDelayedPushButton::KDMDelayedPushButton(const /*KGuiItem*/QString &item, QWidget *parent)
    : inherited(item, parent)
{
    popt.setSingleShot(true);
    popt.setInterval(0/*style()->styleHint(QStyle::SH_ToolButton_PopupDelay, 0, this)*/);
}

void KDMDelayedPushButton::setDelayedMenu(QMenu *p)
{
    setMenu(p);
    disconnect(this, nullptr, this, nullptr); // Internal button -> popup connection
    if (p) {
        connect(this, SIGNAL(pressed()), &popt, SLOT(start()));
        connect(this, SIGNAL(released()), &popt, SLOT(stop()));
        connect(&popt, SIGNAL(timeout()), SLOT(showMenu()));
    }
}

KDMSlimShutdown::KDMSlimShutdown(QWidget *_parent)
    : inherited(_parent)
{
    bool flatStyle = _theme.contains("flat");

    QHBoxLayout *hbox = new QHBoxLayout(this);

    QFrame *lfrm = new QFrame(this);
    hbox->addWidget(lfrm, Qt::AlignCenter);

    QLabel *icon = new QLabel(lfrm);
    QMovie * mv = nullptr;

    if (flatStyle) icon->setPixmap(QIcon::fromTheme("system-shutdown").pixmap(QSize(128, 128)));
    else {
        //icon->setPixmap(QPixmap(KStandardDirs::locate("data", "kdm/pics/shutdown.png")));
        // alex: do so --------
        mv = new QMovie(this);
        mv->setFileName(KDMDATA"/pics/shutdown.gif");
        if (mv->isValid()) {
            icon->setMovie(mv); mv->start();
        }
        else {
            delete mv; mv=nullptr;
            icon->setPixmap(QPixmap(KDMDATA"/pics/shutdown.png"));
        }
        //---------------
    }
    icon->setFixedSize(icon->sizeHint());
    lfrm->setFixedSize(icon->sizeHint());

    QVBoxLayout *buttonlay = new QVBoxLayout();
    hbox->addLayout(buttonlay);

    buttonlay->addStretch(1);

    FlyAnimPushButton *btnHalt = new FlyAnimPushButton(/*KGuiItem(*/tr("&Turn Off Computer")/*, "system-shutdown")*/, this);
    buttonlay->addWidget(btnHalt);
    connect(btnHalt, SIGNAL(clicked()), SLOT(slotHalt()));

    //buttonlay->addSpacing(KDialog::spacingHint());

    KDMDelayedPushButton *btnReboot = new KDMDelayedPushButton(/*KGuiItem(*/tr("&Restart Computer")/*, "system-reboot")*/, this);
    buttonlay->addWidget(btnReboot);
    connect(btnReboot, SIGNAL(clicked()), SLOT(slotReboot()));

#ifdef WITH_POWER_MANAGEMENT /*alex--------------*/
    standby    = suspend_ram    = suspend_disk    = false;
    qa_standby = qa_suspend_ram = qa_suspend_disk = nullptr;
    //if (zamokIsPlugged()) _allowSuspend = SUSP_NONE; //disable power saving with zamok? - OK
    if ( _allowSuspend != SUSP_NONE )
    {
        int supported = -1;
        if ((supported=dbus_Logind_CanSuspend())>=0)     standby     =(supported==0?0:1);
        if ((supported=dbus_Logind_CanHybridSleep())>=0) suspend_ram =(supported==0?0:1);
        if ((supported=dbus_Logind_CanHibernate())>=0)   suspend_disk=(supported==0?0:1);

        int sum = standby + suspend_ram + suspend_disk;
        if ( sum )
        {
            buttonlay->addSpacing( 5/*KDialog::spacingHint()*/ );

            FlyAnimPushButton *btnSuspend;
            if (sum > 1)
            {
                btnSuspend = new KDMDelayedPushButton(/*KGuiItem(*/tr("&Suspend Computer")/*, "media-playback-pause")*/, this);
                QMenu *suspends = new QMenu(this);
                if (standby)      qa_standby     = suspends->addAction(tr("Standby"));
                if (suspend_ram)  qa_suspend_ram = suspends->addAction(tr("Suspend to RAM"));
                if (suspend_disk) qa_suspend_disk= suspends->addAction(tr("Suspend to Disk"));

                connect(suspends, SIGNAL(triggered( QAction* )), SLOT(slotSuspend(QAction*)));
                static_cast<KDMDelayedPushButton*>(btnSuspend)->setDelayedMenu(suspends);
            }
            else
            {
                btnSuspend = new FlyAnimPushButton(/*KGuiItem(*/tr("&Suspend Computer")/*, "media-playback-pause")*/, this);
            }
            buttonlay->addWidget( btnSuspend );
            connect(btnSuspend, SIGNAL(clicked()), SLOT(slotSuspend()));

            if (flatStyle) {
                QIcon suspIcon = QIcon::fromTheme("system-suspend");
                btnSuspend->setIcon(suspIcon);
            }
            else {
                QPixmap *suspPix = new QPixmap(KDMDATA"/pics/suspend.png");
                if (!suspPix->isNull()) btnSuspend->setAnimationInfo(icon,-1,suspPix);
            }
        }
    }
#endif //------------------------
    int dummy, cur;
    if (getBootOptions(&targetList, &dummy, &cur)) {
        QMenu *targets = new QMenu(this);
        for (int i = 0; i < targetList.size(); i++)
            (targets->addAction(i == cur ?
                                /*i18nc( "current option in boot loader",*/
                                      tr("%1 (current)").arg(targetList[i]) :
                                targetList[i]))->setData(i);
        btnReboot->setDelayedMenu(targets);
        connect(targets, SIGNAL(triggered(QAction*)),
                SLOT(slotReboot(QAction*)));
    }

    buttonlay->addStretch(1);

    if (_scheduledSd != SHUT_NEVER) {
        FlyAnimPushButton *btnSched = new
        FlyAnimPushButton(/*KGuiItem(i18nc("@action:button verb",*/tr("&Schedule..."), this);
        buttonlay->addWidget(btnSched);
        connect(btnSched, SIGNAL(clicked()), SLOT(slotSched()));

        buttonlay->addStretch(1);
		//alex:
        if (flatStyle) {
            QIcon schedIcon = QIcon::fromTheme("clock"); 
            btnSched->setIcon(schedIcon);
        }
        else {
            QPixmap *shedPix = new QPixmap(KDMDATA"/pics/shedule.png");
            if (!shedPix->isNull())	btnSched->setAnimationInfo(icon,-1,shedPix);
        }
	}

	QFrame *sep=new QFrame(this); sep->setFrameStyle(QFrame::HLine);
    buttonlay->addWidget(sep/*new KSeparator(this)*/);

    buttonlay->addSpacing(0);

    QPushButton *btnBack = new QPushButton(/*KStandardGuiItem::cancel()*/tr("Cancel"), this);
    buttonlay->addWidget(btnBack);
    connect(btnBack, SIGNAL(clicked()), SLOT(reject()));

    //buttonlay->addSpacing(KDialog::spacingHint());
	//alex:
    if (flatStyle) {
        QIcon haltIcon = QIcon::fromTheme("system-shutdown");
        QIcon rebootIcon = QIcon::fromTheme("system-reboot");
        btnHalt->setIcon(haltIcon);
        btnReboot->setIcon(rebootIcon);
    }
    else {
        QPixmap *haltPix   = new QPixmap(KDMDATA"/pics/halt.png");
        QPixmap *rebootPix = new QPixmap(KDMDATA"/pics/reboot.png");
        if (!haltPix->isNull())	 btnHalt->setAnimationInfo(icon,-1,haltPix);
        if (!rebootPix->isNull())btnReboot->setAnimationInfo(icon,-1,rebootPix);
    }
    btnBack->setFocus();
}

void
KDMSlimShutdown::slotSched()
{
    reject();
    KDMShutdown::scheduleShutdown();
}

void
KDMSlimShutdown::slotHalt()
{
    if (checkShutdown(SHUT_HALT, QString()))
        doShutdown(SHUT_HALT, QString());
}

void
KDMSlimShutdown::slotReboot()
{
    if (checkShutdown(SHUT_REBOOT, QString()))
        doShutdown(SHUT_REBOOT, QString());
}

void
KDMSlimShutdown::slotReboot(QAction *action)
{
    int opt = action->data().toInt();
    if (checkShutdown(SHUT_REBOOT, targetList[opt]))
        doShutdown(SHUT_REBOOT, targetList[opt]);
}

bool
KDMSlimShutdown::checkShutdown(int type, const QString &os)
{
    reject();
    QList<DpySpec> sess = fetchSessions(lstRemote | lstTTY);
    if (sess.isEmpty() && _allowShutdown != SHUT_ROOT)
        return true;
    int ret = KDMConfShutdown(-1, sess, type, os).exec();
    if (ret == Schedule) {
        KDMShutdown::scheduleShutdown();
        return false;
    }
    return ret;
}

void
KDMSlimShutdown::externShutdown(int type, const QString &os, int uid, bool ask)
{
    QList<DpySpec> sess = fetchSessions(lstRemote | lstTTY);

    /*alex: check different users ot the same?
    bool diff_users=false;
    for (int i=0;i<sess.count();i++)
    {
       QString user = sess[i].user;
       for (int j=0;i<sess.count();j++)
       {
          if (i!=j && sess[i].user!=sess[j].user) { diff_users=true; break; }
       }
       if (diff_users) break;
    }*/

    if (ask || !sess.isEmpty() || (!isUserInGroup("astra-admin",uid) && _allowShutdown == SHUT_ROOT)) {
        int ret = KDMConfShutdown(uid, sess, type, os).exec();
        if (ret == Schedule) {
            KDMShutdown(uid).exec();
            return;
        } else if (!ret) {
            return;
        }
    }
    doShutdown(type, os);
}
/*
#define SHUT_CONSOLE_HELP QT_TR_NOOP(\
    "<br/>Switching to console mode will terminate all local X servers and" \
    " leave you with console logins only. Graphical mode is automatically" \
    " resumed 10 seconds after the last console session ends or after" \
    " 40 seconds if no-one logs in in the first place.<br/>")
- alex: moved down*/
KDMConfShutdown::KDMConfShutdown(int _uid, const QList<DpySpec> &sessions, int type,
                                 const QString &os, QWidget *_parent)
    : inherited(_uid, _parent)
{
#ifdef HAVE_VTS
    if (type == SHUT_CONSOLE)
        willShut = false;
#endif
#ifdef WITH_POWER_MANAGEMENT /*alex*/
    QString title;
    if ( type == SHUT_HALT) title = tr("Turn Off Computer");
    else {
#ifdef HAVE_VTS
            if ( type == SHUT_CONSOLE) title = tr("Switch to Console");
            else
#endif
                if ( type == SHUT_SUSPEND ) {
                     willSuspend = true;
                     title = tr("Suspend Computer");
                }
                else title = tr("Restart Computer");
    }
#endif
    QLabel *lbl = new QLabel(QString("<qt><center><b><nobr>"
                                     "%1%2"
                                     "</nobr></b></center>"
#ifdef HAVE_VTS
                                     "%3"
#endif
                                     "</qt>")
#ifdef WITH_POWER_MANAGEMENT /*alex*/
                             .arg(title)
#else
                             .arg((type == SHUT_HALT) ?
                                      tr("Turn Off Computer") :
#ifdef HAVE_VTS
                                      (type == SHUT_CONSOLE) ?
                                      tr("Switch to Console") :
#endif
                                      tr("Restart Computer"))
#endif
                             .arg(!os.isEmpty() ?
                                      tr("<br/>(Next boot: %1)").arg(os) :
                                      QString())
#ifdef HAVE_VTS
                             .arg((type == SHUT_CONSOLE) ?
                                      tr(/*SHUT_CONSOLE_HELP*/
    "<br/>Switching to console mode will terminate all local X servers and"
    " leave you with console logins only. Graphical mode is automatically"
    " resumed 10 seconds after the last console session ends or after"
    " 40 seconds if no-one logs in in the first place.<br/>") :
                                      QString())
#endif
                             ,this);
    lbl->setWordWrap(true);
    box->addWidget(lbl);

    if (!sessions.isEmpty()) {
        if (willShut && _scheduledSd != SHUT_NEVER)
            maySched = true;
        mayNuke = doesNuke = true;
        if (_allowNuke == SHUT_NONE)
            mayOk = false;
        QLabel *lab = new QLabel(mayOk ?
                                 tr("Abort active sessions:") :
                                 tr("No permission to abort active sessions:"),
                                 this);
        box->addWidget(lab);
        QTreeWidget *lv = new QTreeWidget(this);
        lv->setRootIsDecorated(false);
        lv->setSelectionMode(QAbstractItemView::NoSelection);
        lv->setAllColumnsShowFocus(true);
        lv->setUniformRowHeights(true);
        lv->setEditTriggers(QAbstractItemView::NoEditTriggers);
        lv->setColumnCount(2);
        lv->setHeaderLabels(QStringList()
            << /*i18nc("@title:column",*/tr("Session")
            << /*i18nc("@title:column ... of session",*/tr("Location"));
        int ns = 0;
        QString user, loc;
        foreach (const DpySpec &sess, sessions) {
            decodeSession(sess, user, loc);
            new QTreeWidgetItem(lv, QStringList() << user << loc);
            ns++;
        }
        int fw = lv->frameWidth() * 2;
        int hh = lv->header()->sizeHint().height();
        int ih = lv->itemDelegate()->sizeHint(
                QStyleOptionViewItem(), lv->model()->index(0, 0)).height();
        lv->setFixedHeight(fw + hh + ih * (ns < 3 ? 3 : ns > 10 ? 10 : ns));
        box->addWidget(lv);
        complete(lv);
        int cw[2];
        for (int i = 0; i < 2; i++)
            cw[i] = qMax(static_cast<QAbstractItemView *>(lv)->sizeHintForColumn(i),
                         lv->header()->sectionSizeHint(i));
        int w = lv->maximumViewportSize().width(), w2 = w / 2;
        int m = (w < cw[0] + cw[1]) ?
                    (cw[0] + (w - cw[1])) / 2 :
                    (cw[0] > w2) ? cw[0] : (cw[1] > w2) ? (w - cw[1]) : w2;
        lv->header()->resizeSection(0, m);
    } else {
        complete(nullptr);
    }
}


KDMCancelShutdown::KDMCancelShutdown(int how, int start, int timeout,
                                     int force, int uid, const QString &os,
                                     QWidget *_parent)
    : inherited(-1, _parent)
{
    if (force == SHUT_FORCE) {
        if (_allowNuke == SHUT_NONE)
            mayOk = false;
        else if (_allowNuke == SHUT_ROOT)
            mayNuke = doesNuke = true;
    }
    QLabel *lab = new QLabel(mayOk ?
                                 tr("Abort pending shutdown:") :
                                 tr("No permission to abort pending shutdown:"),
                             this);
    box->addWidget(lab);
    QDateTime qdt;
    QString strt, end;
    if (start < time(nullptr)) {
        strt = /*i18nc("start of shutdown:",*/tr("now");
    } else {
        qdt.setTime_t(start);
        strt = qdt.toString(Qt::LocalDate);
    }
    if (timeout == TO_INF) {
        end = /*i18nc("timeout of shutdown:",*/tr("infinite");
    } else {
        qdt.setTime_t(timeout);
        end = qdt.toString(Qt::LocalDate);
    }
/*    QString trg =
        i18n("Owner: %1"
             "\nType: %2%5"
             "\nStart: %3"
             "\nTimeout: %4",
          uid == -2 ?
              i18nc("owner of shutdown:", "console user") :
              uid == -1 ?
              i18nc("owner of shutdown:", "control socket") :
              KUser(uid).loginName() ,
          how == SHUT_HALT ?
              i18n("turn off computer") :
              i18n("restart computer") ,
          strt, end ,
          !os.isEmpty() ?
              i18n("\nNext boot: %1", os) :
              QString());
	alex: keep it simple:*/
	QString trg = tr("Owner: ")+ 
         (uid == -2 ? tr("console user") : 
		 (uid == -1 ? tr("control socket") : MyUser::loginName(uid)));
	trg += 	tr("\nType: ")+
		 (how == SHUT_HALT ? tr("turn off computer") : tr("restart computer"));
	trg += (!os.isEmpty()? tr("\nNext boot: %1").arg( os ) : QString());
    trg += tr("\nStart: ")+strt;
	trg += tr("\nTimeout: ")+end;

    if (timeout != TO_INF)
        trg += tr("\nAfter timeout: %1").arg( 
                 (force == SHUT_FORCE ?
                     tr("abort all sessions") :
                     (force == SHUT_FORCEMY ?
                     tr("abort own sessions") :
                     tr("cancel shutdown"))));
    lab = new QLabel(trg, this);
    box->addWidget(lab);
    complete(nullptr);
}

//alex: my stuff
FlyAnimPushButton::FlyAnimPushButton( const QString &item, QWidget *parent ) //alex
	: inherited( item, parent )
{ 
	masterLabel=nullptr;
	animFrame=-1;
	savedMovie=nullptr;
	animPixmap=nullptr;
}
void FlyAnimPushButton::setAnimationInfo( QLabel *mLabel, int aFrame, QPixmap *pm ) 
{ 
	masterLabel=mLabel; animFrame=aFrame; animPixmap=pm;
}
void FlyAnimPushButton::startOwnAnimation()
{
	if (masterLabel && masterLabel->movie() && (animFrame>=0 || animPixmap)) 
	{
		if (animFrame>=0)
		{
			masterLabel->movie()->jumpToFrame(animFrame); 
			masterLabel->movie()->setPaused(true);
		}
		else if (animPixmap) 
		{
			savedMovie=masterLabel->movie();
			masterLabel->setPixmap(*animPixmap);
		}
	}
}
void FlyAnimPushButton::stopOwnAnimation()
{
	if (masterLabel && savedMovie) 
	{	
		masterLabel->setMovie(savedMovie);
		if (animFrame>=0) masterLabel->movie()->setPaused(false);
		else			  masterLabel->movie()->start();
	}
}
void FlyAnimPushButton::focusInEvent(QFocusEvent *e)  { startOwnAnimation(); inherited::focusInEvent(e); }
void FlyAnimPushButton::focusOutEvent(QFocusEvent *e) { stopOwnAnimation();  inherited::focusOutEvent(e); }
void FlyAnimPushButton::enterEvent(QEvent *e) 		  { startOwnAnimation(); inherited::enterEvent(e); }
void FlyAnimPushButton::leaveEvent(QEvent *e) 		  { stopOwnAnimation();  inherited::leaveEvent(e);}

#ifdef WITH_POWER_MANAGEMENT /*alex: ----------------*/
void KDMSlimShutdown::slotSuspend()
{
       if (suspend_disk)slotSuspend( qa_suspend_disk );
  else if (suspend_ram) slotSuspend( qa_suspend_ram );
  else if (standby)     slotSuspend( qa_standby );
  else reject();
}

void KDMSlimShutdown::slotSuspend(QAction * id)
{
  reject();
  QList<DpySpec> sess = fetchSessions( lstRemote | lstTTY );

  if (!sess.isEmpty() || _allowSuspend == SUSP_ROOT)
  {
      int ret = KDMConfShutdown( -1, sess, SHUT_SUSPEND, QString() ).exec();
      if ( !ret ) return;
  }

  char *err=nullptr;
       if (standby      && id == qa_standby )     err=dbus_Logind_Suspend();
  else if (suspend_ram  && id == qa_suspend_ram)  err=dbus_Logind_HybridSleep();
  else if (suspend_disk && id == qa_suspend_disk) err=dbus_Logind_Hibernate();
  if (err) free(err);

  return;
}
#endif /*alex----------------*/

//#include "kdmshutdown.moc"
