MythTV  master
mythfrontend/exitprompt.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QCoreApplication>
3 
4 // MythTV
5 #include "config.h"
6 #include "exitprompt.h"
7 #include "mythcontext.h"
8 #include "mythdialogbox.h"
9 #include "mythmainwindow.h"
10 #include "mythscreenstack.h"
11 #include "mythsystemlegacy.h"
12 #include "mythlogging.h"
13 #include "exitcodes.h"
14 
16  : m_power(MythPower::AcquireRelease(this, true)),
17  m_confirm(gCoreContext->GetBoolSetting("ConfirmPowerEvent", true)),
18  m_haltCommand(gCoreContext->GetSetting("HaltCommand", "")),
19  m_rebootCommand(gCoreContext->GetSetting("RebootCommand", "")),
20  m_suspendCommand(gCoreContext->GetSetting("SuspendCommand", ""))
21 {
22  // Log to confirm we are not leaking prompters...
23  LOG(VB_GENERAL, LOG_INFO, "Created ExitPrompter");
24 }
25 
27 {
28  if (m_power)
29  MythPower::AcquireRelease(this, false);
30  LOG(VB_GENERAL, LOG_INFO, "Deleted ExitPrompter");
31 }
32 
34 {
35  // Ensure additional actions are not processed after we are deleted
36  if (m_dialog)
37  m_dialog->SetReturnEvent(nullptr, QString());
38 
39  qApp->exit();
40  deleteLater();
41 }
42 
44 {
46 }
47 
48 void ExitPrompter::DoHalt(bool Confirmed)
49 {
50  if (Confirmed)
51  {
52  bool handled = false;
53  // Use user specified command if it exists
54  if (!m_haltCommand.isEmpty())
55  {
57  if (ret == GENERIC_EXIT_OK)
58  {
59  handled = true;
60  }
61  else
62  {
63  LOG(VB_GENERAL, LOG_ERR, "User defined HaltCommand failed, falling back to "
64  "alternative methods.");
65  }
66  }
67 
68  // Otherwise use MythPower
71  handled = true;
72 
73  // halt of last resort
74  if (!handled)
75  myth_system("sudo /sbin/halt -p");
76  }
77  deleteLater();
78 }
79 
81 {
83 }
84 
85 void ExitPrompter::DoReboot(bool Confirmed)
86 {
87  if (Confirmed)
88  {
89  bool handled = false;
90  if (!m_rebootCommand.isEmpty())
91  {
93  if (ret == GENERIC_EXIT_OK)
94  {
95  handled = true;
96  }
97  else
98  {
99  LOG(VB_GENERAL, LOG_ERR, "User defined RebootCommand failed, falling back to "
100  "alternative methods.");
101  }
102  }
103 
104  // Otherwise use MythPower
107  handled = true;
108 
109  // reboot of last resort
110  if (!handled)
111  myth_system("sudo /sbin/reboot");
112  }
113  deleteLater();
114 }
115 
117 {
119 }
120 
121 void ExitPrompter::DoSuspend(bool Confirmed)
122 {
123  if (Confirmed)
124  {
125  bool handled = false;
126  // Use user specified command if it exists
127  if (!m_suspendCommand.isEmpty())
128  {
130  if (ret == GENERIC_EXIT_OK)
131  {
132  handled = true;
133  }
134  else
135  {
136  LOG(VB_GENERAL, LOG_ERR,
137  "User defined SuspendCommand failed, falling back to alternative methods.");
138  }
139  }
140 
143  }
144  deleteLater();
145 }
146 
148 {
150  deleteLater();
151 }
152 
153 void ExitPrompter::MainDialogClosed(const QString& /*unused*/, int Id)
154 {
155  // If the dialog box was closed without a result - or the result was no, then
156  // delete
157  if (Id < 1)
158  deleteLater();
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  // how do you want to quit today?
174  bool allowExit = false;
175  bool allowReboot = false;
176  bool allowShutdown = false;
177  bool allowStandby = false;
178  bool allowSuspend = false;
179 
180  bool haveshutdown = !m_haltCommand.isEmpty();
181  bool havereboot = !m_rebootCommand.isEmpty();
182  bool havesuspend = !m_suspendCommand.isEmpty();
183 
184 #ifdef Q_OS_ANDROID
185  haveshutdown = false;
186  havereboot = false;
187  havesuspend = false;
188 #endif
189 
190  if (m_power)
191  {
195  }
196 
197  switch (gCoreContext->GetNumSetting("OverrideExitMenu", 0))
198  {
199  case 0:
200  allowExit = true;
201  if (frontendOnly)
202  allowShutdown = haveshutdown;
203  break;
204  case 1:
205  allowExit = true;
206  break;
207  case 2:
208  allowExit = true;
209  allowShutdown = haveshutdown;
210  break;
211  case 3:
212  allowExit = true;
213  allowReboot = havereboot;
214  allowShutdown = haveshutdown;
215  break;
216  case 4:
217  allowShutdown = haveshutdown;
218  break;
219  case 5:
220  allowReboot = havereboot;
221  break;
222  case 6:
223  allowReboot = havereboot;
224  allowShutdown = haveshutdown;
225  break;
226  case 7:
227  allowStandby = true;
228  break;
229  case 8:
230  allowSuspend = havesuspend;
231  break;
232  case 9:
233  allowExit = true;
234  allowSuspend = havesuspend;
235  break;
236  case 10:
237  allowExit = true;
238  allowReboot = havereboot;
239  allowShutdown = haveshutdown;
240  allowSuspend = havesuspend;
241  break;
242  }
243 
244  delete m_dialog;
245  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
246  m_dialog = new MythDialogBox(tr("Do you really want to exit MythTV?"), ss,
247  "exit prompt");
248 
249  if (!m_dialog->Create())
250  {
251  LOG(VB_GENERAL, LOG_ERR, "Can't create Exit Prompt dialog?");
252  delete m_dialog;
253  DoQuit();
254  return;
255  }
256 
257  // ensure ExitPrompt is deleted if the dialog is not actioned
259 
260  bool confirm = m_confirm || !frontendOnly;
261 
262  m_dialog->AddButton(QCoreApplication::translate("(Common)", "No"));
263  if (allowExit)
264  m_dialog->AddButton(tr("Yes, Exit now"), &ExitPrompter::DoQuit);
265  if (allowReboot)
266  m_dialog->AddButton(tr("Yes, Exit and Reboot"),
267  confirm ? &ExitPrompter::ConfirmReboot : qOverload<>(&ExitPrompter::DoReboot));
268  if (allowShutdown)
269  m_dialog->AddButton(tr("Yes, Exit and Shutdown"),
270  confirm ? &ExitPrompter::ConfirmHalt : qOverload<>(&ExitPrompter::DoHalt));
271  if (allowStandby)
272  m_dialog->AddButton(tr("Yes, Enter Standby Mode"), &ExitPrompter::DoStandby);
273  if (allowSuspend)
274  m_dialog->AddButton(tr("Yes, Suspend"),
275  confirm ? &ExitPrompter::ConfirmSuspend : qOverload<>(&ExitPrompter::DoSuspend));
276 
277  // This is a hack so that the button clicks target the correct slot
278  m_dialog->SetReturnEvent(this, QString());
279  ss->AddScreen(m_dialog);
280 }
281 
283 {
284  // Main dialog will now be deleted
285  m_dialog = nullptr;
286 
287  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
288 
289  QString msg;
290  switch (Action)
291  {
292  case MythPower::FeatureShutdown: msg = tr("Are you sure you want to shutdown?"); break;
293  case MythPower::FeatureRestart: msg = tr("Are you sure you want to reboot?"); break;
294  case MythPower::FeatureSuspend: msg = tr("Are you sure you want to suspend?"); break;
295  default: break;
296  }
297 
300  msg.prepend(tr("Mythbackend is running on this system. "));
302 
303  auto *dlg = new MythConfirmationDialog(ss, msg);
304 
305  if (!dlg->Create())
306  {
307  delete dlg;
308  DoQuit();
309  return;
310  }
311 
313  connect(dlg, &MythConfirmationDialog::haveResult, this, qOverload<bool>(&ExitPrompter::DoHalt));
314  else if (Action == MythPower::FeatureRestart)
315  connect(dlg, &MythConfirmationDialog::haveResult, this, qOverload<bool>(&ExitPrompter::DoReboot));
316  else if (Action == MythPower::FeatureSuspend)
317  connect(dlg, &MythConfirmationDialog::haveResult, this, qOverload<bool>(&ExitPrompter::DoSuspend));
318  ss->AddScreen(dlg);
319 }
ExitPrompter::m_confirm
bool m_confirm
Definition: mythfrontend/exitprompt.h:34
MythDialogBox::SetReturnEvent
void SetReturnEvent(QObject *retobject, const QString &resultid)
Definition: mythdialogbox.cpp:301
ExitPrompter::ConfirmHalt
void ConfirmHalt()
Definition: mythfrontend/exitprompt.cpp:43
ExitPrompter::m_dialog
MythDialogBox * m_dialog
Definition: mythfrontend/exitprompt.h:38
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
MythPower
Definition: mythpower.h:23
MythPower::FeatureSuspend
@ FeatureSuspend
Definition: mythpower.h:43
exitprompt.h
MythCoreContext::IsFrontendOnly
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host
Definition: mythcorecontext.cpp:769
mythscreenstack.h
ExitPrompter::m_power
MythPower * m_power
Definition: mythfrontend/exitprompt.h:33
MythContext::SetDisableEventPopup
void SetDisableEventPopup(bool check)
Definition: mythcontext.cpp:1682
MythConfirmationDialog::haveResult
void haveResult(bool)
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
MythPower::FeatureShutdown
@ FeatureShutdown
Definition: mythpower.h:42
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDialogBox::Closed
void Closed(QString, int)
ExitPrompter::~ExitPrompter
~ExitPrompter() override
Definition: mythfrontend/exitprompt.cpp:26
ExitPrompter::DoReboot
void DoReboot()
Definition: mythfrontend/exitprompt.h:22
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:502
MythPower::IsFeatureSupported
bool IsFeatureSupported(Feature Supported)
Definition: mythpower.cpp:164
ExitPrompter::DoQuit
void DoQuit()
Definition: mythfrontend/exitprompt.cpp:33
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
Action
An action (for this plugin) consists of a description, and a set of key sequences.
Definition: action.h:40
mythsystemlegacy.h
ExitPrompter::m_suspendCommand
QString m_suspendCommand
Definition: mythfrontend/exitprompt.h:37
ExitPrompter::MainDialogClosed
void MainDialogClosed(const QString &, int Id)
Definition: mythfrontend/exitprompt.cpp:153
mythlogging.h
ExitPrompter::m_rebootCommand
QString m_rebootCommand
Definition: mythfrontend/exitprompt.h:36
MythDialogBox::AddButton
void AddButton(const QString &title)
Definition: mythdialogbox.h:198
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
MythPower::AcquireRelease
static MythPower * AcquireRelease(void *Reference, bool Acquire, std::chrono::seconds MinimumDelay=0s)
Definition: mythpower.cpp:74
MythDialogBox::Create
bool Create(void) override
Definition: mythdialogbox.cpp:127
ExitPrompter::DoStandby
void DoStandby()
Definition: mythfrontend/exitprompt.cpp:147
MythPower::RequestFeature
virtual bool RequestFeature(Feature Request, bool Delay=true)
Definition: mythpower.cpp:182
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:936
MythPower::Feature
Feature
Definition: mythpower.h:39
ExitPrompter::Confirm
void Confirm(MythPower::Feature Action)
Definition: mythfrontend/exitprompt.cpp:282
ExitPrompter::DoSuspend
void DoSuspend()
Definition: mythfrontend/exitprompt.h:25
ExitPrompter::m_haltCommand
QString m_haltCommand
Definition: mythfrontend/exitprompt.h:35
ExitPrompter::DoHalt
void DoHalt()
Definition: mythfrontend/exitprompt.h:20
MythConfirmationDialog
Dialog asking for user confirmation. Ok and optional Cancel button.
Definition: mythdialogbox.h:271
MythPower::FeatureRestart
@ FeatureRestart
Definition: mythpower.h:45
ExitPrompter::ConfirmReboot
void ConfirmReboot()
Definition: mythfrontend/exitprompt.cpp:80
mythcontext.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
ExitPrompter::HandleExit
void HandleExit()
Definition: mythfrontend/exitprompt.cpp:161
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:322
MythMainWindow::IdleTimeout
void IdleTimeout()
Definition: mythmainwindow.cpp:2150
exitcodes.h
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:50
ExitPrompter::ConfirmSuspend
void ConfirmSuspend()
Definition: mythfrontend/exitprompt.cpp:116
gContext
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:64
ExitPrompter::ExitPrompter
ExitPrompter()
Definition: mythfrontend/exitprompt.cpp:15