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