MythTV  0.26-pre
exitprompt.cpp
Go to the documentation of this file.
00001 #include "config.h"
00002 
00003 #include <QCoreApplication>
00004 #if CONFIG_QTDBUS
00005 #include <QtDBus>
00006 #include <QDBusInterface>
00007 #endif
00008 
00009 #include "exitprompt.h"
00010 #include "mythcontext.h"
00011 #include "mythdialogbox.h"
00012 #include "mythmainwindow.h"
00013 #include "mythscreenstack.h"
00014 #include "mythsystem.h"
00015 #include "mythlogging.h"
00016 #include "exitcodes.h"
00017 
00018 void ExitPrompter::quit()
00019 {
00020     qApp->exit();
00021 }
00022 
00023 static bool DBusHalt(void)
00024 {
00025 #if CONFIG_QTDBUS
00026     QDBusInterface kde("org.kde.ksmserver",
00027                        "/KSMServer",
00028                        "org.kde.KSMServerInterface");
00029     QDBusInterface gnome("org.gnome.SessionManager",
00030                          "/org/gnome/SessionManager",
00031                          "org.gnome.SessionManager");
00032     QDBusInterface consolekit("org.freedesktop.ConsoleKit",
00033                               "/org/freedesktop/ConsoleKit/Manager",
00034                               "org.freedesktop.ConsoleKit.Manager",
00035                               QDBusConnection::systemBus());
00036     QDBusInterface hal("org.freedesktop.Hal",
00037                        "/org/freedesktop/Hal/devices/computer",
00038                        "org.freedesktop.Hal.Device.SystemPowerManagement",
00039                        QDBusConnection::systemBus());
00040 
00041     QDBusReply<void> void_reply = kde.call("logout", 0, 2, 2);
00042     QDBusReply<bool> bool_reply;
00043     QDBusReply<int>  int_reply;
00044 
00045     if (!void_reply.isValid())
00046     {
00047         bool_reply = gnome.call("CanShutdown");
00048         if (bool_reply.isValid() && bool_reply.value() == 1)
00049             void_reply = gnome.call("RequestShutdown");
00050     }
00051     if (!void_reply.isValid())
00052     {
00053         bool_reply = consolekit.call("CanStop");
00054         if (bool_reply.isValid() && bool_reply.value() == 1)
00055             void_reply = consolekit.call("Stop");
00056     }
00057     if (!void_reply.isValid())
00058         int_reply = hal.call("Shutdown");
00059 
00060     return void_reply.isValid() || int_reply.isValid();
00061 #endif
00062     return false;
00063 }
00064 
00065 void ExitPrompter::halt()
00066 {
00067     QString halt_cmd = gCoreContext->GetSetting("HaltCommand","");
00068     int ret = -1;
00069 
00070     if (!halt_cmd.isEmpty()) /* Use user specified command if it exists */
00071     {
00072         ret = myth_system(halt_cmd);
00073         if (ret != GENERIC_EXIT_OK)
00074             LOG(VB_GENERAL, LOG_ERR,
00075                 "User defined HaltCommand failed, falling back to "
00076                 "alternative methods.");
00077     }
00078 
00079     /* If supported, use DBus to shutdown */
00080     if (ret != GENERIC_EXIT_OK && !DBusHalt())
00081         myth_system("sudo /sbin/halt -p");
00082 }
00083 
00084 static bool DBusReboot(void)
00085 {
00086 #if CONFIG_QTDBUS
00087     QDBusInterface kde("org.kde.ksmserver",
00088                        "/KSMServer",
00089                        "org.kde.KSMServerInterface");
00090     QDBusInterface gnome("org.gnome.SessionManager",
00091                          "/org/gnome/SessionManager",
00092                          "org.gnome.SessionManager");
00093     QDBusInterface consolekit("org.freedesktop.ConsoleKit",
00094                               "/org/freedesktop/ConsoleKit/Manager",
00095                               "org.freedesktop.ConsoleKit.Manager",
00096                               QDBusConnection::systemBus());
00097     QDBusInterface hal("org.freedesktop.Hal",
00098                        "/org/freedesktop/Hal/devices/computer",
00099                        "org.freedesktop.Hal.Device.SystemPowerManagement",
00100                        QDBusConnection::systemBus());
00101 
00102     QDBusReply<void> void_reply = kde.call("logout", 0, 1, 2);
00103     QDBusReply<bool> bool_reply;
00104     QDBusReply<int>  int_reply;
00105 
00106     if (!void_reply.isValid())
00107     {
00108         bool_reply = gnome.call("CanShutdown");
00109         if (bool_reply.isValid() && bool_reply.value() == 1)
00110             void_reply=gnome.call("RequestReboot");
00111     }
00112     if (!void_reply.isValid())
00113     {
00114         bool_reply = consolekit.call("CanRestart");
00115         if (bool_reply.isValid() && bool_reply.value() == 1)
00116             void_reply = consolekit.call("Restart");
00117     }
00118     if (!void_reply.isValid())
00119         int_reply = hal.call("Reboot");
00120 
00121     return void_reply.isValid() || int_reply.isValid();
00122 #endif
00123     return false;
00124 }
00125 
00126 void ExitPrompter::reboot()
00127 {
00128     QString reboot_cmd = gCoreContext->GetSetting("RebootCommand","");
00129     int ret = -1;
00130 
00131     if (!reboot_cmd.isEmpty()) /* Use user specified command if it exists */
00132     {
00133         ret = myth_system(reboot_cmd);
00134         if (ret != GENERIC_EXIT_OK)
00135             LOG(VB_GENERAL, LOG_ERR,
00136                 "User defined RebootCommand failed, falling back to "
00137                 "alternative methods.");
00138     }
00139 
00140     /* If supported, use DBus to reboot */
00141     if (ret != GENERIC_EXIT_OK && !DBusReboot())
00142         myth_system("sudo /sbin/reboot");
00143 }
00144 
00145 void ExitPrompter::handleExit()
00146 {
00147     // HACK IsFrontendOnly() triggers a popup if there is no BE connection.
00148     // We really don't need that right now. This hack prevents it.
00149     gContext->SetDisableEventPopup(true);
00150 
00151     // first of all find out, if this is a frontend only host...
00152     bool frontendOnly = gCoreContext->IsFrontendOnly();
00153 
00154     // HACK Undo the hack, just in case we _don't_ quit:
00155     gContext->SetDisableEventPopup(false);
00156 
00157 
00158     // how do you want to quit today?
00159     bool allowExit     = false;
00160     bool allowReboot   = false;
00161     bool allowShutdown = false;
00162 
00163     switch (gCoreContext->GetNumSetting("OverrideExitMenu", 0))
00164     {
00165         case 0:
00166             allowExit = true;
00167             if (frontendOnly)
00168                 allowShutdown = true;
00169             break;
00170         case 1:
00171             allowExit = true;
00172             break;
00173         case 2:
00174             allowExit = true;
00175             allowShutdown = true;
00176             break;
00177         case 3:
00178             allowExit     = true;
00179             allowReboot   = true;
00180             allowShutdown = true;
00181             break;
00182         case 4:
00183             allowShutdown = true;
00184             break;
00185         case 5:
00186             allowReboot = true;
00187             break;
00188         case 6:
00189             allowReboot   = true;
00190             allowShutdown = true;
00191             break;
00192     }
00193 
00194     MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
00195     MythDialogBox *dlg = new MythDialogBox(
00196         tr("Do you really want to exit MythTV?"), ss, "exit prompt");
00197 
00198     if (!dlg->Create())
00199     {
00200         LOG(VB_GENERAL, LOG_ERR, "Can't create Exit Prompt dialog?");
00201         delete dlg;
00202         quit();
00203     }
00204 
00205     dlg->AddButton(tr("No"));
00206     if (allowExit)
00207         dlg->AddButton(QObject::tr("Yes, Exit now"),          SLOT(quit()));
00208     if (allowReboot)
00209         dlg->AddButton(QObject::tr("Yes, Exit and Reboot"),   SLOT(reboot()));
00210     if (allowShutdown)
00211         dlg->AddButton(QObject::tr("Yes, Exit and Shutdown"), SLOT(halt()));
00212 
00213     // This is a hack so that the button clicks target the correct slot:
00214     dlg->SetReturnEvent(this, QString());
00215 
00216     ss->AddScreen(dlg);
00217 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends