MythTV  master
statusbox.cpp
Go to the documentation of this file.
1 
2 #include "statusbox.h"
3 
4 using namespace std;
5 
6 #include <QRegExp>
7 #include <QHostAddress>
8 
9 #include "mythcorecontext.h"
10 #include "filesysteminfo.h"
11 #include "mythmiscutil.h"
12 #include "mythdb.h"
13 #include "mythlogging.h"
14 #include "mythversion.h"
15 #include "mythdate.h"
16 
17 #include "config.h"
18 #include "remoteutil.h"
19 #include "tv.h"
20 #include "jobqueue.h"
21 #include "cardutil.h"
22 #include "recordinginfo.h"
23 
24 #include "mythuihelper.h"
25 #include "mythuibuttonlist.h"
26 #include "mythuitext.h"
27 #include "mythuistatetype.h"
28 #include "mythdialogbox.h"
29 
30 struct LogLine {
31  QString line;
32  QString detail;
33  QString help;
34  QString helpdetail;
35  QString data;
36  QString state;
37 };
38 
39 
50  : MythScreenType(parent, "StatusBox")
51 {
52  m_minLevel = gCoreContext->GetNumSetting("LogDefaultView",5);
53 
54  m_iconState = nullptr;
55  m_categoryList = m_logList = nullptr;
56  m_helpText = nullptr;
57  m_justHelpText = nullptr;
58 
59  QStringList strlist;
60  strlist << "QUERY_IS_ACTIVE_BACKEND";
61  strlist << gCoreContext->GetHostName();
62 
64 
65  if (strlist[0] == "TRUE")
66  m_isBackendActive = true;
67  else
68  m_isBackendActive = false;
69 
70  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
71 }
72 
74 {
75  if (m_logList)
76  gCoreContext->SaveSetting("StatusBoxItemCurrent",
78 }
79 
81 {
82  if (!LoadWindowFromXML("status-ui.xml", "status", this))
83  return false;
84 
85  m_categoryList = dynamic_cast<MythUIButtonList *>(GetChild("category"));
86  m_logList = dynamic_cast<MythUIButtonList *>(GetChild("log"));
87 
88  m_iconState = dynamic_cast<MythUIStateType *>(GetChild("icon"));
89  m_helpText = dynamic_cast<MythUIText *>(GetChild("helptext"));
90  m_justHelpText = dynamic_cast<MythUIText *>(GetChild("justhelptext"));
91 
93  {
94  LOG(VB_GENERAL, LOG_ERR, "StatusBox, theme is missing "
95  "required elements");
96  return false;
97  }
98 
99  connect(m_categoryList, SIGNAL(itemSelected(MythUIButtonListItem *)),
101  connect(m_logList, SIGNAL(itemSelected(MythUIButtonListItem *)),
103  connect(m_logList, SIGNAL(itemClicked(MythUIButtonListItem *)),
104  SLOT(clicked(MythUIButtonListItem *)));
105 
106  BuildFocusList();
107  return true;
108 }
109 
111 {
112  MythUIButtonListItem *item;
113 
114  item = new MythUIButtonListItem(m_categoryList, tr("Listings Status"),
115  qVariantFromValue((void*)SLOT(doListingsStatus())));
116  item->DisplayState("listings", "icon");
117 
118  item = new MythUIButtonListItem(m_categoryList, tr("Schedule Status"),
119  qVariantFromValue((void*)SLOT(doScheduleStatus())));
120  item->DisplayState("schedule", "icon");
121 
122  item = new MythUIButtonListItem(m_categoryList, tr("Input Status"),
123  qVariantFromValue((void*)SLOT(doTunerStatus())));
124  item->DisplayState("tuner", "icon");
125 
126  item = new MythUIButtonListItem(m_categoryList, tr("Job Queue"),
127  qVariantFromValue((void*)SLOT(doJobQueueStatus())));
128  item->DisplayState("jobqueue", "icon");
129 
130  item = new MythUIButtonListItem(m_categoryList, tr("Machine Status"),
131  qVariantFromValue((void*)SLOT(doMachineStatus())));
132  item->DisplayState("machine", "icon");
133 
134  item = new MythUIButtonListItem(m_categoryList, tr("AutoExpire List"),
135  qVariantFromValue((void*)SLOT(doAutoExpireList())));
136  item->DisplayState("autoexpire", "icon");
137 
138  int itemCurrent = gCoreContext->GetNumSetting("StatusBoxItemCurrent", 0);
139  m_categoryList->SetItemCurrent(itemCurrent);
140 }
141 
142 void StatusBox::AddLogLine(const QString & line,
143  const QString & help,
144  const QString & detail,
145  const QString & helpdetail,
146  const QString & state,
147  const QString & data)
148 {
149  LogLine logline;
150  logline.line = line;
151 
152  if (detail.isEmpty())
153  logline.detail = line;
154  else
155  logline.detail = detail;
156 
157  if (help.isEmpty())
158  logline.help = logline.detail;
159  else
160  logline.help = help;
161 
162  if (helpdetail.isEmpty())
163  logline.helpdetail = logline.detail;
164  else
165  logline.helpdetail = helpdetail;
166 
167  logline.state = state;
168  logline.data = data;
169 
171  qVariantFromValue(logline));
172  if (logline.state.isEmpty())
173  logline.state = "normal";
174 
175  item->SetFontState(logline.state);
176  item->DisplayState(logline.state, "status");
177  item->SetText(logline.detail, "detail");
178 }
179 
180 bool StatusBox::keyPressEvent(QKeyEvent *event)
181 {
182  if (GetFocusWidget()->keyPressEvent(event))
183  return true;
184 
185  QStringList actions;
186  bool handled = GetMythMainWindow()->TranslateKeyPress("Status", event, actions);
187 
188  for (int i = 0; i < actions.size() && !handled; ++i)
189  {
190  QString action = actions[i];
191  handled = true;
192 
193  QRegExp logNumberKeys( "^[12345678]$" );
194 
196  QString currentItem;
197  if (currentButton)
198  currentItem = currentButton->GetText();
199 
200  handled = true;
201 
202  if (action == "MENU")
203  {
204  if (currentItem == tr("Log Entries"))
205  {
206  QString message = tr("Acknowledge all log entries at "
207  "this priority level or lower?");
208 
209  MythConfirmationDialog *confirmPopup =
210  new MythConfirmationDialog(m_popupStack, message);
211 
212  confirmPopup->SetReturnEvent(this, "LogAckAll");
213 
214  if (confirmPopup->Create())
215  m_popupStack->AddScreen(confirmPopup, false);
216  }
217  }
218  else if ((currentItem == tr("Log Entries")) &&
219  (logNumberKeys.indexIn(action) == 0))
220  {
221  m_minLevel = action.toInt();
222  if (m_helpText)
223  m_helpText->SetText(tr("Setting priority level to %1")
224  .arg(m_minLevel));
225  if (m_justHelpText)
226  m_justHelpText->SetText(tr("Setting priority level to %1")
227  .arg(m_minLevel));
228  doLogEntries();
229  }
230  else
231  handled = false;
232  }
233 
234  if (!handled && MythScreenType::keyPressEvent(event))
235  handled = true;
236 
237  return handled;
238 }
239 
241 {
242  if (!item || GetFocusWidget() != m_logList)
243  return;
244 
245  LogLine logline = item->GetData().value<LogLine>();
246  if (m_helpText)
247  m_helpText->SetText(logline.helpdetail);
248  if (m_justHelpText)
249  m_justHelpText->SetText(logline.help);
250 }
251 
253 {
254  if (!item)
255  return;
256 
257  disconnect(this, SIGNAL(updateLog()),nullptr,nullptr);
258 
259  const char *slot = (const char *)item->GetData().value<void*>();
260 
261  connect(this, SIGNAL(updateLog()), slot);
262  emit updateLog();
263 }
264 
266 {
267  if (!item)
268  return;
269 
270  LogLine logline = item->GetData().value<LogLine>();
271 
273  QString currentItem;
274  if (currentButton)
275  currentItem = currentButton->GetText();
276 
277  // FIXME: Comparisons against strings here is not great, changing names
278  // breaks everything and it's inefficient
279  if (currentItem == tr("Log Entries"))
280  {
281  QString message = tr("Acknowledge this log entry?");
282 
283  MythConfirmationDialog *confirmPopup =
284  new MythConfirmationDialog(m_popupStack, message);
285 
286  confirmPopup->SetReturnEvent(this, "LogAck");
287  confirmPopup->SetData(logline.data);
288 
289  if (confirmPopup->Create())
290  m_popupStack->AddScreen(confirmPopup, false);
291  }
292  else if (currentItem == tr("Job Queue"))
293  {
294  QStringList msgs;
295  int jobStatus;
296 
297  jobStatus = JobQueue::GetJobStatus(logline.data.toInt());
298 
299  if (jobStatus == JOB_QUEUED)
300  {
301  QString message = tr("Delete Job?");
302 
303  MythConfirmationDialog *confirmPopup =
304  new MythConfirmationDialog(m_popupStack, message);
305 
306  confirmPopup->SetReturnEvent(this, "JobDelete");
307  confirmPopup->SetData(logline.data);
308 
309  if (confirmPopup->Create())
310  m_popupStack->AddScreen(confirmPopup, false);
311  }
312  else if ((jobStatus == JOB_PENDING) ||
313  (jobStatus == JOB_STARTING) ||
314  (jobStatus == JOB_RUNNING) ||
315  (jobStatus == JOB_PAUSED))
316  {
317  QString label = tr("Job Queue Actions:");
318 
319  MythDialogBox *menuPopup = new MythDialogBox(label, m_popupStack,
320  "statusboxpopup");
321 
322  if (menuPopup->Create())
323  m_popupStack->AddScreen(menuPopup, false);
324 
325  menuPopup->SetReturnEvent(this, "JobModify");
326 
327  QVariant data = qVariantFromValue(logline.data);
328 
329  if (jobStatus == JOB_PAUSED)
330  menuPopup->AddButton(tr("Resume"), data);
331  else
332  menuPopup->AddButton(tr("Pause"), data);
333  menuPopup->AddButton(tr("Stop"), data);
334  menuPopup->AddButton(tr("No Change"), data);
335  }
336  else if (jobStatus & JOB_DONE)
337  {
338  QString message = tr("Requeue Job?");
339 
340  MythConfirmationDialog *confirmPopup =
341  new MythConfirmationDialog(m_popupStack, message);
342 
343  confirmPopup->SetReturnEvent(this, "JobRequeue");
344  confirmPopup->SetData(logline.data);
345 
346  if (confirmPopup->Create())
347  m_popupStack->AddScreen(confirmPopup, false);
348  }
349  }
350  else if (currentItem == tr("AutoExpire List"))
351  {
353 
354  if (rec)
355  {
356  QString label = tr("AutoExpire Actions:");
357 
358  MythDialogBox *menuPopup = new MythDialogBox(label, m_popupStack,
359  "statusboxpopup");
360 
361  if (menuPopup->Create())
362  m_popupStack->AddScreen(menuPopup, false);
363 
364  menuPopup->SetReturnEvent(this, "AutoExpireManage");
365 
366  menuPopup->AddButton(tr("Delete Now"), qVariantFromValue(rec));
367  if ((rec)->GetRecordingGroup() == "LiveTV")
368  {
369  menuPopup->AddButton(tr("Move to Default group"),
370  qVariantFromValue(rec));
371  }
372  else if ((rec)->GetRecordingGroup() == "Deleted")
373  menuPopup->AddButton(tr("Undelete"), qVariantFromValue(rec));
374  else
375  menuPopup->AddButton(tr("Disable AutoExpire"),
376  qVariantFromValue(rec));
377  menuPopup->AddButton(tr("No Change"), qVariantFromValue(rec));
378 
379  }
380  }
381 }
382 
383 void StatusBox::customEvent(QEvent *event)
384 {
385  if (event->type() == DialogCompletionEvent::kEventType)
386  {
388 
389  QString resultid = dce->GetId();
390  int buttonnum = dce->GetResult();
391 
392  if (resultid == "LogAck")
393  {
394  if (buttonnum == 1)
395  {
396  QString sql = dce->GetData().toString();
397  MSqlQuery query(MSqlQuery::InitCon());
398  query.prepare("UPDATE mythlog SET acknowledged = 1 "
399  "WHERE logid = :LOGID ;");
400  query.bindValue(":LOGID", sql);
401  if (!query.exec())
402  MythDB::DBError("StatusBox::customEvent -- LogAck", query);
404  }
405  }
406  else if (resultid == "LogAckAll")
407  {
408  if (buttonnum == 1)
409  {
410  MSqlQuery query(MSqlQuery::InitCon());
411  query.prepare("UPDATE mythlog SET acknowledged = 1 "
412  "WHERE priority <= :PRIORITY ;");
413  query.bindValue(":PRIORITY", m_minLevel);
414  if (!query.exec())
415  MythDB::DBError("StatusBox::customEvent -- LogAckAll",
416  query);
417  doLogEntries();
418  }
419  }
420  else if (resultid == "JobDelete")
421  {
422  if (buttonnum == 1)
423  {
424  int jobID = dce->GetData().toInt();
426 
428  }
429  }
430  else if (resultid == "JobRequeue")
431  {
432  if (buttonnum == 1)
433  {
434  int jobID = dce->GetData().toInt();
435  JobQueue::ChangeJobStatus(jobID, JOB_QUEUED);
437  }
438  }
439  else if (resultid == "JobModify")
440  {
441  int jobID = dce->GetData().toInt();
442  if (buttonnum == 0)
443  {
444  if (JobQueue::GetJobStatus(jobID) == JOB_PAUSED)
446  else
448  }
449  else if (buttonnum == 1)
450  {
452  }
453 
455  }
456  else if (resultid == "AutoExpireManage")
457  {
458  ProgramInfo* rec = dce->GetData().value<ProgramInfo*>();
459 
460  // button 2 is "No Change"
461  if (!rec || buttonnum == 2)
462  return;
463 
464  // button 1 is "Delete Now"
465  if ((buttonnum == 0) && rec->QueryIsDeleteCandidate())
466  {
468  false, false))
469  {
470  LOG(VB_GENERAL, LOG_ERR, QString("Failed to delete recording: %1").arg(rec->GetTitle()));
471  return;
472  }
473  }
474  // button 1 is "Move To Default Group" or "UnDelete" or "Disable AutoExpire"
475  else if (buttonnum == 1)
476  {
477  if ((rec)->GetRecordingGroup() == "Deleted")
478  {
480  }
481  else
482  {
484 
485  if ((rec)->GetRecordingGroup() == "LiveTV")
486  {
487  RecordingInfo ri(*rec);
489  *rec = ri;
490  }
491  }
492  }
493 
494  // remove the changed recording from the expire list
495  delete m_expList[m_logList->GetCurrentPos()];
496  m_expList.erase(m_expList.begin() + m_logList->GetCurrentPos());
497 
498  int pos = m_logList->GetCurrentPos();
499  int topPos = m_logList->GetTopItemPos();
500  doAutoExpireList(false);
501  m_logList->SetItemCurrent(pos, topPos);
502  }
503 
504  }
505 }
506 
508 {
509  if (m_iconState)
510  m_iconState->DisplayState("listings");
511  m_logList->Reset();
512 
513  QString helpmsg(tr("Listings Status shows the latest "
514  "status information from "
515  "mythfilldatabase"));
516  if (m_helpText)
517  m_helpText->SetText(helpmsg);
518  if (m_justHelpText)
519  m_justHelpText->SetText(helpmsg);
520 
521  QDateTime mfdLastRunStart, mfdLastRunEnd, mfdNextRunStart;
522  QString mfdLastRunStatus;
523  QString querytext, DataDirectMessage;
524  int DaysOfData;
525  QDateTime qdtNow, GuideDataThrough;
526 
527  qdtNow = MythDate::current();
528 
529  MSqlQuery query(MSqlQuery::InitCon());
530  query.prepare("SELECT max(endtime) FROM program WHERE manualid=0;");
531 
532  if (query.exec() && query.next())
533  GuideDataThrough = MythDate::fromString(query.value(0).toString());
534 
535  QString tmp = gCoreContext->GetSetting("mythfilldatabaseLastRunStart");
536  mfdLastRunStart = MythDate::fromString(tmp);
537  tmp = gCoreContext->GetSetting("mythfilldatabaseLastRunEnd");
538  mfdLastRunEnd = MythDate::fromString(tmp);
539  tmp = gCoreContext->GetSetting("MythFillSuggestedRunTime");
540  mfdNextRunStart = MythDate::fromString(tmp);
541 
542  mfdLastRunStatus = gCoreContext->GetSetting("mythfilldatabaseLastRunStatus");
543  DataDirectMessage = gCoreContext->GetSetting("DataDirectMessage");
544 
545  AddLogLine(tr("Mythfrontend version: %1 (%2)").arg(MYTH_SOURCE_PATH)
546  .arg(MYTH_SOURCE_VERSION), helpmsg);
547  AddLogLine(tr("Last mythfilldatabase guide update:"), helpmsg);
548  tmp = tr("Started: %1").arg(
550  mfdLastRunStart, MythDate::kDateTimeFull | MythDate::kSimplify));
551  AddLogLine(tmp, helpmsg);
552 
553  if (mfdLastRunEnd >= mfdLastRunStart)
554  {
555  tmp = tr("Finished: %1")
556  .arg(MythDate::toString(
557  mfdLastRunEnd,
559  AddLogLine(tmp, helpmsg);
560  }
561 
562  AddLogLine(tr("Result: %1").arg(mfdLastRunStatus), helpmsg);
563 
564 
565  if (mfdNextRunStart >= mfdLastRunStart)
566  {
567  tmp = tr("Suggested Next: %1")
568  .arg(MythDate::toString(
569  mfdNextRunStart,
571  AddLogLine(tmp, helpmsg);
572  }
573 
574  DaysOfData = qdtNow.daysTo(GuideDataThrough);
575 
576  if (GuideDataThrough.isNull())
577  {
578  AddLogLine(tr("There's no guide data available!"), helpmsg,
579  "", "warning");
580  AddLogLine(tr("Have you run mythfilldatabase?"), helpmsg,
581  "", "warning");
582  }
583  else
584  {
585  AddLogLine(
586  tr("There is guide data until %1")
587  .arg(MythDate::toString(
588  GuideDataThrough,
590 
591  AddLogLine(QString("(%1).").arg(tr("%n day(s)", "", DaysOfData)),
592  helpmsg);
593  }
594 
595  if (DaysOfData <= 3)
596  AddLogLine(tr("WARNING: is mythfilldatabase running?"), helpmsg,
597  "", "", "warning");
598 
599  if (!DataDirectMessage.isEmpty())
600  {
601  AddLogLine(tr("DataDirect Status: "), helpmsg);
602  AddLogLine(DataDirectMessage, helpmsg);
603  }
604 
605 }
606 
608 {
609  if (m_iconState)
610  m_iconState->DisplayState("schedule");
611  m_logList->Reset();
612 
613  QString helpmsg(tr("Schedule Status shows current statistics "
614  "from the scheduler."));
615  if (m_helpText)
616  m_helpText->SetText(helpmsg);
617  if (m_justHelpText)
618  m_justHelpText->SetText(helpmsg);
619 
620  MSqlQuery query(MSqlQuery::InitCon());
621 
622  query.prepare("SELECT COUNT(*) FROM record WHERE type = :TEMPLATE");
623  query.bindValue(":TEMPLATE", kTemplateRecord);
624  if (query.exec() && query.next())
625  {
626  QString rules = tr("%n template rule(s) (is) defined", "",
627  query.value(0).toInt());
628  AddLogLine(rules, helpmsg);
629  }
630  else
631  {
632  MythDB::DBError("StatusBox::doScheduleStatus()", query);
633  return;
634  }
635 
636  query.prepare("SELECT COUNT(*) FROM record "
637  "WHERE type <> :TEMPLATE AND search = :NOSEARCH");
638  query.bindValue(":TEMPLATE", kTemplateRecord);
639  query.bindValue(":NOSEARCH", kNoSearch);
640  if (query.exec() && query.next())
641  {
642  QString rules = tr("%n standard rule(s) (is) defined", "",
643  query.value(0).toInt());
644  AddLogLine(rules, helpmsg);
645  }
646  else
647  {
648  MythDB::DBError("StatusBox::doScheduleStatus()", query);
649  return;
650  }
651 
652  query.prepare("SELECT COUNT(*) FROM record WHERE search > :NOSEARCH");
653  query.bindValue(":NOSEARCH", kNoSearch);
654  if (query.exec() && query.next())
655  {
656  QString rules = tr("%n search rule(s) are defined", "",
657  query.value(0).toInt());
658  AddLogLine(rules, helpmsg);
659  }
660  else
661  {
662  MythDB::DBError("StatusBox::doScheduleStatus()", query);
663  return;
664  }
665 
666  QMap<RecStatus::Type, int> statusMatch;
667  QMap<RecStatus::Type, QString> statusText;
668  QMap<int, int> sourceMatch;
669  QMap<int, QString> sourceText;
670  QMap<int, int> cardMatch;
671  QMap<int, QString> cardText;
672  QMap<int, int> cardParent;
673  QMap<int, bool> cardSchedGroup;
674  QString tmpstr;
675  int maxSource = 0;
676  int maxCard = 0;
677  int lowerpriority = 0;
678  int hdflag = 0;
679 
680  query.prepare("SELECT MAX(sourceid) FROM videosource");
681  if (query.exec())
682  {
683  if (query.next())
684  maxSource = query.value(0).toInt();
685  }
686 
687  query.prepare("SELECT sourceid,name FROM videosource");
688  if (query.exec())
689  {
690  while (query.next())
691  sourceText[query.value(0).toInt()] = query.value(1).toString();
692  }
693 
694  query.prepare("SELECT MAX(cardid) FROM capturecard");
695  if (query.exec())
696  {
697  if (query.next())
698  maxCard = query.value(0).toInt();
699  }
700 
701  query.prepare("SELECT cardid, inputname, displayname, parentid, "
702  " schedgroup "
703  "FROM capturecard");
704  if (query.exec())
705  {
706  while (query.next())
707  {
708  int inputid = query.value(0).toInt();
709  cardText[inputid] = query.value(2).toString();
710  if (cardText[inputid].isEmpty())
711  cardText[inputid] = QString::number(query.value(1).toInt());
712  cardParent[inputid] = query.value(3).toInt();
713  cardSchedGroup[inputid] = query.value(4).toBool();
714  }
715  }
716 
717  ProgramList schedList;
718  LoadFromScheduler(schedList);
719 
720  tmpstr = tr("%n matching showing(s)", "", schedList.size());
721  AddLogLine(tmpstr, helpmsg);
722 
723  ProgramList::const_iterator it = schedList.begin();
724  for (; it != schedList.end(); ++it)
725  {
726  const ProgramInfo *s = *it;
727  const RecStatus::Type recstatus = s->GetRecordingStatus();
728 
729  if (statusMatch[recstatus] < 1)
730  {
731  statusText[recstatus] = RecStatus::toString(
732  recstatus, s->GetRecordingRuleType());
733  }
734 
735  ++statusMatch[recstatus];
736 
737  if (recstatus == RecStatus::WillRecord ||
738  recstatus == RecStatus::Pending ||
739  recstatus == RecStatus::Recording ||
740  recstatus == RecStatus::Tuning ||
741  recstatus == RecStatus::Failing)
742  {
743  ++sourceMatch[s->GetSourceID()];
744  int inputid = s->GetInputID();
745  // When schedgroup is used, always attribute recordings to
746  // the parent inputs.
747  if (cardParent[inputid] && cardSchedGroup[cardParent[inputid]])
748  inputid = cardParent[inputid];
749  ++cardMatch[inputid];
750  if (s->GetRecordingPriority2() < 0)
751  ++lowerpriority;
752  if (s->GetVideoProperties() & VID_HDTV)
753  ++hdflag;
754  }
755  }
756 
757 #define ADD_STATUS_LOG_LINE(rtype, fstate) \
758  do { \
759  if (statusMatch[rtype] > 0) \
760  { \
761  tmpstr = QString("%1 %2").arg(statusMatch[rtype]) \
762  .arg(statusText[rtype]); \
763  AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr, fstate);\
764  } \
765  } while (0)
776 
777  QString willrec = statusText[RecStatus::WillRecord];
778 
779  if (lowerpriority > 0)
780  {
781  tmpstr = QString("%1 %2 %3").arg(lowerpriority).arg(willrec)
782  .arg(tr("with lower priority"));
783  AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr, "warning");
784  }
785  if (hdflag > 0)
786  {
787  tmpstr = QString("%1 %2 %3").arg(hdflag).arg(willrec)
788  .arg(tr("marked as HDTV"));
789  AddLogLine(tmpstr, helpmsg);
790  }
791  int i;
792  for (i = 1; i <= maxSource; ++i)
793  {
794  if (sourceMatch[i] > 0)
795  {
796  tmpstr = QString("%1 %2 %3 %4 \"%5\"")
797  .arg(sourceMatch[i]).arg(willrec)
798  .arg(tr("from source")).arg(i).arg(sourceText[i]);
799  AddLogLine(tmpstr, helpmsg);
800  }
801  }
802  for (i = 1; i <= maxCard; ++i)
803  {
804  if (cardMatch[i] > 0)
805  {
806  tmpstr = QString("%1 %2 %3 %4 \"%5\"")
807  .arg(cardMatch[i]).arg(willrec)
808  .arg(tr("on input")).arg(i).arg(cardText[i]);
809  AddLogLine(tmpstr, helpmsg);
810  }
811  }
812 }
813 
815 {
816  struct info
817  {
818  int inputid;
819  bool schedgroup;
820  QString displayname;
821  int errored;
822  int unavailable;
823  int sleeping;
824  int recording;
825  int livetv;
826  int available;
827  QStringList recordings;
828  };
829  QMap<int, struct info> info;
830  QList<int> inputids;
831 
832  if (m_iconState)
833  m_iconState->DisplayState("tuner");
834  m_logList->Reset();
835 
836  QString helpmsg(tr("Input Status shows the current information "
837  "about the state of backend inputs"));
838  if (m_helpText)
839  m_helpText->SetText(helpmsg);
840  if (m_justHelpText)
841  m_justHelpText->SetText(helpmsg);
842 
843  MSqlQuery query(MSqlQuery::InitCon());
844  query.prepare(
845  "SELECT cardid, parentid, schedgroup, displayname "
846  "FROM capturecard ORDER BY cardid");
847 
848  if (!query.exec() || !query.isActive())
849  {
850  MythDB::DBError("StatusBox::doTunerStatus()", query);
851  return;
852  }
853 
854  while (query.next())
855  {
856  int inputid = query.value(0).toInt();
857  int parentid = query.value(1).toInt();
858 
859  // If this is a schedgroup child, attribute all status to the
860  // parent.
861  int infoid = inputid;
862  if (parentid && info[parentid].schedgroup)
863  infoid = parentid;
864  else
865  {
866  info[infoid].inputid = inputid;
867  info[infoid].schedgroup = query.value(2).toBool();
868  info[infoid].displayname = query.value(3).toString();
869  inputids.append(inputid);
870  }
871 
872  QString cmd = QString("QUERY_REMOTEENCODER %1").arg(inputid);
873  QStringList strlist( cmd );
874  strlist << "GET_STATE";
875 
877  int state = strlist[0].toInt();
878 
879  QString status;
880  QString fontstate;
881  if (state == kState_Error)
882  {
883  strlist.clear();
884  strlist << QString("QUERY_REMOTEENCODER %1").arg(inputid);
885  strlist << "GET_SLEEPSTATUS";
886 
888  int sleepState = strlist[0].toInt();
889 
890  if (sleepState == -1)
891  info[infoid].errored += 1;
892  else if (sleepState == sStatus_Undefined)
893  info[infoid].unavailable += 1;
894  else
895  info[infoid].sleeping += 1;
896  }
897  else if (state == kState_RecordingOnly ||
898  state == kState_WatchingRecording)
899  info[infoid].recording += 1;
900  else if (state == kState_WatchingLiveTV)
901  info[infoid].livetv += 1;
902  else
903  info[infoid].available += 1;
904 
905  if (state == kState_RecordingOnly ||
906  state == kState_WatchingRecording ||
907  state == kState_WatchingLiveTV)
908  {
909  strlist = QStringList( QString("QUERY_RECORDER %1").arg(inputid));
910  strlist << "GET_RECORDING";
912  ProgramInfo pginfo(strlist);
913  if (pginfo.GetChanID())
914  {
915  QString titlesub = pginfo.GetTitle();
916  if (!pginfo.GetSubtitle().isEmpty())
917  titlesub += QString(" - ") + pginfo.GetSubtitle();
918  info[infoid].recordings += titlesub;
919  }
920  }
921  }
922 
923  QList<int>::iterator it = inputids.begin();
924  for ( ; it != inputids.end(); ++it)
925  {
926  int inputid = *it;
927 
928  QStringList statuslist;
929  if (info[inputid].errored)
930  statuslist << tr("%1 errored").arg(info[inputid].errored);
931  if (info[inputid].unavailable)
932  statuslist << tr("%1 unavailable").arg(info[inputid].unavailable);
933  if (info[inputid].sleeping)
934  statuslist << tr("%1 sleeping").arg(info[inputid].sleeping);
935  if (info[inputid].recording)
936  statuslist << tr("%1 recording").arg(info[inputid].recording);
937  if (info[inputid].livetv)
938  statuslist << tr("%1 live television").arg(info[inputid].livetv);
939  if (info[inputid].available)
940  statuslist << tr("%1 available").arg(info[inputid].available);
941 
942  QString fontstate;
943  if (info[inputid].errored)
944  fontstate = "error";
945  else if (info[inputid].unavailable || info[inputid].sleeping)
946  fontstate = "warning";
947 
948  QString shortstatus = tr("Input %1 %2: %3")
949  .arg(inputid).arg(info[inputid].displayname)
950  .arg(statuslist.join(tr(", ")));
951  QString longstatus = shortstatus + "\n" +
952  info[inputid].recordings.join("\n");
953 
954  AddLogLine(shortstatus, helpmsg, longstatus, longstatus, fontstate);
955  }
956 }
957 
959 {
960  if (m_iconState)
961  m_iconState->DisplayState("log");
962  m_logList->Reset();
963 
964  QString helpmsg(tr("Log Entries shows any unread log entries "
965  "from the system if you have logging enabled"));
966  if (m_helpText)
967  m_helpText->SetText(helpmsg);
968  if (m_justHelpText)
969  m_justHelpText->SetText(helpmsg);
970 
971  MSqlQuery query(MSqlQuery::InitCon());
972  query.prepare("SELECT logid, module, priority, logdate, host, "
973  "message, details "
974  "FROM mythlog WHERE acknowledged = 0 "
975  "AND priority <= :PRIORITY ORDER BY logdate DESC;");
976  query.bindValue(":PRIORITY", m_minLevel);
977 
978  if (query.exec())
979  {
980  QString line;
981  QString detail;
982  while (query.next())
983  {
984  line = QString("%1").arg(query.value(5).toString());
985 
986  detail = tr("On %1 from %2.%3\n%4\n")
987  .arg(MythDate::toString(
988  MythDate::as_utc(query.value(3).toDateTime()),
990  .arg(query.value(4).toString())
991  .arg(query.value(1).toString())
992  .arg(query.value(5).toString());
993 
994  QString tmp = query.value(6).toString();
995  if (!tmp.isEmpty())
996  detail.append(tmp);
997  else
998  detail.append(tr("No further details"));
999 
1000  AddLogLine(line, helpmsg, detail, detail,
1001  "", query.value(0).toString());
1002  }
1003 
1004  if (query.size() == 0)
1005  {
1006  AddLogLine(tr("No items found at priority level %1 or lower.")
1007  .arg(m_minLevel), helpmsg);
1008  AddLogLine(tr("Use 1-8 to change priority level."), helpmsg);
1009  }
1010  }
1011 }
1012 
1014 {
1015  if (m_iconState)
1016  m_iconState->DisplayState("jobqueue");
1017  m_logList->Reset();
1018 
1019  QString helpmsg(tr("Job Queue shows any jobs currently in "
1020  "MythTV's Job Queue such as a commercial "
1021  "detection job."));
1022  if (m_helpText)
1023  m_helpText->SetText(helpmsg);
1024  if (m_justHelpText)
1025  m_justHelpText->SetText(helpmsg);
1026 
1027  QMap<int, JobQueueEntry> jobs;
1028  QMap<int, JobQueueEntry>::Iterator it;
1029 
1032  JOB_LIST_RECENT);
1033 
1034  if (jobs.size())
1035  {
1036  QString detail;
1037  QString line;
1038 
1039  for (it = jobs.begin(); it != jobs.end(); ++it)
1040  {
1041  ProgramInfo pginfo((*it).chanid, (*it).recstartts);
1042 
1043  if (!pginfo.GetChanID())
1044  continue;
1045 
1046  detail = QString("%1\n%2 %3 @ %4\n%5 %6 %7 %8")
1047  .arg(pginfo.GetTitle())
1048  .arg(pginfo.GetChannelName())
1049  .arg(pginfo.GetChanNum())
1050  .arg(MythDate::toString(
1051  pginfo.GetRecordingStartTime(),
1053  .arg(tr("Job:"))
1054  .arg(JobQueue::JobText((*it).type))
1055  .arg(tr("Status: "))
1056  .arg(JobQueue::StatusText((*it).status));
1057 
1058  if ((*it).status != JOB_QUEUED)
1059  detail += " (" + (*it).hostname + ')';
1060 
1061  if ((*it).schedruntime > MythDate::current())
1062  detail += '\n' + tr("Scheduled Run Time:") + ' ' +
1064  (*it).schedruntime,
1066  else
1067  detail += '\n' + (*it).comment;
1068 
1069  line = QString("%1 @ %2").arg(pginfo.GetTitle())
1070  .arg(MythDate::toString(
1071  pginfo.GetRecordingStartTime(),
1073 
1074  QString font;
1075  if ((*it).status == JOB_ERRORED)
1076  font = "error";
1077  else if ((*it).status == JOB_ABORTED)
1078  font = "warning";
1079 
1080  AddLogLine(line, helpmsg, detail, detail, font,
1081  QString("%1").arg((*it).id));
1082  }
1083  }
1084  else
1085  AddLogLine(tr("Job Queue is currently empty."), helpmsg);
1086 
1087 }
1088 
1089 // Some helper routines for doMachineStatus() that format the output strings
1090 
1098 static const QString sm_str(long long sizeKB, int prec=1)
1099 {
1100  if (sizeKB>1024*1024*1024) // Terabytes
1101  {
1102  double sizeGB = sizeKB/(1024*1024*1024.0);
1103  return QObject::tr("%1 TB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
1104  }
1105  else if (sizeKB>1024*1024) // Gigabytes
1106  {
1107  double sizeGB = sizeKB/(1024*1024.0);
1108  return QObject::tr("%1 GB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
1109  }
1110  else if (sizeKB>1024) // Megabytes
1111  {
1112  double sizeMB = sizeKB/1024.0;
1113  return QObject::tr("%1 MB").arg(sizeMB, 0, 'f', (sizeMB>10)?0:prec);
1114  }
1115  // Kilobytes
1116  return QObject::tr("%1 KB").arg(sizeKB);
1117 }
1118 
1119 static const QString usage_str_kb(long long total,
1120  long long used,
1121  long long free)
1122 {
1123  QString ret = QObject::tr("Unknown");
1124  if (total > 0.0 && free > 0.0)
1125  {
1126  double percent = (100.0*free)/total;
1127  ret = StatusBox::tr("%1 total, %2 used, %3 (or %4%) free.")
1128  .arg(sm_str(total)).arg(sm_str(used))
1129  .arg(sm_str(free)).arg(percent, 0, 'f', (percent >= 10.0) ? 0 : 2);
1130  }
1131  return ret;
1132 }
1133 
1134 static const QString usage_str_mb(float total, float used, float free)
1135 {
1136  return usage_str_kb((long long)(total*1024), (long long)(used*1024),
1137  (long long)(free*1024));
1138 }
1139 
1140 static void disk_usage_with_rec_time_kb(QStringList& out, long long total,
1141  long long used, long long free,
1142  const recprof2bps_t& prof2bps)
1143 {
1144  const QString tail = StatusBox::tr(", using your %1 rate of %2 kb/s");
1145 
1146  out<<usage_str_kb(total, used, free);
1147  if (free<0)
1148  return;
1149 
1150  recprof2bps_t::const_iterator it = prof2bps.begin();
1151  for (; it != prof2bps.end(); ++it)
1152  {
1153  const QString pro =
1154  tail.arg(it.key()).arg((int)((float)(*it) / 1024.0f));
1155 
1156  long long bytesPerMin = ((*it) >> 1) * 15;
1157  uint minLeft = ((free<<5)/bytesPerMin)<<5;
1158  minLeft = (minLeft/15)*15;
1159  uint hoursLeft = minLeft/60;
1160  QString hourstring = StatusBox::tr("%n hour(s)", "", hoursLeft);
1161  QString minstring = StatusBox::tr("%n minute(s)", "", minLeft%60);
1162  QString remainstring = StatusBox::tr("%1 remaining", "time");
1163  if (minLeft%60 == 0)
1164  out<<remainstring.arg(hourstring) + pro;
1165  else if (minLeft > 60)
1166  out<<StatusBox::tr("%1 and %2 remaining", "time").arg(hourstring)
1167  .arg(minstring) + pro;
1168  else
1169  out<<remainstring.arg(minstring) + pro;
1170  }
1171 }
1172 
1173 static const QString uptimeStr(time_t uptime)
1174 {
1175  int days, hours, min, secs;
1176  QString str;
1177 
1178  str = " " + StatusBox::tr("Uptime") + ": ";
1179 
1180  if (uptime == 0)
1181  return str + StatusBox::tr("unknown", "unknown uptime");
1182 
1183  days = uptime/(60*60*24);
1184  uptime -= days*60*60*24;
1185  hours = uptime/(60*60);
1186  uptime -= hours*60*60;
1187  min = uptime/60;
1188  secs = uptime%60;
1189 
1190  if (days > 0)
1191  {
1192  char buff[6];
1193  QString dayLabel = StatusBox::tr("%n day(s)", "", days);
1194 
1195  sprintf(buff, "%d:%02d", hours, min);
1196 
1197  return str + QString("%1, %2").arg(dayLabel).arg(buff);
1198  }
1199  else
1200  {
1201  char buff[9];
1202 
1203  sprintf(buff, "%d:%02d:%02d", hours, min, secs);
1204 
1205  return str + QString( buff );
1206  }
1207 }
1208 
1212 void StatusBox::getActualRecordedBPS(QString hostnames)
1213 {
1214  recordingProfilesBPS.clear();
1215 
1216  QString querystr;
1217  MSqlQuery query(MSqlQuery::InitCon());
1218 
1219  querystr =
1220  "SELECT sum(filesize) * 8 / "
1221  "sum(((unix_timestamp(endtime) - unix_timestamp(starttime)))) "
1222  "AS avg_bitrate "
1223  "FROM recorded WHERE hostname in (%1) "
1224  "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
1225 
1226  query.prepare(querystr.arg(hostnames));
1227 
1228  if (query.exec() && query.next() &&
1229  query.value(0).toDouble() > 0)
1230  {
1231  QString rateStr = tr("average", "average rate");
1232 
1233  // Don't user a tr() directly here as the Qt tools will
1234  // not be able to extract the string for translation.
1235  recordingProfilesBPS[rateStr] =
1236  (int)(query.value(0).toDouble());
1237  }
1238 
1239  querystr =
1240  "SELECT max(filesize * 8 / "
1241  "(unix_timestamp(endtime) - unix_timestamp(starttime))) "
1242  "AS max_bitrate "
1243  "FROM recorded WHERE hostname in (%1) "
1244  "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
1245 
1246  query.prepare(querystr.arg(hostnames));
1247 
1248  if (query.exec() && query.next() &&
1249  query.value(0).toDouble() > 0)
1250  {
1251  QString rateStr = tr("maximum", "maximum rate");
1252 
1253  // Don't user a tr() directly here as the Qt tools will
1254  // not be able to extract the string for translation.
1255  recordingProfilesBPS[rateStr] =
1256  (int)(query.value(0).toDouble());
1257  }
1258 }
1259 
1269 {
1270  if (m_iconState)
1271  m_iconState->DisplayState("machine");
1272  m_logList->Reset();
1273  QString machineStr = tr("Machine Status shows some operating system "
1274  "statistics of this machine");
1275  if (!m_isBackendActive)
1276  machineStr.append(" " + tr("and the MythTV server"));
1277 
1278  if (m_helpText)
1279  m_helpText->SetText(machineStr);
1280  if (m_justHelpText)
1281  m_justHelpText->SetText(machineStr);
1282 
1283  int totalM, usedM, freeM; // Physical memory
1284  int totalS, usedS, freeS; // Virtual memory (swap)
1285  time_t uptime;
1286 
1287  QString line;
1288  if (m_isBackendActive)
1289  line = tr("System:");
1290  else
1291  line = tr("This machine:");
1292  AddLogLine(line, machineStr);
1293 
1294  // uptime
1295  if (!getUptime(uptime))
1296  uptime = 0;
1297  line = uptimeStr(uptime);
1298 
1299  // weighted average loads
1300  line.append(". " + tr("Load") + ": ");
1301 
1302 #if defined(_WIN32) || defined(Q_OS_ANDROID)
1303  line.append(tr("unknown") + " - getloadavg() " + tr("failed"));
1304 #else // if !_WIN32
1305  double loads[3];
1306  if (getloadavg(loads,3) == -1)
1307  line.append(tr("unknown") + " - getloadavg() " + tr("failed"));
1308  else
1309  {
1310  char buff[30];
1311 
1312  sprintf(buff, "%0.2lf, %0.2lf, %0.2lf", loads[0], loads[1], loads[2]);
1313  line.append(QString(buff));
1314  }
1315 #endif // _WIN32
1316 
1317  AddLogLine(line, machineStr);
1318 
1319  // memory usage
1320  if (getMemStats(totalM, freeM, totalS, freeS))
1321  {
1322  usedM = totalM - freeM;
1323  if (totalM > 0)
1324  {
1325  line = " " + tr("RAM") + ": " + usage_str_mb(totalM, usedM, freeM);
1326  AddLogLine(line, machineStr);
1327  }
1328  usedS = totalS - freeS;
1329  if (totalS > 0)
1330  {
1331  line = " " + tr("Swap") +
1332  ": " + usage_str_mb(totalS, usedS, freeS);
1333  AddLogLine(line, machineStr);
1334  }
1335  }
1336 
1337  if (!m_isBackendActive)
1338  {
1339  line = tr("MythTV server") + ':';
1340  AddLogLine(line, machineStr);
1341 
1342  // uptime
1343  if (!RemoteGetUptime(uptime))
1344  uptime = 0;
1345  line = uptimeStr(uptime);
1346 
1347  // weighted average loads
1348  line.append(". " + tr("Load") + ": ");
1349  float floads[3];
1350  if (RemoteGetLoad(floads))
1351  {
1352  char buff[30];
1353 
1354  sprintf(buff, "%0.2f, %0.2f, %0.2f",
1355  static_cast<double>(floads[0]),
1356  static_cast<double>(floads[1]),
1357  static_cast<double>(floads[2]));
1358  line.append(QString(buff));
1359  }
1360  else
1361  line.append(tr("unknown"));
1362 
1363  AddLogLine(line, machineStr);
1364 
1365  // memory usage
1366  if (RemoteGetMemStats(totalM, freeM, totalS, freeS))
1367  {
1368  usedM = totalM - freeM;
1369  if (totalM > 0)
1370  {
1371  line = " " + tr("RAM") +
1372  ": " + usage_str_mb(totalM, usedM, freeM);
1373  AddLogLine(line, machineStr);
1374  }
1375 
1376  usedS = totalS - freeS;
1377  if (totalS > 0)
1378  {
1379  line = " " + tr("Swap") +
1380  ": " + usage_str_mb(totalS, usedS, freeS);
1381  AddLogLine(line, machineStr);
1382  }
1383  }
1384  }
1385 
1386  // get free disk space
1387  QString hostnames;
1388 
1389  QList<FileSystemInfo> fsInfos = FileSystemInfo::RemoteGetInfo();
1390  for (int i = 0; i < fsInfos.size(); ++i)
1391  {
1392  // For a single-directory installation just display the totals
1393  if ((fsInfos.size() == 2) && (i == 0) &&
1394  (fsInfos[i].getPath() != "TotalDiskSpace") &&
1395  (fsInfos[i+1].getPath() == "TotalDiskSpace"))
1396  i++;
1397 
1398  hostnames = QString("\"%1\"").arg(fsInfos[i].getHostname());
1399  hostnames.replace(' ', "");
1400  hostnames.replace(',', "\",\"");
1401 
1402  getActualRecordedBPS(hostnames);
1403 
1404  QStringList list;
1406  fsInfos[i].getTotalSpace(), fsInfos[i].getUsedSpace(),
1407  fsInfos[i].getTotalSpace() - fsInfos[i].getUsedSpace(),
1409 
1410  if (fsInfos[i].getPath() == "TotalDiskSpace")
1411  {
1412  line = tr("Total Disk Space:");
1413  AddLogLine(line, machineStr);
1414  }
1415  else
1416  {
1417  line = tr("MythTV Drive #%1:").arg(fsInfos[i].getFSysID());
1418  AddLogLine(line, machineStr);
1419 
1420  QStringList tokens = fsInfos[i].getPath().split(',');
1421 
1422  if (tokens.size() > 1)
1423  {
1424  AddLogLine(QString(" ") + tr("Directories:"), machineStr);
1425 
1426  int curToken = 0;
1427  while (curToken < tokens.size())
1428  AddLogLine(QString(" ") +
1429  tokens[curToken++], machineStr);
1430  }
1431  else
1432  {
1433  AddLogLine(QString(" " ) + tr("Directory:") + ' ' +
1434  fsInfos[i].getPath(), machineStr);
1435  }
1436  }
1437 
1438  QStringList::iterator it = list.begin();
1439  for (;it != list.end(); ++it)
1440  {
1441  line = QString(" ") + (*it);
1442  AddLogLine(line, machineStr);
1443  }
1444  }
1445 
1446 }
1447 
1451 void StatusBox::doAutoExpireList(bool updateExpList)
1452 {
1453  if (m_iconState)
1454  m_iconState->DisplayState("autoexpire");
1455  m_logList->Reset();
1456 
1457  QString helpmsg(tr("The AutoExpire List shows all recordings "
1458  "which may be expired and the order of "
1459  "their expiration. Recordings at the top "
1460  "of the list will be expired first."));
1461  if (m_helpText)
1462  m_helpText->SetText(helpmsg);
1463  if (m_justHelpText)
1464  m_justHelpText->SetText(helpmsg);
1465 
1466  ProgramInfo* pginfo;
1467  QString contentLine;
1468  QString detailInfo;
1469  QString staticInfo;
1470  long long totalSize(0);
1471  long long liveTVSize(0);
1472  int liveTVCount(0);
1473  long long deletedGroupSize(0);
1474  int deletedGroupCount(0);
1475 
1476  vector<ProgramInfo *>::iterator it;
1477 
1478  if (updateExpList)
1479  {
1480  for (it = m_expList.begin(); it != m_expList.end(); ++it)
1481  delete *it;
1482  m_expList.clear();
1483 
1485  }
1486 
1487  for (it = m_expList.begin(); it != m_expList.end(); ++it)
1488  {
1489  pginfo = *it;
1490 
1491  totalSize += pginfo->GetFilesize();
1492  if (pginfo->GetRecordingGroup() == "LiveTV")
1493  {
1494  liveTVSize += pginfo->GetFilesize();
1495  liveTVCount++;
1496  }
1497  else if (pginfo->GetRecordingGroup() == "Deleted")
1498  {
1499  deletedGroupSize += pginfo->GetFilesize();
1500  deletedGroupCount++;
1501  }
1502  }
1503 
1504  staticInfo = tr("%n recording(s) consuming %1 (is) allowed to expire\n", "",
1505  m_expList.size()).arg(sm_str(totalSize / 1024));
1506 
1507  if (liveTVCount)
1508  staticInfo += tr("%n (is) LiveTV and consume(s) %1\n", "", liveTVCount)
1509  .arg(sm_str(liveTVSize / 1024));
1510 
1511  if (deletedGroupCount)
1512  staticInfo += tr("%n (is) Deleted and consume(s) %1\n", "",
1513  deletedGroupCount)
1514  .arg(sm_str(deletedGroupSize / 1024));
1515 
1516  for (it = m_expList.begin(); it != m_expList.end(); ++it)
1517  {
1518  pginfo = *it;
1519  QDateTime starttime = pginfo->GetRecordingStartTime();
1520  QDateTime endtime = pginfo->GetRecordingEndTime();
1521  contentLine =
1523  starttime, MythDate::kDateFull | MythDate::kSimplify) + " - ";
1524 
1525  contentLine +=
1526  "(" + ProgramInfo::i18n(pginfo->GetRecordingGroup()) + ") ";
1527 
1528  contentLine += pginfo->GetTitle() +
1529  " (" + sm_str(pginfo->GetFilesize() / 1024) + ")";
1530 
1531  detailInfo =
1534  " - " +
1537 
1538  detailInfo += " (" + sm_str(pginfo->GetFilesize() / 1024) + ")";
1539 
1540  detailInfo += " (" + ProgramInfo::i18n(pginfo->GetRecordingGroup()) + ")";
1541 
1542  detailInfo += "\n" + pginfo->toString(ProgramInfo::kTitleSubtitle, " - ");
1543 
1544  AddLogLine(contentLine, staticInfo, detailInfo,
1545  staticInfo + detailInfo);
1546  }
1547 }
1548 
1550 
1551 /* vim: set expandtab tabstop=4 shiftwidth=4: */
void doScheduleStatus()
Definition: statusbox.cpp:607
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:794
static void disk_usage_with_rec_time_kb(QStringList &out, long long total, long long used, long long free, const recprof2bps_t &prof2bps)
Definition: statusbox.cpp:1140
MythUIButtonList * m_categoryList
Definition: statusbox.h:60
Error State, if we ever try to enter this state errored is set.
Definition: tv.h:54
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:875
uint GetInputID(void) const
Definition: programinfo.h:457
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:63
vector< ProgramInfo * > m_expList
Definition: statusbox.h:67
static bool DeleteJob(int jobID)
Definition: jobqueue.cpp:895
Dialog asking for user confirmation.
void doMachineStatus()
Show machine status.
Definition: statusbox.cpp:1268
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
Definition: programinfo.h:380
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
static const QList< FileSystemInfo > RemoteGetInfo(MythSocket *sock=nullptr)
virtual uint64_t GetFilesize(void) const
bool Create(void) override
Definition: statusbox.cpp:80
void SaveSetting(const QString &key, int newValue)
uint GetSourceID(void) const
Definition: programinfo.h:456
static QString JobText(int jobType)
Definition: jobqueue.cpp:1141
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
int GetTopItemPos(void) const
StatusBox(MythScreenStack *parent)
Definition: statusbox.cpp:49
bool RemoteGetMemStats(int &totalMB, int &freeMB, int &totalVM, int &freeVM)
Definition: remoteutil.cpp:74
void doTunerStatus()
Definition: statusbox.cpp:814
Basic menu dialog, message and a list of options.
QString toString(Verbosity v=kLongDescription, QString sep=":", QString grp="\"") const
QString GetTitle(void) const
Definition: programinfo.h:355
bool QueryIsDeleteCandidate(bool one_player_allowed=false) const
Returns true iff this is a recording, it is not in use (except by the recorder), and at most one play...
int size(void) const
Definition: mythdbcon.h:187
void setHelpText(MythUIButtonListItem *item)
Definition: statusbox.cpp:240
static bool ChangeJobStatus(int jobID, int newStatus, QString comment="")
Definition: jobqueue.cpp:1006
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:168
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
void RemoteGetAllExpiringRecordings(vector< ProgramInfo * > &expiringlist)
Definition: remoteutil.cpp:169
MythScreenStack * GetStack(const QString &stackname)
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:80
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
int m_minLevel
Definition: statusbox.h:71
size_t size(void) const
bool getMemStats(int &totalMB, int &freeMB, int &totalVM, int &freeVM)
Returns memory statistics in megabytes.
Default local time.
Definition: mythdate.h:21
void clicked(MythUIButtonListItem *item)
Definition: statusbox.cpp:265
static const QString usage_str_kb(long long total, long long used, long long free)
Definition: statusbox.cpp:1119
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:370
Q_DECLARE_METATYPE(GrabberScript *)
static guint32 * tmp
Definition: goom_core.c:35
QString help
Definition: statusbox.cpp:33
iterator begin(void)
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:23
void RemoveItem(MythUIButtonListItem *item)
void BuildFocusList(void)
static int GetJobsInQueue(QMap< int, JobQueueEntry > &jobs, int findJobs=JOB_LIST_NOT_DONE)
Definition: jobqueue.cpp:1302
static Type kEventType
Definition: mythdialogbox.h:50
uint GetVideoProperties(void) const
Definition: programinfo.h:488
void doAutoExpireList(bool updateExpList=true)
Show list of recordings which may AutoExpire.
Definition: statusbox.cpp:1451
static bool StopJob(int jobID)
Definition: jobqueue.cpp:765
bool RemoteDeleteRecording(uint recordingID, bool forceMetadataDelete, bool forgetHistory)
Definition: remoteutil.cpp:110
recprof2bps_t recordingProfilesBPS
Definition: statusbox.h:65
QVariant value(int i) const
Definition: mythdbcon.h:182
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
static bool ResumeJob(int jobID)
Definition: jobqueue.cpp:747
MythScreenStack * m_popupStack
Definition: statusbox.h:69
Holds information on recordings and videos.
Definition: programinfo.h:66
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:84
static const QString sm_str(long long sizeKB, int prec=1)
Returns a short string describing an amount of space, choosing one of a number of useful units,...
Definition: statusbox.cpp:1098
void updateLog()
MythUIText * m_justHelpText
Definition: statusbox.h:59
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
QString helpdetail
Definition: statusbox.cpp:34
void customEvent(QEvent *) override
Definition: statusbox.cpp:383
static QString toString(Type, uint id)
Converts "recstatus" into a short (unreadable) string.
Definition: recStatus.cpp:39
QString GetSubtitle(void) const
Definition: programinfo.h:357
static QString StatusText(int status)
Definition: jobqueue.cpp:1160
bool isActive(void) const
Definition: mythdbcon.h:188
Default local time.
Definition: mythdate.h:16
void SetReturnEvent(QObject *retobject, const QString &resultid)
QString GetRecordingGroup(void) const
Definition: programinfo.h:413
uint GetRecordingID(void) const
Definition: programinfo.h:440
bool keyPressEvent(QKeyEvent *) override
Key event handler.
Definition: statusbox.cpp:180
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:547
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:23
void doJobQueueStatus()
Definition: statusbox.cpp:1013
~StatusBox(void)
Definition: statusbox.cpp:73
static QString i18n(const QString &)
Translations for play,recording, & storage groups +.
#define getloadavg(x, y)
Definition: compat.h:315
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:101
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythUIText * m_helpText
Definition: statusbox.h:58
MythUIType * GetFocusWidget(void) const
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
QString GetText(const QString &name="") const
int GetNumSetting(const QString &key, int defaultval=0)
#define MYTH_SOURCE_PATH
Definition: version.h:3
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:819
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void AddLogLine(const QString &line, const QString &help="", const QString &detail="", const QString &helpdetail="", const QString &state="", const QString &data="")
Definition: statusbox.cpp:142
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:441
#define ADD_STATUS_LOG_LINE(rtype, fstate)
MythUIButtonList * m_logList
Definition: statusbox.h:61
int GetRecordingPriority2(void) const
Definition: programinfo.h:435
QMap< QString, unsigned int > recprof2bps_t
Definition: statusbox.h:14
void doListingsStatus()
Definition: statusbox.cpp:507
bool Create(void) override
void updateLogList(MythUIButtonListItem *item)
Definition: statusbox.cpp:252
QString state
Definition: statusbox.cpp:36
bool RemoteGetLoad(float load[3])
Definition: remoteutil.cpp:39
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:445
static bool PauseJob(int jobID)
Definition: jobqueue.cpp:738
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:366
void SetReturnEvent(QObject *retobject, const QString &resultid)
iterator end(void)
bool RemoteUndeleteRecording(uint recordingID)
Definition: remoteutil.cpp:140
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, QString altTable="", int recordid=-1)
Definition: programinfo.h:876
Default local time.
Definition: mythdate.h:20
A slave's sleep status is undefined when it has never connected to the master backend or is not able ...
Definition: tv.h:117
bool DisplayState(const QString &name)
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:398
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:406
void SetItemCurrent(MythUIButtonListItem *item)
bool m_isBackendActive
Definition: statusbox.h:73
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:615
bool RemoteGetUptime(time_t &uptime)
Definition: remoteutil.cpp:54
QString line
Definition: statusbox.cpp:31
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
Screen in which all other widgets are contained and rendered.
int GetCurrentPos() const
void getActualRecordedBPS(QString hostnames)
Fills in recordingProfilesBPS w/ average bitrate from recorded table.
Definition: statusbox.cpp:1212
static enum JobStatus GetJobStatus(int jobID)
Definition: jobqueue.cpp:1551
List::const_iterator const_iterator
void doLogEntries()
Definition: statusbox.cpp:958
QString GetHostName(void)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
QString data
Definition: statusbox.cpp:35
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:155
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
void DisplayState(const QString &state, const QString &name)
bool getUptime(time_t &uptime)
Returns uptime statistics.
#define MYTH_SOURCE_VERSION
Definition: version.h:2
static const QString uptimeStr(time_t uptime)
Definition: statusbox.cpp:1173
static const QString usage_str_mb(float total, float used, float free)
Definition: statusbox.cpp:1134
void SetData(QVariant data)
MythUIStateType * m_iconState
Definition: statusbox.h:62
MythUIButtonListItem * GetItemCurrent() const
bool Create(void) override
QString detail
Definition: statusbox.cpp:32
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
Definition: statusbox.cpp:110
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".