2 #include <QHostAddress>
3 #include <QNetworkInterface>
13 #include "libmythbase/mythversion.h"
63 strlist <<
"QUERY_IS_ACTIVE_BACKEND";
93 LOG(VB_GENERAL, LOG_ERR,
"StatusBox, theme is missing "
113 item->DisplayState(
"listings",
"icon");
117 item->DisplayState(
"schedule",
"icon");
121 item->DisplayState(
"tuner",
"icon");
125 item->DisplayState(
"jobqueue",
"icon");
129 item->DisplayState(
"decoders",
"icon");
133 item->DisplayState(
"display",
"icon");
137 item->DisplayState(
"render",
"icon");
141 item->DisplayState(
"machine",
"icon");
145 item->DisplayState(
"autoexpire",
"icon");
152 const QString &
help,
153 const QString & detail,
154 const QString & helpdetail,
155 const QString & state,
156 const QString & data)
161 if (detail.isEmpty())
171 if (helpdetail.isEmpty())
183 item->SetFontState(logline.
m_state);
184 item->DisplayState(logline.
m_state,
"status");
185 item->SetText(logline.
m_detail,
"detail");
198 for (
int i = 0; i < actions.size() && !handled; ++i)
200 QString
action = actions[i];
260 currentItem = currentButton->
GetText();
264 if (currentItem == tr(
"Job Queue"))
268 if (jobStatus == JOB_QUEUED)
270 QString message = tr(
"Delete Job?");
275 confirmPopup->SetReturnEvent(
this,
"JobDelete");
276 confirmPopup->SetData(logline.m_data);
278 if (confirmPopup->Create())
281 else if ((jobStatus == JOB_PENDING) ||
282 (jobStatus == JOB_STARTING) ||
283 (jobStatus == JOB_RUNNING) ||
284 (jobStatus == JOB_PAUSED))
286 QString label = tr(
"Job Queue Actions:");
291 if (menuPopup->Create())
294 menuPopup->SetReturnEvent(
this,
"JobModify");
296 QVariant data = QVariant::fromValue(logline.m_data);
298 if (jobStatus == JOB_PAUSED)
299 menuPopup->AddButtonV(tr(
"Resume"), data);
301 menuPopup->AddButtonV(tr(
"Pause"), data);
302 menuPopup->AddButtonV(tr(
"Stop"), data);
303 menuPopup->AddButtonV(tr(
"No Change"), data);
305 else if (jobStatus & JOB_DONE)
307 QString message = tr(
"Requeue Job?");
312 confirmPopup->SetReturnEvent(
this,
"JobRequeue");
313 confirmPopup->SetData(logline.m_data);
315 if (confirmPopup->Create())
319 else if (currentItem == tr(
"AutoExpire List"))
325 QString label = tr(
"AutoExpire Actions:");
330 if (menuPopup->Create())
333 menuPopup->SetReturnEvent(
this,
"AutoExpireManage");
335 menuPopup->AddButtonV(tr(
"Delete Now"), QVariant::fromValue(rec));
336 if ((rec)->GetRecordingGroup() ==
"LiveTV")
338 menuPopup->AddButtonV(tr(
"Move to Default group"),
339 QVariant::fromValue(rec));
341 else if ((rec)->GetRecordingGroup() ==
"Deleted")
342 menuPopup->AddButtonV(tr(
"Undelete"), QVariant::fromValue(rec));
344 menuPopup->AddButtonV(tr(
"Disable AutoExpire"),
345 QVariant::fromValue(rec));
346 menuPopup->AddButtonV(tr(
"No Change"), QVariant::fromValue(rec));
358 QString resultid = dce->GetId();
359 int buttonnum = dce->GetResult();
361 if (resultid ==
"JobDelete")
365 int jobID = dce->GetData().toInt();
371 else if (resultid ==
"JobRequeue")
375 int jobID = dce->GetData().toInt();
380 else if (resultid ==
"JobModify")
382 int jobID = dce->GetData().toInt();
390 else if (buttonnum == 1)
397 else if (resultid ==
"AutoExpireManage")
402 if (!rec || buttonnum == 2)
406 if ((buttonnum == 0) && rec->QueryIsDeleteCandidate())
411 LOG(VB_GENERAL, LOG_ERR, QString(
"Failed to delete recording: %1").arg(rec->GetTitle()));
416 else if (buttonnum == 1)
418 if ((rec)->GetRecordingGroup() ==
"Deleted")
426 if ((rec)->GetRecordingGroup() ==
"LiveTV")
454 QString helpmsg(tr(
"Listings Status shows the latest "
455 "status information from "
456 "mythfilldatabase"));
462 QDateTime mfdLastRunStart;
463 QDateTime mfdLastRunEnd;
464 QDateTime mfdNextRunStart;
465 QString mfdLastRunStatus;
467 QDateTime GuideDataThrough;
472 query.
prepare(
"SELECT max(endtime) FROM program WHERE manualid=0;");
486 AddLogLine(tr(
"Mythfrontend version: %1 (%2)")
490 AddLogLine(tr(
"Last mythfilldatabase guide update:"), helpmsg);
491 tmp = tr(
"Started: %1").arg(
496 if (mfdLastRunEnd >= mfdLastRunStart)
498 tmp = tr(
"Finished: %1")
505 AddLogLine(tr(
"Result: %1").arg(mfdLastRunStatus), helpmsg);
508 if (mfdNextRunStart >= mfdLastRunStart)
510 tmp = tr(
"Suggested Next: %1")
517 int DaysOfData = qdtNow.daysTo(GuideDataThrough);
519 if (GuideDataThrough.isNull())
521 AddLogLine(tr(
"There's no guide data available!"), helpmsg,
523 AddLogLine(tr(
"Have you run mythfilldatabase?"), helpmsg,
529 tr(
"There is guide data until %1")
534 AddLogLine(QString(
"(%1).").arg(tr(
"%n day(s)",
"", DaysOfData)),
539 AddLogLine(tr(
"WARNING: is mythfilldatabase running?"), helpmsg,
549 QString helpmsg(tr(
"Schedule Status shows current statistics "
550 "from the scheduler."));
558 query.
prepare(
"SELECT COUNT(*) FROM record WHERE type = :TEMPLATE");
562 QString rules = tr(
"%n template rule(s) (is) defined",
"",
563 query.
value(0).toInt());
572 query.
prepare(
"SELECT COUNT(*) FROM record "
573 "WHERE type <> :TEMPLATE AND search = :NOSEARCH");
578 QString rules = tr(
"%n standard rule(s) (is) defined",
"",
579 query.
value(0).toInt());
588 query.
prepare(
"SELECT COUNT(*) FROM record WHERE search > :NOSEARCH");
592 QString rules = tr(
"%n search rule(s) are defined",
"",
593 query.
value(0).toInt());
602 QMap<RecStatus::Type, int> statusMatch;
603 QMap<RecStatus::Type, QString> statusText;
604 QMap<int, int> sourceMatch;
605 QMap<int, QString> sourceText;
606 QMap<int, int> cardMatch;
607 QMap<int, QString> cardText;
608 QMap<int, int> cardParent;
609 QMap<int, bool> cardSchedGroup;
613 int lowerpriority = 0;
616 query.
prepare(
"SELECT MAX(sourceid) FROM videosource");
620 maxSource = query.
value(0).toInt();
623 query.
prepare(
"SELECT sourceid,name FROM videosource");
627 sourceText[query.
value(0).toInt()] = query.
value(1).toString();
630 query.
prepare(
"SELECT MAX(cardid) FROM capturecard");
634 maxCard = query.
value(0).toInt();
637 query.
prepare(
"SELECT cardid, inputname, displayname, parentid, "
644 int inputid = query.
value(0).toInt();
645 cardText[inputid] = query.
value(2).toString();
646 if (cardText[inputid].isEmpty())
647 cardText[inputid] = QString::number(query.
value(1).toInt());
648 cardParent[inputid] = query.
value(3).toInt();
649 cardSchedGroup[inputid] = query.
value(4).toBool();
656 tmpstr = tr(
"%n matching showing(s)",
"", schedList.
size());
659 for (
auto *s : schedList)
663 if (statusMatch[recstatus] < 1)
666 recstatus, s->GetRecordingRuleType());
669 ++statusMatch[recstatus];
677 ++sourceMatch[s->GetSourceID()];
678 int inputid = s->GetInputID();
681 if (cardParent[inputid] && cardSchedGroup[cardParent[inputid]])
682 inputid = cardParent[inputid];
683 ++cardMatch[inputid];
684 if (s->GetRecordingPriority2() < 0)
686 if (s->GetVideoProperties() & VID_HDTV)
692 #define ADD_STATUS_LOG_LINE(rtype, fstate) \
694 if (statusMatch[rtype] > 0) \
696 tmpstr = QString("%1 %2").arg(statusMatch[rtype]) \
697 .arg(statusText[rtype]); \
698 AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr, fstate);\
714 if (lowerpriority > 0)
716 tmpstr = QString(
"%1 %2 %3").arg(QString::number(lowerpriority),
717 willrec, tr(
"with lower priority"));
718 AddLogLine(tmpstr, helpmsg, tmpstr, tmpstr,
"warning");
722 tmpstr = QString(
"%1 %2 %3").arg(QString::number(hdflag),
723 willrec, tr(
"marked as HDTV"));
726 for (
int i = 1; i <= maxSource; ++i)
728 if (sourceMatch[i] > 0)
730 tmpstr = QString(
"%1 %2 %3 %4 \"%5\"")
731 .arg(QString::number(sourceMatch[i]), willrec,
732 tr(
"from source"), QString::number(i), sourceText[i]);
736 for (
int i = 1; i <= maxCard; ++i)
738 if (cardMatch[i] > 0)
740 tmpstr = QString(
"%1 %2 %3 %4 \"%5\"")
741 .arg(QString::number(cardMatch[i]), willrec,
742 tr(
"on input"), QString::number(i), cardText[i]);
753 bool m_schedgroup {
false};
754 QString m_displayname;
756 int m_unavailable {0};
761 QStringList m_recordings;
763 QMap<int, struct info> info;
770 QString helpmsg(tr(
"Input Status shows the current information "
771 "about the state of backend inputs"));
779 "SELECT cardid, parentid, schedgroup, displayname "
780 "FROM capturecard ORDER BY cardid");
790 int inputid = query.
value(0).toInt();
791 int parentid = query.
value(1).toInt();
795 int infoid = inputid;
796 if (parentid && info[parentid].m_schedgroup)
800 info[infoid].m_inputid = inputid;
801 info[infoid].m_schedgroup = query.
value(2).toBool();
802 info[infoid].m_displayname = query.
value(3).toString();
803 inputids.append(inputid);
806 QString cmd = QString(
"QUERY_REMOTEENCODER %1").arg(inputid);
807 QStringList strlist( cmd );
808 strlist <<
"GET_STATE";
811 int state = strlist[0].toInt();
816 strlist << QString(
"QUERY_REMOTEENCODER %1").arg(inputid);
817 strlist <<
"GET_SLEEPSTATUS";
820 int sleepState = strlist[0].toInt();
822 if (sleepState == -1)
823 info[infoid].m_errored += 1;
825 info[infoid].m_unavailable += 1;
827 info[infoid].m_sleeping += 1;
831 info[infoid].m_recording += 1;
833 info[infoid].m_livetv += 1;
835 info[infoid].m_available += 1;
841 strlist = QStringList( QString(
"QUERY_RECORDER %1").arg(inputid));
842 strlist <<
"GET_RECORDING";
847 QString titlesub = pginfo.
GetTitle();
850 info[infoid].m_recordings += titlesub;
855 for (
int inputid : qAsConst(inputids))
857 QStringList statuslist;
858 if (info[inputid].m_errored)
859 statuslist << tr(
"%1 errored").arg(info[inputid].m_errored);
860 if (info[inputid].m_unavailable)
861 statuslist << tr(
"%1 unavailable").arg(info[inputid].m_unavailable);
862 if (info[inputid].m_sleeping)
863 statuslist << tr(
"%1 sleeping").arg(info[inputid].m_sleeping);
864 if (info[inputid].m_recording)
865 statuslist << tr(
"%1 recording").arg(info[inputid].m_recording);
866 if (info[inputid].m_livetv)
867 statuslist << tr(
"%1 live television").arg(info[inputid].m_livetv);
868 if (info[inputid].m_available)
869 statuslist << tr(
"%1 available").arg(info[inputid].m_available);
872 if (info[inputid].m_errored)
874 else if (info[inputid].m_unavailable || info[inputid].m_sleeping)
875 fontstate =
"warning";
877 QString shortstatus = tr(
"Input %1 %2: %3")
878 .arg(QString::number(inputid), info[inputid].m_displayname,
879 statuslist.join(tr(
", ")));
880 QString longstatus = shortstatus +
"\n" +
881 info[inputid].m_recordings.join(
"\n");
883 AddLogLine(shortstatus, helpmsg, longstatus, longstatus, fontstate);
893 QString helpmsg(tr(
"Log Entries shows any unread log entries "
894 "from the system if you have logging enabled"));
901 query.
prepare(
"SELECT logid, module, priority, logdate, host, "
903 "FROM mythlog WHERE acknowledged = 0 "
904 "AND priority <= :PRIORITY ORDER BY logdate DESC;");
913 line = QString(
"%1").arg(query.
value(5).toString());
915 detail = tr(
"On %1 from %2.%3\n%4\n")
919 query.
value(4).toString(),
920 query.
value(1).toString(),
921 query.
value(5).toString());
923 QString
tmp = query.
value(6).toString();
927 detail.append(tr(
"No further details"));
930 "", query.
value(0).toString());
933 if (query.
size() == 0)
935 AddLogLine(tr(
"No items found at priority level %1 or lower.")
937 AddLogLine(tr(
"Use 1-8 to change priority level."), helpmsg);
948 QString helpmsg(tr(
"Job Queue shows any jobs currently in "
949 "MythTV's Job Queue such as a commercial "
956 QMap<int, JobQueueEntry> jobs;
957 QMap<int, JobQueueEntry>::Iterator it;
968 for (it = jobs.begin(); it != jobs.end(); ++it)
970 ProgramInfo pginfo((*it).chanid, (*it).recstartts);
975 detail = QString(
"%1\n%2 %3 @ %4\n%5 %6 %7 %8")
987 if ((*it).status != JOB_QUEUED)
988 detail +=
" (" + (*it).hostname +
')';
992 detail +=
'\n' + tr(
"Scheduled Run Time:") +
' ' +
999 detail +=
'\n' + (*it).comment;
1002 line = QString(
"%1 @ %2")
1009 if ((*it).status == JOB_ERRORED)
1011 else if ((*it).status == JOB_ABORTED)
1014 AddLogLine(line, helpmsg, detail, detail, font,
1015 QString(
"%1").arg((*it).id));
1019 AddLogLine(tr(
"Job Queue is currently empty."), helpmsg);
1029 QString ret = QObject::tr(
"Unknown");
1030 if (total > 0.0 && free > 0.0)
1032 double percent = (100.0*free)/total;
1033 ret = StatusBox::tr(
"%1 total, %2 used, %3 (or %4%) free.")
1037 .arg(percent, 0,
'f', (percent >= 10.0) ? 0 : 2);
1044 return usage_str_kb((
long long)(total*1024), (
long long)(used*1024),
1045 (
long long)(free*1024));
1049 long long used,
long long free,
1052 const QString tail = StatusBox::tr(
", using your %1 rate of %2 kb/s");
1059 for (
auto it = prof2bps.begin(); it != prof2bps.end(); ++it)
1062 tail.arg(it.key()).arg((
int)((
float)(*it) / 1024.0F));
1064 long long bytesPerMin = ((*it) >> 1) * 15LL;
1065 uint minLeft = ((free<<5)/bytesPerMin)<<5;
1066 minLeft = (minLeft/15)*15;
1067 uint hoursLeft = minLeft/60;
1068 QString hourstring = StatusBox::tr(
"%n hour(s)",
"", hoursLeft);
1069 QString minstring = StatusBox::tr(
"%n minute(s)",
"", minLeft%60);
1070 QString remainstring = StatusBox::tr(
"%1 remaining",
"time");
1071 if (minLeft%60 == 0)
1072 out<<remainstring.arg(hourstring) + pro;
1073 else if (minLeft > 60)
1075 out<<StatusBox::tr(
"%1 and %2 remaining",
"time")
1076 .arg(hourstring, minstring) + pro;
1080 out<<remainstring.arg(minstring) + pro;
1087 QString str =
" " + StatusBox::tr(
"Uptime") +
": ";
1090 return str + StatusBox::tr(
"unknown",
"unknown uptime");
1092 auto days = duration_cast<std::chrono::days>(uptime);
1093 auto secs = uptime % 24h;
1096 if (
days.count() > 0)
1098 astext = QString(
"%1, %2")
1099 .arg(StatusBox::tr(
"%n day(s)",
"",
days.count()),
1104 return str + astext;
1118 "SELECT sum(filesize) * 8 / "
1119 "sum(((unix_timestamp(endtime) - unix_timestamp(starttime)))) "
1121 "FROM recorded WHERE hostname in (%1) "
1122 "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
1124 query.
prepare(querystr.arg(hostnames));
1126 if (query.
exec() && query.
next() &&
1127 query.
value(0).toDouble() > 0)
1129 QString rateStr = tr(
"average",
"average rate");
1134 (int)(query.
value(0).toDouble());
1138 "SELECT max(filesize * 8 / "
1139 "(unix_timestamp(endtime) - unix_timestamp(starttime))) "
1141 "FROM recorded WHERE hostname in (%1) "
1142 "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
1144 query.
prepare(querystr.arg(hostnames));
1146 if (query.
exec() && query.
next() &&
1147 query.
value(0).toDouble() > 0)
1149 QString rateStr = tr(
"maximum",
"maximum rate");
1154 (int)(query.
value(0).toDouble());
1171 QString machineStr = tr(
"Machine Status shows some operating system "
1172 "statistics of this machine and the MythTV "
1182 line = tr(
"System:");
1184 line = tr(
"This machine:");
1191 Item->SetText(
" " + tr(
"System time") +
": " + QDateTime::currentDateTime().toString());
1193 UpdateTime(timebox);
1199 AddLogLine(
" " + tr(
"OS") + QString(
": %1 (%2)").arg(QSysInfo::prettyProductName(),
1200 QSysInfo::currentCpuArchitecture()));
1201 AddLogLine(
" " + tr(
"Qt version") + QString(
": %1").arg(qVersion()));
1203 QList allInterfaces = QNetworkInterface::allInterfaces();
1204 for (
const QNetworkInterface & iface : qAsConst(allInterfaces))
1206 QNetworkInterface::InterfaceFlags f = iface.flags();
1207 if (!(f & QNetworkInterface::IsUp))
1209 if (!(f & QNetworkInterface::IsRunning))
1211 if ((f & QNetworkInterface::IsLoopBack) != 0U)
1214 QNetworkInterface::InterfaceType
type = iface.type();
1215 QString name =
type == QNetworkInterface::Wifi ? tr(
"WiFi") : tr(
"Ethernet");
1216 AddLogLine(
" " + name + QString(
" (%1): ").arg(iface.humanReadableName()));
1217 AddLogLine(
" " + tr(
"MAC Address") +
": " + iface.hardwareAddress());
1218 QList addresses = iface.addressEntries();
1219 for (
const QNetworkAddressEntry & addr : qAsConst(addresses))
1221 if (addr.ip().protocol() == QAbstractSocket::IPv4Protocol ||
1222 addr.ip().protocol() == QAbstractSocket::IPv6Protocol)
1224 AddLogLine(
" " + tr(
"IP Address") +
": " + addr.ip().toString());
1231 std::chrono::seconds uptime = 0s;
1236 std::chrono::seconds time = 0s;
1242 uptimeitem->
Start(1min);
1246 #if !defined(_WIN32) && !defined(Q_OS_ANDROID)
1250 Item->SetText(QString(
" %1: %2 %3 %4").arg(tr(
"Load")).arg(loads[0], 1,
'f', 2)
1251 .arg(loads[1], 1,
'f', 2).arg(loads[2], 1,
'f', 2));
1254 UpdateLoad(loaditem);
1273 Item->SetText(QString(
" " + tr(
"RAM") +
": " +
usage_str_mb(totm, totm - freem, freem)));
1283 Item->SetText(QString(
" " + tr(
"Swap") +
": " +
usage_str_mb(tots, tots - frees, frees)));
1297 line = tr(
"MythTV server") +
':';
1310 std::chrono::seconds time = 0s;
1316 remoteuptime->
Start(1min);
1327 Item->SetText(QString(
" %1: %2 %3 %4").arg(tr(
"Load")).arg(loads[0], 1,
'f', 2)
1328 .arg(loads[1], 1,
'f', 2).arg(loads[2], 1,
'f', 2));
1331 UpdateRemoteLoad(remoteloaditem);
1333 remoteloaditem->
Start();
1346 Item->SetText(QString(
" " + tr(
"RAM") +
": " +
usage_str_mb(totm, totm - freem, freem)));
1356 Item->SetText(QString(
" " + tr(
"Swap") +
": " +
usage_str_mb(tots, tots - frees, frees)));
1360 UpdateRemoteMem(rmem);
1361 UpdateRemoteSwap(rswap);
1373 for (
int i = 0; i < fsInfos.size(); ++i)
1376 if ((fsInfos.size() == 2) && (i == 0) &&
1377 (fsInfos[i].getPath() !=
"TotalDiskSpace") &&
1378 (fsInfos[i+1].getPath() ==
"TotalDiskSpace"))
1381 hostnames = QString(
"\"%1\"").arg(fsInfos[i].getHostname());
1382 hostnames.replace(
' ',
"");
1383 hostnames.replace(
',',
"\",\"");
1389 fsInfos[i].getTotalSpace(), fsInfos[i].getUsedSpace(),
1390 fsInfos[i].getTotalSpace() - fsInfos[i].getUsedSpace(),
1393 if (fsInfos[i].getPath() ==
"TotalDiskSpace")
1395 line = tr(
"Total Disk Space:");
1400 line = tr(
"MythTV Drive #%1:").arg(fsInfos[i].getFSysID());
1403 QStringList tokens = fsInfos[i].getPath().split(
',');
1405 if (tokens.size() > 1)
1407 AddLogLine(QString(
" ") + tr(
"Directories:"), machineStr);
1410 while (curToken < tokens.size())
1412 tokens[curToken++], machineStr);
1416 AddLogLine(QString(
" " ) + tr(
"Directory:") +
' ' +
1417 fsInfos[i].getPath(), machineStr);
1421 for (
auto & diskinfo : list)
1423 line = QString(
" ") + diskinfo;
1435 QString displayhelp = tr(
"Available hardware decoders for video playback.");
1442 if (decoders.isEmpty())
1448 for (
const QString & decoder : qAsConst(decoders))
1458 auto displayhelp = tr(
"Display information.");
1465 for (
const auto & line : qAsConst(desc))
1474 auto displayhelp = tr(
"Render information.");
1489 uint64_t swapcount = 0;
1492 swapcount = gl->GetSwapCount();
1493 Item->SetText(tr(
"Current fps\t: %1").arg(swapcount));
1498 (void)opengl->GetSwapCount();
1504 if (opengl && (opengl->GetExtraFeatures() &
kGLNVMemory))
1506 auto GetGPUMem = []()
1510 return gl->GetGPUMemory();
1511 return std::tuple<int,int,int> { 0, 0, 0 };
1515 auto mem = GetGPUMem();
1516 int total = std::get<0>(mem);
1519 int avail = std::get<2>(mem);
1520 Item->SetText(tr(
"GPU memory used : %1MB").arg(total - avail));
1526 auto mem = GetGPUMem();
1527 int total = std::get<0>(mem);
1530 int avail = std::get<2>(mem);
1531 int percent =
static_cast<int>((avail /
static_cast<float>(total) * 100.0F));
1532 Item->SetText(tr(
"GPU memory free : %1MB (or %2%)").arg(avail).arg(percent));
1543 UpdateFree(freemem);
1550 auto desc = render->GetDescription();
1551 for (
const auto & line : qAsConst(desc))
1565 QString helpmsg(tr(
"The AutoExpire List shows all recordings "
1566 "which may be expired and the order of "
1567 "their expiration. Recordings at the top "
1568 "of the list will be expired first."));
1574 QString contentLine;
1577 long long totalSize(0);
1578 long long liveTVSize(0);
1580 long long deletedGroupSize(0);
1581 int deletedGroupCount(0);
1583 std::vector<ProgramInfo *>::iterator it;
1607 deletedGroupCount++;
1611 staticInfo = tr(
"%n recording(s) consuming %1 (is) allowed to expire\n",
"",
1615 staticInfo += tr(
"%n (is) LiveTV and consume(s) %1\n",
"", liveTVCount)
1618 if (deletedGroupCount)
1620 staticInfo += tr(
"%n (is) Deleted and consume(s) %1\n",
"",
1637 contentLine += pginfo->
GetTitle() +
1653 AddLogLine(contentLine, staticInfo, detailInfo,
1654 staticInfo + detailInfo);