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 #else
73  return false;
74 #endif
75 }
76 
78 {
79  confirm(HALT);
80 }
81 
82 void ExitPrompter::halt(bool Confirmed)
83 {
84  if (!Confirmed)
85  return;
86 
87  QString halt_cmd = gCoreContext->GetSetting("HaltCommand","");
88  int ret = -1;
89 
90  if (!halt_cmd.isEmpty()) /* Use user specified command if it exists */
91  {
92  ret = myth_system(halt_cmd);
93  if (ret != GENERIC_EXIT_OK)
94  LOG(VB_GENERAL, LOG_ERR,
95  "User defined HaltCommand failed, falling back to "
96  "alternative methods.");
97  }
98 
99  /* If supported, use DBus to shutdown */
100  if (ret != GENERIC_EXIT_OK && !DBusHalt())
101  myth_system("sudo /sbin/halt -p");
102 }
103 
104 static bool DBusReboot(void)
105 {
106 #if CONFIG_QTDBUS
107  QDBusInterface kde("org.kde.ksmserver",
108  "/KSMServer",
109  "org.kde.KSMServerInterface");
110  QDBusInterface gnome("org.gnome.SessionManager",
111  "/org/gnome/SessionManager",
112  "org.gnome.SessionManager");
113  QDBusInterface consolekit("org.freedesktop.ConsoleKit",
114  "/org/freedesktop/ConsoleKit/Manager",
115  "org.freedesktop.ConsoleKit.Manager",
116  QDBusConnection::systemBus());
117  QDBusInterface hal("org.freedesktop.Hal",
118  "/org/freedesktop/Hal/devices/computer",
119  "org.freedesktop.Hal.Device.SystemPowerManagement",
120  QDBusConnection::systemBus());
121 
122  QDBusReply<void> void_reply = kde.call("logout", 0, 1, 2);
123  QDBusReply<bool> bool_reply;
124  QDBusReply<int> int_reply;
125 
126  if (!void_reply.isValid())
127  {
128  bool_reply = gnome.call("CanShutdown");
129  if (bool_reply.isValid() && bool_reply.value())
130  void_reply=gnome.call("RequestReboot");
131  }
132  if (!void_reply.isValid())
133  {
134  bool_reply = consolekit.call("CanRestart");
135  if (bool_reply.isValid() && bool_reply.value())
136  void_reply = consolekit.call("Restart");
137  }
138  if (!void_reply.isValid())
139  int_reply = hal.call("Reboot");
140 
141  return void_reply.isValid() || int_reply.isValid();
142 #else
143  return false;
144 #endif
145 }
146 
148 {
149  confirm(REBOOT);
150 }
151 
152 void ExitPrompter::reboot(bool Confirmed)
153 {
154  if (!Confirmed)
155  return;
156 
157  QString reboot_cmd = gCoreContext->GetSetting("RebootCommand","");
158  int ret = -1;
159 
160  if (!reboot_cmd.isEmpty()) /* Use user specified command if it exists */
161  {
162  ret = myth_system(reboot_cmd);
163  if (ret != GENERIC_EXIT_OK)
164  LOG(VB_GENERAL, LOG_ERR,
165  "User defined RebootCommand failed, falling back to "
166  "alternative methods.");
167  }
168 
169  /* If supported, use DBus to reboot */
170  if (ret != GENERIC_EXIT_OK && !DBusReboot())
171  myth_system("sudo /sbin/reboot");
172 }
173 
175 {
177 }
178 
180 {
181  // HACK IsFrontendOnly() triggers a popup if there is no BE connection.
182  // We really don't need that right now. This hack prevents it.
184 
185  // first of all find out, if this is a frontend only host...
186  bool frontendOnly = gCoreContext->IsFrontendOnly();
187 
188  // HACK Undo the hack, just in case we _don't_ quit:
190 
191 
192  // how do you want to quit today?
193  bool allowExit = false;
194  bool allowReboot = false;
195  bool allowShutdown = false;
196  bool allowStandby = false;
197 
198  switch (gCoreContext->GetNumSetting("OverrideExitMenu", 0))
199  {
200  case 0:
201  allowExit = true;
202  if (frontendOnly)
203  allowShutdown = true;
204  break;
205  case 1:
206  allowExit = true;
207  break;
208  case 2:
209  allowExit = true;
210  allowShutdown = true;
211  break;
212  case 3:
213  allowExit = true;
214  allowReboot = true;
215  allowShutdown = true;
216  break;
217  case 4:
218  allowShutdown = true;
219  break;
220  case 5:
221  allowReboot = true;
222  break;
223  case 6:
224  allowReboot = true;
225  allowShutdown = true;
226  break;
227  case 7:
228  allowStandby = true;
229  break;
230  }
231 
232  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
233  auto *dlg = new MythDialogBox(tr("Do you really want to exit MythTV?"), ss,
234  "exit prompt");
235 
236  if (!dlg->Create())
237  {
238  LOG(VB_GENERAL, LOG_ERR, "Can't create Exit Prompt dialog?");
239  delete dlg;
240  quit();
241  return;
242  }
243 
244  dlg->AddButton(QCoreApplication::translate("(Common)", "No"));
245  if (allowExit)
246  dlg->AddButton(tr("Yes, Exit now"), SLOT(quit()));
247  if (allowReboot)
248  {
249  dlg->AddButton(tr("Yes, Exit and Reboot"),
250  frontendOnly ? SLOT(reboot()) : SLOT(confirmReboot()));
251  }
252  if (allowShutdown)
253  {
254  dlg->AddButton(tr("Yes, Exit and Shutdown"),
255  frontendOnly ? SLOT(halt()) : SLOT(confirmHalt()));
256  }
257  if (allowStandby)
258  dlg->AddButton(tr("Yes, Enter Standby Mode"), SLOT(standby()));
259 
260  // This is a hack so that the button clicks target the correct slot:
261  dlg->SetReturnEvent(this, QString());
262 
263  ss->AddScreen(dlg);
264 }
265 
267 {
268  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
269  auto *dlg = new MythConfirmationDialog(ss,
270  tr("Mythbackend is running on this system. Are you sure you want to continue?"));
271 
272  if (!dlg->Create())
273  {
274  delete dlg;
275  quit();
276  return;
277  }
278 
279  if (Action == HALT)
280  connect(dlg, SIGNAL(haveResult(bool)), SLOT(halt(bool)));
281  else if (Action == REBOOT)
282  connect(dlg, SIGNAL(haveResult(bool)), SLOT(reboot(bool)));
283 
284  ss->AddScreen(dlg);
285 }
#define REBOOT
Dialog asking for user confirmation.
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
Basic menu dialog, message and a list of options.
static void standby(void)
MythScreenStack * GetStack(const QString &stackname)
void SetDisableEventPopup(bool check)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static void quit(void)
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:62
An action (for this plugin) consists of a description, and a set of key sequences.
Definition: action.h:38
static bool DBusReboot(void)
void confirm(int Action)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
#define HALT
static void halt(bool Confirmed=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
static void reboot(bool Confirmed=true)
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host