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