MythTV  master
mythfrontend/exitprompt.cpp
Go to the documentation of this file.
1 #include "config.h"
2 
3 #include <QCoreApplication>
4 #if CONFIG_QTDBUS
5 #include <QtDBus>
6 #include <QDBusInterface>
7 #endif
8 
9 #include "exitprompt.h"
10 #include "mythcontext.h"
11 #include "mythdialogbox.h"
12 #include "mythmainwindow.h"
13 #include "mythscreenstack.h"
14 #include "mythsystemlegacy.h"
15 #include "mythlogging.h"
16 #include "exitcodes.h"
17 
19 {
20  qApp->exit();
21 }
22 
23 static bool DBusHalt(void)
24 {
25 #if CONFIG_QTDBUS
26  QDBusInterface kde("org.kde.ksmserver",
27  "/KSMServer",
28  "org.kde.KSMServerInterface");
29  QDBusInterface gnome("org.gnome.SessionManager",
30  "/org/gnome/SessionManager",
31  "org.gnome.SessionManager");
32  QDBusInterface consolekit("org.freedesktop.ConsoleKit",
33  "/org/freedesktop/ConsoleKit/Manager",
34  "org.freedesktop.ConsoleKit.Manager",
35  QDBusConnection::systemBus());
36  QDBusInterface logind("org.freedesktop.login1",
37  "/org/freedesktop/login1",
38  "org.freedesktop.login1.Manager",
39  QDBusConnection::systemBus());
40  QDBusInterface hal("org.freedesktop.Hal",
41  "/org/freedesktop/Hal/devices/computer",
42  "org.freedesktop.Hal.Device.SystemPowerManagement",
43  QDBusConnection::systemBus());
44 
45  QDBusReply<void> void_reply = kde.call("logout", 0, 2, 2);
46  QDBusReply<bool> bool_reply;
47  QDBusReply<int> int_reply;
48  QDBusReply<QString> string_reply;
49 
50  if (!void_reply.isValid())
51  {
52  bool_reply = logind.call("CanPowerOff");
53  if (string_reply.isValid() && string_reply.value() == "yes")
54  void_reply = logind.call("PowerOff", false);
55  }
56  if (!void_reply.isValid())
57  {
58  bool_reply = gnome.call("CanShutdown");
59  if (bool_reply.isValid() && bool_reply.value())
60  void_reply = gnome.call("RequestShutdown");
61  }
62  if (!void_reply.isValid())
63  {
64  bool_reply = consolekit.call("CanStop");
65  if (bool_reply.isValid() && bool_reply.value())
66  void_reply = consolekit.call("Stop");
67  }
68  if (!void_reply.isValid())
69  int_reply = hal.call("Shutdown");
70 
71  return void_reply.isValid() || int_reply.isValid();
72 #endif
73  return false;
74 }
75 
77 {
78  QString halt_cmd = gCoreContext->GetSetting("HaltCommand","");
79  int ret = -1;
80 
81  if (!halt_cmd.isEmpty()) /* Use user specified command if it exists */
82  {
83  ret = myth_system(halt_cmd);
84  if (ret != GENERIC_EXIT_OK)
85  LOG(VB_GENERAL, LOG_ERR,
86  "User defined HaltCommand failed, falling back to "
87  "alternative methods.");
88  }
89 
90  /* If supported, use DBus to shutdown */
91  if (ret != GENERIC_EXIT_OK && !DBusHalt())
92  myth_system("sudo /sbin/halt -p");
93 }
94 
95 static bool DBusReboot(void)
96 {
97 #if CONFIG_QTDBUS
98  QDBusInterface kde("org.kde.ksmserver",
99  "/KSMServer",
100  "org.kde.KSMServerInterface");
101  QDBusInterface gnome("org.gnome.SessionManager",
102  "/org/gnome/SessionManager",
103  "org.gnome.SessionManager");
104  QDBusInterface consolekit("org.freedesktop.ConsoleKit",
105  "/org/freedesktop/ConsoleKit/Manager",
106  "org.freedesktop.ConsoleKit.Manager",
107  QDBusConnection::systemBus());
108  QDBusInterface hal("org.freedesktop.Hal",
109  "/org/freedesktop/Hal/devices/computer",
110  "org.freedesktop.Hal.Device.SystemPowerManagement",
111  QDBusConnection::systemBus());
112 
113  QDBusReply<void> void_reply = kde.call("logout", 0, 1, 2);
114  QDBusReply<bool> bool_reply;
115  QDBusReply<int> int_reply;
116 
117  if (!void_reply.isValid())
118  {
119  bool_reply = gnome.call("CanShutdown");
120  if (bool_reply.isValid() && bool_reply.value())
121  void_reply=gnome.call("RequestReboot");
122  }
123  if (!void_reply.isValid())
124  {
125  bool_reply = consolekit.call("CanRestart");
126  if (bool_reply.isValid() && bool_reply.value())
127  void_reply = consolekit.call("Restart");
128  }
129  if (!void_reply.isValid())
130  int_reply = hal.call("Reboot");
131 
132  return void_reply.isValid() || int_reply.isValid();
133 #endif
134  return false;
135 }
136 
138 {
139  QString reboot_cmd = gCoreContext->GetSetting("RebootCommand","");
140  int ret = -1;
141 
142  if (!reboot_cmd.isEmpty()) /* Use user specified command if it exists */
143  {
144  ret = myth_system(reboot_cmd);
145  if (ret != GENERIC_EXIT_OK)
146  LOG(VB_GENERAL, LOG_ERR,
147  "User defined RebootCommand failed, falling back to "
148  "alternative methods.");
149  }
150 
151  /* If supported, use DBus to reboot */
152  if (ret != GENERIC_EXIT_OK && !DBusReboot())
153  myth_system("sudo /sbin/reboot");
154 }
155 
157 {
159 }
160 
162 {
163  // HACK IsFrontendOnly() triggers a popup if there is no BE connection.
164  // We really don't need that right now. This hack prevents it.
166 
167  // first of all find out, if this is a frontend only host...
168  bool frontendOnly = gCoreContext->IsFrontendOnly();
169 
170  // HACK Undo the hack, just in case we _don't_ quit:
172 
173 
174  // how do you want to quit today?
175  bool allowExit = false;
176  bool allowReboot = false;
177  bool allowShutdown = false;
178  bool allowStandby = false;
179 
180  switch (gCoreContext->GetNumSetting("OverrideExitMenu", 0))
181  {
182  case 0:
183  allowExit = true;
184  if (frontendOnly)
185  allowShutdown = true;
186  break;
187  case 1:
188  allowExit = true;
189  break;
190  case 2:
191  allowExit = true;
192  allowShutdown = true;
193  break;
194  case 3:
195  allowExit = true;
196  allowReboot = true;
197  allowShutdown = true;
198  break;
199  case 4:
200  allowShutdown = true;
201  break;
202  case 5:
203  allowReboot = true;
204  break;
205  case 6:
206  allowReboot = true;
207  allowShutdown = true;
208  break;
209  case 7:
210  allowStandby = true;
211  break;
212  }
213 
214  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
215  MythDialogBox *dlg = new MythDialogBox(
216  tr("Do you really want to exit MythTV?"), ss, "exit prompt");
217 
218  if (!dlg->Create())
219  {
220  LOG(VB_GENERAL, LOG_ERR, "Can't create Exit Prompt dialog?");
221  delete dlg;
222  quit();
223  return;
224  }
225 
226  dlg->AddButton(QCoreApplication::translate("(Common)", "No"));
227  if (allowExit)
228  dlg->AddButton(tr("Yes, Exit now"), SLOT(quit()));
229  if (allowReboot)
230  dlg->AddButton(tr("Yes, Exit and Reboot"), SLOT(reboot()));
231  if (allowShutdown)
232  dlg->AddButton(tr("Yes, Exit and Shutdown"), SLOT(halt()));
233  if (allowStandby)
234  dlg->AddButton(tr("Yes, Enter Standby Mode"), SLOT(standby()));
235 
236  // This is a hack so that the button clicks target the correct slot:
237  dlg->SetReturnEvent(this, QString());
238 
239  ss->AddScreen(dlg);
240 }
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
Basic menu dialog, message and a list of options.
MythScreenStack * GetStack(const QString &stackname)
void SetDisableEventPopup(bool check)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:63
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
static bool DBusReboot(void)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
QString GetSetting(const QString &key, const QString &defaultval="")
static bool DBusHalt(void)
uint myth_system(const QString &command, uint flags, uint timeout)
MythMainWindow * GetMythMainWindow(void)
int GetNumSetting(const QString &key, int defaultval=0)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void SetReturnEvent(QObject *retobject, const QString &resultid)
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host
bool Create(void) override