MythTV master
welcomedialog.cpp
Go to the documentation of this file.
1// POSIX
2#include <unistd.h>
3
4// C++
5#include <chrono>
6#include <cstdlib>
7
8// qt
9#include <QEvent>
10#include <QGuiApplication>
11#include <QKeyEvent>
12
13// myth
14#include "libmythbase/compat.h"
23#include "libmythtv/tv.h"
24
25// mythwelcome
26#include "welcomedialog.h"
27#include "welcomesettings.h"
28
29static constexpr std::chrono::milliseconds UPDATE_STATUS_INTERVAL { 30s };
30static constexpr std::chrono::milliseconds UPDATE_SCREEN_INTERVAL { 15s };
31
32
34 :MythScreenType(parent, name),
35 m_updateStatusTimer(new QTimer(this)),
36 m_updateScreenTimer(new QTimer(this))
37{
39
41 m_preRollSeconds = gCoreContext->GetDurSetting<std::chrono::seconds>("RecordPreRoll");
43 gCoreContext->GetDurSetting<std::chrono::minutes>("idleWaitForRecordingTime", 15min);
44 m_idleTimeoutSecs = gCoreContext->GetDurSetting<std::chrono::seconds>("idleTimeoutSecs", 0s);
45
46 // if idleTimeoutSecs is 0, the user disabled the auto-shutdown feature
48
52
55}
56
58{
59 // Load the theme for this screen
60 bool foundtheme = LoadWindowFromXML("welcome-ui.xml", "welcome_screen", this);
61 if (!foundtheme)
62 return false;
63
64 bool err = false;
65 UIUtilE::Assign(this, m_statusText, "status_text", &err);
66 UIUtilE::Assign(this, m_recordingText, "recording_text", &err);
67 UIUtilE::Assign(this, m_scheduledText, "scheduled_text", &err);
68 UIUtilE::Assign(this, m_warningText, "conflicts_text", &err);
69 UIUtilE::Assign(this, m_startFrontendButton, "startfrontend_button", &err);
70
71 if (err)
72 {
73 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'welcome_screen'");
74 return false;
75 }
76
78
79 m_startFrontendButton->SetText(tr("Start Frontend"));
82
84
86
89
90 return true;
91}
92
94{
95 QString startFECmd = gCoreContext->GetSetting("MythWelcomeStartFECmd",
96 m_appBinDir + "mythfrontend");
97
98 // Ensure we use the same platform for mythfrontend
99 QStringList args;
100 if (!startFECmd.contains("platform"))
101 args << QString("--platform %1").arg(QGuiApplication::platformName());
103 updateAll();
104 m_frontendIsRunning = false;
105}
106
108{
110 return;
111
112 m_frontendIsRunning = true;
113
114 // this makes sure the button appears to click properly
115 QTimer::singleShot(500ms, this, &WelcomeDialog::startFrontend);
116}
117
119{
120 // mythshutdown --startup returns 0 for automatic startup
121 // 1 for manual startup
122 QString command = m_appBinDir + "mythshutdown --startup";
123 command += logPropagateArgs;
124 uint state = myth_system(command, kMSDontBlockInputDevs);
125
126 LOG(VB_GENERAL, LOG_NOTICE,
127 QString("mythshutdown --startup returned: %1").arg(state));
128
129 bool bAutoStartFrontend = gCoreContext->GetBoolSetting("AutoStartFrontend", true);
130
131 if (state == 1 && bAutoStartFrontend)
133
134 // update status now
135 updateAll();
136}
137
139{
140 if (e->type() == MythEvent::kMythEventMessage)
141 {
142 auto *me = dynamic_cast<MythEvent *>(e);
143 if (me == nullptr)
144 return;
145
146 if (me->Message().startsWith("RECORDING_LIST_CHANGE") ||
147 me->Message() == "UPDATE_PROG_INFO")
148 {
149 LOG(VB_GENERAL, LOG_NOTICE,
150 "MythWelcome received a recording list change event");
151
152 QMutexLocker lock(&m_recListUpdateMuxtex);
153
155 {
156 LOG(VB_GENERAL, LOG_NOTICE,
157 " [deferred to pending handler]");
158 }
159 else
160 {
161 // we can't query the backend from inside a customEvent
162 QTimer::singleShot(500ms, this, &WelcomeDialog::updateRecordingList);
164 }
165 }
166 else if (me->Message().startsWith("SCHEDULE_CHANGE"))
167 {
168 LOG(VB_GENERAL, LOG_NOTICE,
169 "MythWelcome received a SCHEDULE_CHANGE event");
170
171 QMutexLocker lock(&m_schedUpdateMuxtex);
172
173 if (pendingSchedUpdate())
174 {
175 LOG(VB_GENERAL, LOG_NOTICE,
176 " [deferred to pending handler]");
177 }
178 else
179 {
180 QTimer::singleShot(500ms, this, &WelcomeDialog::updateScheduledList);
182 }
183 }
184 else if (me->Message().startsWith("SHUTDOWN_COUNTDOWN"))
185 {
186#if 0
187 LOG(VB_GENERAL, LOG_NOTICE,
188 "MythWelcome received a SHUTDOWN_COUNTDOWN event");
189#endif
190 QString secs = me->Message().mid(19);
191 m_secondsToShutdown = secs.toInt();
193 updateScreen();
194 }
195 else if (me->Message().startsWith("SHUTDOWN_NOW"))
196 {
197 LOG(VB_GENERAL, LOG_NOTICE,
198 "MythWelcome received a SHUTDOWN_NOW event");
200 {
201 // does the user want to shutdown this frontend only machine
202 // when the BE shuts down?
203 if (gCoreContext->GetNumSetting("ShutdownWithMasterBE", 0) == 1)
204 {
205 LOG(VB_GENERAL, LOG_NOTICE,
206 "MythWelcome is shutting this computer down now");
207 QString poweroff_cmd = gCoreContext->GetSetting("MythShutdownPowerOff", "");
208 if (!poweroff_cmd.isEmpty())
209 myth_system(poweroff_cmd, kMSDontBlockInputDevs);
210 }
211 }
212 }
213 }
214}
215
217{
219 auto *ssd = new StandardSettingDialog(mainStack, "settings", screen);
220 if (ssd->Create())
221 mainStack->AddScreen(ssd);
222 else
223 delete ssd;
224}
225
226bool WelcomeDialog::keyPressEvent(QKeyEvent *event)
227{
228 if (GetFocusWidget()->keyPressEvent(event))
229 return true;
230
231 QStringList actions;
232 bool handled = GetMythMainWindow()->TranslateKeyPress("Welcome", event, actions);
233
234 for (int i = 0; i < actions.size() && !handled; i++)
235 {
236 const QString& action = actions[i];
237 handled = true;
238
239 if (action == "ESCAPE")
240 {
241 return true; // eat escape key
242 }
243 if (action == "MENU")
244 {
245 ShowMenu();
246 }
247 else if (action == "NEXTVIEW")
248 {
249 Close();
250 }
251 else if (action == "INFO")
252 {
254 }
255 else if (action == "SHOWSETTINGS")
256 {
258 }
259 else if (action == "0")
260 {
261 QString mythshutdown_status =
262 m_appBinDir + "mythshutdown --status 0";
263 QString mythshutdown_unlock =
264 m_appBinDir + "mythshutdown --unlock";
265 QString mythshutdown_lock =
266 m_appBinDir + "mythshutdown --lock";
267
268 uint statusCode =
269 myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
270
271 // is shutdown locked by a user
272 if (!(statusCode & 0xFF00) && statusCode & 16)
273 {
274 myth_system(mythshutdown_unlock + logPropagateArgs, kMSDontBlockInputDevs);
275 }
276 else
277 {
279 }
280
282 updateScreen();
283 }
284 else if (action == "STARTXTERM")
285 {
286 QString cmd = gCoreContext->GetSetting("MythShutdownXTermCmd", "");
287 if (!cmd.isEmpty())
289 }
290 else if (action == "STARTSETUP")
291 {
292 QString mythtv_setup = m_appBinDir + "mythtv-setup";
293 myth_system(mythtv_setup + logPropagateArgs);
294 }
295 else
296 {
297 handled = false;
298 }
299 }
300
301 if (!handled && MythScreenType::keyPressEvent(event))
302 handled = true;
303
304 return handled;
305}
306
308{
309 Close();
310}
311
313{
315
317 m_updateStatusTimer->disconnect();
318
320 m_updateScreenTimer->disconnect();
321}
322
324{
326
328}
329
331{
332 QString status;
333
335 {
336 m_recordingText->SetText(tr("Cannot connect to server!"));
337 m_scheduledText->SetText(tr("Cannot connect to server!"));
339 }
340 else
341 {
342 // update recording
343 if (m_isRecording && !m_tunerList.empty())
344 {
346
347 while (!tuner.isRecording)
348 {
349 if (m_screenTunerNo < m_tunerList.size() - 1)
351 else
352 m_screenTunerNo = 0;
354 }
355
356 status = tr("Tuner %1 is recording:").arg(tuner.id);
357 status += "\n";
358 status += tuner.channame;
359 status += "\n" + tuner.title;
360 if (!tuner.subtitle.isEmpty())
361 status += "\n("+tuner.subtitle+")";
362
363 status += "\n" +
364 tr("%1 to %2", "Time period, 'starttime to endtime'")
367 }
368 else
369 {
370 status = tr("There are no recordings currently taking place");
371 }
372
373 m_recordingText->SetText(status);
374
375 // update scheduled
376 if (!m_scheduledList.empty())
377 {
380
382
383 InfoMap infomap;
384 progInfo.ToMap(infomap);
385
386 //status = QString("%1 of %2\n").arg(m_screenScheduledNo + 1)
387 // .arg(m_scheduledList.size());
388 status = infomap["channame"] + "\n";
389 status += infomap["title"];
390 if (!infomap["subtitle"].isEmpty())
391 status += "\n(" + infomap["subtitle"] + ")";
392
393 status += "\n" + infomap["timedate"];
394
395 if (m_screenScheduledNo < m_scheduledList.size() - 1)
397 else
399 }
400 else
401 {
402 status = tr("There are no scheduled recordings");
403 }
404
405 m_scheduledText->SetText(status);
406 }
407
408 // update status message
409 if (m_statusList.empty())
410 status = tr("Please Wait...");
411 else
412 {
413 if ((int)m_statusListNo >= m_statusList.count())
414 m_statusListNo = 0;
415
417 if (m_statusList.count() > 1)
418 status += "...";
419 m_statusText->SetText(status);
420
421 if ((int)m_statusListNo < m_statusList.count() - 1)
423 else
424 m_statusListNo = 0;
425 }
426
427 m_updateScreenTimer->stop();
428 m_updateScreenTimer->setSingleShot(true);
430}
431
432// taken from housekeeper.cpp
434{
435 QString command;
436
437 QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath",
438 "mythfilldatabase");
439 QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", "");
440
441 command = QString("%1 %2").arg(mfpath, mfarg);
442 command += logPropagateArgs;
443
444 command += "&";
445
446 LOG(VB_GENERAL, LOG_INFO, QString("Grabbing EPG data using command: %1\n")
447 .arg(command));
448
450}
451
453{
456}
457
459{
460 {
461 // clear pending flag early in case something happens while
462 // we're updating
463 QMutexLocker lock(&m_recListUpdateMuxtex);
465 }
466
467 m_tunerList.clear();
468 m_isRecording = false;
469 m_screenTunerNo = 0;
470
472 return false;
473
475
476 return true;
477}
478
480{
481 {
482 // clear pending flag early in case something happens while
483 // we're updating
484 QMutexLocker lock(&m_schedUpdateMuxtex);
486 }
487
488 m_scheduledList.clear();
490
492 {
494 return false;
495 }
496
499
500 updateStatus();
501 updateScreen();
502
503 return true;
504}
505
507{
508 m_statusList.clear();
509
510 QDateTime curtime = MythDate::current();
511
512 if (!m_isRecording && !m_nextRecordingStart.isNull() &&
513 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
515 {
516 m_statusList.append(tr("MythTV is about to start recording."));
517 }
518
519 if (m_isRecording)
520 {
521 m_statusList.append(tr("MythTV is busy recording."));
522 }
523
524 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
525 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
526
527 if (!(statusCode & 0xFF00))
528 {
529 if (statusCode & 1)
530 m_statusList.append(tr("MythTV is busy transcoding."));
531 if (statusCode & 2)
532 m_statusList.append(tr("MythTV is busy flagging commercials."));
533 if (statusCode & 4)
534 m_statusList.append(tr("MythTV is busy grabbing EPG data."));
535 if (statusCode & 16)
536 m_statusList.append(tr("MythTV is locked by a user."));
537 if (statusCode & 32)
538 m_statusList.append(tr("MythTV has running or pending jobs."));
539 if (statusCode & 64)
540 m_statusList.append(tr("MythTV is in a daily wakeup/shutdown period."));
541 if (statusCode & 128)
542 m_statusList.append(tr("MythTV is about to start a wakeup/shutdown period."));
543 }
544
545 if (m_statusList.empty())
546 {
548 {
549 m_statusList.append(tr("MythTV is idle and will shutdown in %n "
550 "second(s).", "", m_secondsToShutdown));
551 }
552 else
553 {
554 m_statusList.append(tr("MythTV is idle."));
555 }
556 }
557
559}
560
562{
563 m_updateStatusTimer->stop();
564
565 bool bRes = false;
566
568 bRes = true;
569 else
570 {
572 {
573 bRes = true;
574 updateAll();
575 }
576 else
577 {
578 updateScreen();
579 }
580 }
581
582 if (bRes)
584 else
585 m_updateStatusTimer->start(5s);
586
587 return bRes;
588}
589
591{
592 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
593
594 m_menuPopup = new MythDialogBox("Menu", popupStack, "actionmenu");
595
596 if (m_menuPopup->Create())
597 popupStack->AddScreen(m_menuPopup);
598
599 m_menuPopup->SetReturnEvent(this, "action");
600
601 QString mythshutdown_status = m_appBinDir + "mythshutdown --status 0";
602 uint statusCode = myth_system(mythshutdown_status + logPropagateArgs, kMSDontBlockInputDevs);
603
604 if (!(statusCode & 0xFF00) && statusCode & 16)
605 m_menuPopup->AddButton(tr("Unlock Shutdown"), &WelcomeDialog::unlockShutdown);
606 else
607 m_menuPopup->AddButton(tr("Lock Shutdown"), &WelcomeDialog::lockShutdown);
608
609 m_menuPopup->AddButton(tr("Run mythfilldatabase"), &WelcomeDialog::runEPGGrabber);
610 m_menuPopup->AddButton(tr("Shutdown Now"), &WelcomeDialog::shutdownNow);
612 m_menuPopup->AddButton(tr("Cancel"));
613}
614
616{
617 QString command = m_appBinDir + "mythshutdown --lock";
618 command += logPropagateArgs;
621 updateScreen();
622}
623
625{
626 QString command = m_appBinDir + "mythshutdown --unlock";
627 command += logPropagateArgs;
630 updateScreen();
631}
632
634{
636 sleep(1);
638 updateScreen();
639}
640
642{
643 // if this is a frontend only machine just shut down now
645 {
646 LOG(VB_GENERAL, LOG_INFO,
647 "MythWelcome is shutting this computer down now");
648 QString poweroff_cmd = gCoreContext->GetSetting("MythShutdownPowerOff", "");
649 if (!poweroff_cmd.isEmpty())
650 myth_system(poweroff_cmd, kMSDontBlockInputDevs);
651 return;
652 }
653
654 // don't shutdown if we are recording
655 if (m_isRecording)
656 {
657 ShowOkPopup(tr("Cannot shutdown because MythTV is currently recording"));
658 return;
659 }
660
661 QDateTime curtime = MythDate::current();
662
663 // don't shutdown if we are about to start recording
664 if (!m_nextRecordingStart.isNull() &&
665 std::chrono::seconds(curtime.secsTo(m_nextRecordingStart)) - m_preRollSeconds <
667 {
668 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start recording"));
669 return;
670 }
671
672 // don't shutdown if we are about to start a wakeup/shutdown period
673 QString command = m_appBinDir + "mythshutdown --status 0";
674 command += logPropagateArgs;
675
676 uint statusCode = myth_system(command, kMSDontBlockInputDevs);
677 if (!(statusCode & 0xFF00) && statusCode & 128)
678 {
679 ShowOkPopup(tr("Cannot shutdown because MythTV is about to start "
680 "a wakeup/shutdown period."));
681 return;
682 }
683
684 // set the wakeup time for the next scheduled recording
685 if (!m_nextRecordingStart.isNull())
686 {
687 QDateTime restarttime = m_nextRecordingStart.addSecs((-1) * m_preRollSeconds.count());
688
689 int add = gCoreContext->GetNumSetting("StartupSecsBeforeRecording", 240);
690 if (add)
691 restarttime = restarttime.addSecs((-1LL) * add);
692
693 QString wakeup_timeformat = gCoreContext->GetSetting("WakeupTimeFormat",
694 "yyyy-MM-ddThh:mm");
695 QString setwakeup_cmd = gCoreContext->GetSetting("SetWakeuptimeCommand",
696 "echo \'Wakeuptime would "
697 "be $time if command "
698 "set.\'");
699
700 if (wakeup_timeformat == "time_t")
701 {
702 QString time_ts;
703 setwakeup_cmd.replace("$time",
704 time_ts.setNum(restarttime.toSecsSinceEpoch())
705 );
706 }
707 else
708 {
709 setwakeup_cmd.replace(
710 "$time", restarttime.toLocalTime().toString(wakeup_timeformat));
711 }
712
713 if (!setwakeup_cmd.isEmpty())
714 {
715 myth_system(setwakeup_cmd, kMSDontBlockInputDevs);
716 }
717 }
718
719 // run command to set wakeuptime in bios and shutdown the system
720 command = QString();
721
722#ifndef _WIN32
723 command = "sudo ";
724#endif
725
726 command += m_appBinDir + "mythshutdown --shutdown" + logPropagateArgs;
727
729}
730
bool IsConnectedToMaster(void)
bool SafeConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
QString GetSetting(const QString &key, const QString &defaultval="")
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host
int GetNumSetting(const QString &key, int defaultval=0)
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
bool GetBoolSetting(const QString &key, bool defaultval=false)
Basic menu dialog, message and a list of options.
void AddButton(const QString &title)
void SetReturnEvent(QObject *retobject, const QString &resultid)
bool Create(void) override
This class is used as a container for messages.
Definition: mythevent.h:17
static const Type kMythEventMessage
Definition: mythevent.h:79
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
virtual void Close()
void SetText(const QString &msg)
void Clicked()
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
virtual void SetVisible(bool visible)
Holds information on recordings and videos.
Definition: programinfo.h:68
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
recording status stuff
Definition: tvremoteutil.h:17
bool isRecording
Definition: tvremoteutil.h:20
QDateTime endTime
Definition: tvremoteutil.h:25
QString subtitle
Definition: tvremoteutil.h:23
QString channame
Definition: tvremoteutil.h:21
QString title
Definition: tvremoteutil.h:22
QDateTime startTime
Definition: tvremoteutil.h:24
QTimer * m_updateScreenTimer
Definition: welcomedialog.h:66
QString m_appBinDir
Definition: welcomedialog.h:68
void setPendingSchedUpdate(bool newState)
Definition: welcomedialog.h:96
std::vector< TunerStatus > m_tunerList
Definition: welcomedialog.h:83
void lockShutdown(void)
bool checkConnectionToServer(void)
QDateTime m_nextRecordingStart
Definition: welcomedialog.h:73
void checkAutoStart(void)
void ShowMenu(void) override
bool updateRecordingList(void)
void customEvent(QEvent *e) override
bool pendingSchedUpdate() const
Definition: welcomedialog.h:95
static void ShowSettings(GroupSetting *screen)
MythUIText * m_recordingText
Definition: welcomedialog.h:57
uint m_screenScheduledNo
Definition: welcomedialog.h:78
std::chrono::seconds m_preRollSeconds
Definition: welcomedialog.h:74
QTimer * m_updateStatusTimer
Definition: welcomedialog.h:65
MythUIButton * m_startFrontendButton
Definition: welcomedialog.h:61
uint m_screenTunerNo
Definition: welcomedialog.h:77
std::chrono::seconds m_idleWaitForRecordingTime
Definition: welcomedialog.h:75
void startFrontendClick(void)
void setPendingRecListUpdate(bool newState)
Definition: welcomedialog.h:90
QMutex m_recListUpdateMuxtex
Definition: welcomedialog.h:86
std::chrono::seconds m_idleTimeoutSecs
Definition: welcomedialog.h:76
MythUIText * m_warningText
Definition: welcomedialog.h:59
void runEPGGrabber(void)
int m_secondsToShutdown
Definition: welcomedialog.h:72
MythUIText * m_statusText
Definition: welcomedialog.h:56
QMutex m_schedUpdateMuxtex
Definition: welcomedialog.h:92
void updateStatus(void)
bool Create(void) override
~WelcomeDialog() override
void updateAll(void)
QStringList m_statusList
Definition: welcomedialog.h:80
bool m_frontendIsRunning
Definition: welcomedialog.h:81
void shutdownNow(void)
std::vector< ProgramInfo > m_scheduledList
Definition: welcomedialog.h:84
WelcomeDialog(MythScreenStack *parent, const char *name)
void updateScreen(void)
static void runMythFillDatabase(void)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
MythDialogBox * m_menuPopup
Definition: welcomedialog.h:63
MythUIText * m_scheduledText
Definition: welcomedialog.h:58
bool updateScheduledList(void)
void updateStatusMessage(void)
bool pendingRecListUpdate() const
Definition: welcomedialog.h:89
void startFrontend(void)
void unlockShutdown(void)
void closeDialog(void)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
unsigned int uint
Definition: freesurround.h:24
QString logPropagateArgs
Definition: logging.cpp:82
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
QString GetAppBinDir(void)
Definition: mythdirs.cpp:260
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
@ kMSDisableUDPListener
disable MythMessage UDP listener for the duration of application.
Definition: mythsystem.h:50
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kTime
Default local time.
Definition: mythdate.h:22
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
bool GetNextRecordingList(QDateTime &nextRecordingStart, bool *hasConflicts, std::vector< ProgramInfo > *list)
int RemoteGetRecordingStatus(const ProgramInfo *pginfo, int overrecsecs, int underrecsecs)
Get status of an individual programme (with pre-post roll?).
Definition: remoteutil.cpp:505
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
static constexpr std::chrono::milliseconds UPDATE_SCREEN_INTERVAL
static constexpr std::chrono::milliseconds UPDATE_STATUS_INTERVAL