00001 #include <qlayout.h>
00002 #include <qiconview.h>
00003 #include <qsqldatabase.h>
00004 #include <qwidgetstack.h>
00005 #include <qvbox.h>
00006 #include <qgrid.h>
00007 #include <qregexp.h>
00008 #include <qhostaddress.h>
00009
00010 #include <unistd.h>
00011 #include <stdlib.h>
00012
00013 #include <iostream>
00014 #include <cerrno>
00015 using namespace std;
00016
00017 #include "config.h"
00018 #include "statusbox.h"
00019 #include "mythcontext.h"
00020 #include "remoteutil.h"
00021 #include "programinfo.h"
00022 #include "tv.h"
00023 #include "jobqueue.h"
00024 #include "util.h"
00025 #include "mythdbcon.h"
00026 #include "cardutil.h"
00027
00028 #define REC_CAN_BE_DELETED(rec) \
00029 ((((rec)->programflags & FL_INUSEPLAYING) == 0) && \
00030 ((((rec)->programflags & FL_INUSERECORDING) == 0) || \
00031 ((rec)->recgroup != "LiveTV")))
00032
00033
00043 StatusBox::StatusBox(MythMainWindow *parent, const char *name)
00044 : MythDialog(parent, name), errored(false)
00045 {
00046
00047
00048 int item_count = 0;
00049 dateFormat = gContext->GetSetting("ShortDateFormat", "M/d");
00050 timeFormat = gContext->GetSetting("TimeFormat", "h:mm AP");
00051 timeDateFormat = timeFormat + " " + dateFormat;
00052
00053 setNoErase();
00054 LoadTheme();
00055 if (IsErrored())
00056 return;
00057
00058 updateBackground();
00059
00060 icon_list->SetItemText(item_count++, QObject::tr("Listings Status"));
00061 icon_list->SetItemText(item_count++, QObject::tr("Schedule Status"));
00062 icon_list->SetItemText(item_count++, QObject::tr("Tuner Status"));
00063 icon_list->SetItemText(item_count++, QObject::tr("Log Entries"));
00064 icon_list->SetItemText(item_count++, QObject::tr("Job Queue"));
00065 icon_list->SetItemText(item_count++, QObject::tr("Machine Status"));
00066 icon_list->SetItemText(item_count++, QObject::tr("AutoExpire List"));
00067 itemCurrent = gContext->GetNumSetting("StatusBoxItemCurrent", 0);
00068 icon_list->SetItemCurrent(itemCurrent);
00069 icon_list->SetActive(true);
00070
00071 QStringList strlist;
00072 strlist << "QUERY_IS_ACTIVE_BACKEND";
00073 strlist << gContext->GetHostName();
00074
00075 gContext->SendReceiveStringList(strlist);
00076
00077 if (QString(strlist[0]) == "FALSE")
00078 isBackend = false;
00079 else if (QString(strlist[0]) == "TRUE")
00080 isBackend = true;
00081 else
00082 isBackend = false;
00083
00084 VERBOSE(VB_NETWORK, QString("QUERY_IS_ACTIVE_BACKEND=%1").arg(strlist[0]));
00085
00086 max_icons = item_count;
00087 inContent = false;
00088 doScroll = false;
00089 contentPos = 0;
00090 contentTotalLines = 0;
00091 contentSize = 0;
00092 contentMid = 0;
00093 min_level = gContext->GetNumSetting("LogDefaultView",5);
00094 my_parent = parent;
00095 clicked();
00096
00097 gContext->addCurrentLocation("StatusBox");
00098 }
00099
00100 StatusBox::~StatusBox(void)
00101 {
00102 gContext->SaveSetting("StatusBoxItemCurrent", itemCurrent);
00103 gContext->removeCurrentLocation();
00104 }
00105
00106 void StatusBox::paintEvent(QPaintEvent *e)
00107 {
00108 QRect r = e->rect();
00109
00110 if (r.intersects(TopRect))
00111 updateTopBar();
00112 if (r.intersects(SelectRect))
00113 updateSelector();
00114 if (r.intersects(ContentRect))
00115 updateContent();
00116 }
00117
00118 void StatusBox::updateBackground(void)
00119 {
00120 QPixmap bground(size());
00121 bground.fill(this, 0, 0);
00122
00123 QPainter tmp(&bground);
00124
00125 LayerSet *container = theme->GetSet("background");
00126 if (container)
00127 {
00128 container->Draw(&tmp, 0, 0);
00129 }
00130
00131 tmp.end();
00132 m_background = bground;
00133
00134 setPaletteBackgroundPixmap(m_background);
00135 }
00136
00137 void StatusBox::updateContent()
00138 {
00139 QRect pr = ContentRect;
00140 QPixmap pix(pr.size());
00141 pix.fill(this, pr.topLeft());
00142 QPainter tmp(&pix);
00143 QPainter p(this);
00144
00145
00146 contentSize = list_area->GetItems();
00147 if (contentSize > contentTotalLines)
00148 contentSize = contentTotalLines;
00149 contentMid = contentSize / 2;
00150
00151 int startPos = 0;
00152 int highlightPos = 0;
00153
00154 if (contentPos < contentMid)
00155 {
00156 startPos = 0;
00157 highlightPos = contentPos;
00158 }
00159 else if (contentPos >= (contentTotalLines - contentMid))
00160 {
00161 startPos = contentTotalLines - contentSize;
00162 highlightPos = contentSize - (contentTotalLines - contentPos);
00163 }
00164 else if (contentPos >= contentMid)
00165 {
00166 startPos = contentPos - contentMid;
00167 highlightPos = contentMid;
00168 }
00169
00170 if (content == NULL) return;
00171 LayerSet *container = content;
00172
00173 list_area->ResetList();
00174 for (int x = startPos; (x - startPos) <= contentSize; x++)
00175 {
00176 if (contentLines.contains(x))
00177 {
00178 list_area->SetItemText(x - startPos, contentLines[x]);
00179 if (contentFont.contains(x))
00180 list_area->EnableForcedFont(x - startPos, contentFont[x]);
00181 }
00182 }
00183
00184 list_area->SetItemCurrent(highlightPos);
00185
00186 if (inContent)
00187 {
00188 helptext->SetText(contentDetail[contentPos]);
00189 update(TopRect);
00190 }
00191
00192 list_area->SetUpArrow((startPos > 0) && (contentSize < contentTotalLines));
00193 list_area->SetDownArrow((startPos + contentSize) < contentTotalLines);
00194
00195 container->Draw(&tmp, 0, 0);
00196 container->Draw(&tmp, 1, 0);
00197 container->Draw(&tmp, 2, 0);
00198 container->Draw(&tmp, 3, 0);
00199 container->Draw(&tmp, 4, 0);
00200 container->Draw(&tmp, 5, 0);
00201 container->Draw(&tmp, 6, 0);
00202 container->Draw(&tmp, 7, 0);
00203 container->Draw(&tmp, 8, 0);
00204 tmp.end();
00205 p.drawPixmap(pr.topLeft(), pix);
00206 }
00207
00208 void StatusBox::updateSelector()
00209 {
00210 QRect pr = SelectRect;
00211 QPixmap pix(pr.size());
00212 pix.fill(this, pr.topLeft());
00213 QPainter tmp(&pix);
00214 QPainter p(this);
00215
00216 if (selector == NULL) return;
00217 LayerSet *container = selector;
00218
00219 container->Draw(&tmp, 0, 0);
00220 container->Draw(&tmp, 1, 0);
00221 container->Draw(&tmp, 2, 0);
00222 container->Draw(&tmp, 3, 0);
00223 container->Draw(&tmp, 4, 0);
00224 container->Draw(&tmp, 5, 0);
00225 container->Draw(&tmp, 6, 0);
00226 container->Draw(&tmp, 7, 0);
00227 container->Draw(&tmp, 8, 0);
00228 tmp.end();
00229 p.drawPixmap(pr.topLeft(), pix);
00230 }
00231
00232 void StatusBox::updateTopBar()
00233 {
00234 QRect pr = TopRect;
00235 QPixmap pix(pr.size());
00236 pix.fill(this, pr.topLeft());
00237 QPainter tmp(&pix);
00238 QPainter p(this);
00239
00240 if (topbar == NULL) return;
00241 LayerSet *container = topbar;
00242
00243 container->Draw(&tmp, 0, 0);
00244 tmp.end();
00245 p.drawPixmap(pr.topLeft(), pix);
00246 }
00247
00248 void StatusBox::LoadTheme()
00249 {
00250 int screenheight = 0, screenwidth = 0;
00251 float wmult = 0, hmult = 0;
00252
00253 gContext->GetScreenSettings(screenwidth, wmult, screenheight, hmult);
00254
00255 theme = new XMLParse();
00256 theme->SetWMult(wmult);
00257 theme->SetHMult(hmult);
00258 if (!theme->LoadTheme(xmldata, "status", "status-"))
00259 {
00260 VERBOSE(VB_IMPORTANT, "StatusBox: Unable to load theme.");
00261 errored = true;
00262 return;
00263 }
00264
00265 for (QDomNode child = xmldata.firstChild(); !child.isNull();
00266 child = child.nextSibling()) {
00267
00268 QDomElement e = child.toElement();
00269 if (!e.isNull()) {
00270 if (e.tagName() == "font") {
00271 theme->parseFont(e);
00272 }
00273 else if (e.tagName() == "container") {
00274 QRect area;
00275 QString name;
00276 int context;
00277 theme->parseContainer(e, name, context, area);
00278
00279 if (name.lower() == "topbar")
00280 TopRect = area;
00281 if (name.lower() == "selector")
00282 SelectRect = area;
00283 if (name.lower() == "content")
00284 ContentRect = area;
00285 }
00286 else {
00287 QString msg =
00288 QString(tr("The theme you are using contains an "
00289 "unknown element ('%1'). It will be ignored"))
00290 .arg(e.tagName());
00291 VERBOSE(VB_IMPORTANT, msg);
00292 errored = true;
00293 }
00294 }
00295 }
00296
00297 selector = theme->GetSet("selector");
00298 if (!selector)
00299 {
00300 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get selector container.");
00301 errored = true;
00302 }
00303
00304 icon_list = (UIListType*)selector->GetType("icon_list");
00305 if (!icon_list)
00306 {
00307 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get icon list area.");
00308 errored = true;
00309 }
00310
00311 content = theme->GetSet("content");
00312 if (!content)
00313 {
00314 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get content container.");
00315 errored = true;
00316 }
00317
00318 list_area = (UIListType*)content->GetType("list_area");
00319 if (!list_area)
00320 {
00321 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get list area.");
00322 errored = true;
00323 }
00324
00325 topbar = theme->GetSet("topbar");
00326 if (!topbar)
00327 {
00328 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get topbar container.");
00329 errored = true;
00330 }
00331
00332 helptext = (UITextType*)topbar->GetType("helptext");
00333 if (!helptext)
00334 {
00335 VERBOSE(VB_IMPORTANT, "StatusBox: Failed to get helptext area.");
00336 errored = true;
00337 }
00338 }
00339
00340 void StatusBox::keyPressEvent(QKeyEvent *e)
00341 {
00342 bool handled = false;
00343 QStringList actions;
00344 gContext->GetMainWindow()->TranslateKeyPress("Status", e, actions);
00345
00346 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00347 {
00348 QString action = actions[i];
00349 QString currentItem;
00350 QRegExp logNumberKeys( "^[12345678]$" );
00351
00352 currentItem = icon_list->GetItemText(icon_list->GetCurrentItem());
00353 handled = true;
00354
00355 if (action == "SELECT")
00356 {
00357 clicked();
00358 }
00359 else if (action == "MENU")
00360 {
00361 if ((inContent) &&
00362 (currentItem == QObject::tr("Log Entries")))
00363 {
00364 DialogCode retval = MythPopupBox::Show2ButtonPopup(
00365 my_parent, QString("AckLogEntry"),
00366 QObject::tr("Acknowledge all log entries at "
00367 "this priority level or lower?"),
00368 QObject::tr("Yes"), QObject::tr("No"),
00369 kDialogCodeButton0);
00370
00371 if (kDialogCodeButton0 == retval)
00372 {
00373 MSqlQuery query(MSqlQuery::InitCon());
00374 query.prepare("UPDATE mythlog SET acknowledged = 1 "
00375 "WHERE priority <= :PRIORITY ;");
00376 query.bindValue(":PRIORITY", min_level);
00377 query.exec();
00378 doLogEntries();
00379 }
00380 }
00381 else if ((inContent) &&
00382 (currentItem == QObject::tr("Job Queue")))
00383 {
00384 clicked();
00385 }
00386 }
00387 else if (action == "UP")
00388 {
00389 if (inContent)
00390 {
00391 if (contentPos > 0)
00392 contentPos--;
00393 update(ContentRect);
00394 }
00395 else
00396 {
00397 if (icon_list->GetCurrentItem() > 0)
00398 itemCurrent = icon_list->GetCurrentItem()-1;
00399 else
00400 itemCurrent = max_icons - 1;
00401 icon_list->SetItemCurrent(itemCurrent);
00402 clicked();
00403 setHelpText();
00404 update(SelectRect);
00405 }
00406
00407 }
00408 else if (action == "DOWN")
00409 {
00410 if (inContent)
00411 {
00412 if (contentPos < (contentTotalLines - 1))
00413 contentPos++;
00414 update(ContentRect);
00415 }
00416 else
00417 {
00418 if (icon_list->GetCurrentItem() < (max_icons - 1))
00419 itemCurrent = icon_list->GetCurrentItem()+1;
00420 else
00421 itemCurrent = 0;
00422 icon_list->SetItemCurrent(itemCurrent);
00423 clicked();
00424 setHelpText();
00425 update(SelectRect);
00426 }
00427 }
00428 else if (action == "PAGEUP" && inContent)
00429 {
00430 contentPos -= contentSize;
00431 if (contentPos < 0)
00432 contentPos = 0;
00433 update(ContentRect);
00434 }
00435 else if (action == "PAGEDOWN" && inContent)
00436 {
00437 contentPos += contentSize;
00438 if (contentPos > (contentTotalLines - 1))
00439 contentPos = contentTotalLines - 1;
00440 update(ContentRect);
00441 }
00442 else if ((action == "RIGHT") &&
00443 (!inContent) &&
00444 (((contentSize > 0) &&
00445 (contentTotalLines > contentSize)) ||
00446 (doScroll)))
00447 {
00448 clicked();
00449 inContent = true;
00450 contentPos = 0;
00451 icon_list->SetActive(false);
00452 list_area->SetActive(true);
00453 update(SelectRect);
00454 update(ContentRect);
00455 }
00456 else if (action == "LEFT")
00457 {
00458 if (inContent)
00459 {
00460 inContent = false;
00461 contentPos = 0;
00462 list_area->SetActive(false);
00463 icon_list->SetActive(true);
00464 setHelpText();
00465 update(SelectRect);
00466 update(ContentRect);
00467 }
00468 else
00469 {
00470 if (gContext->GetNumSetting("UseArrowAccels", 1))
00471 accept();
00472 }
00473 }
00474 else if ((currentItem == QObject::tr("Log Entries")) &&
00475 (logNumberKeys.search(action) == 0))
00476 {
00477 min_level = action.toInt();
00478 helptext->SetText(QObject::tr("Setting priority level to %1")
00479 .arg(min_level));
00480 update(TopRect);
00481 doLogEntries();
00482 }
00483 else
00484 handled = false;
00485 }
00486
00487 if (!handled)
00488 MythDialog::keyPressEvent(e);
00489 }
00490
00491 void StatusBox::setHelpText()
00492 {
00493 if (inContent)
00494 {
00495 helptext->SetText(contentDetail[contentPos]);
00496 } else {
00497 topbar->ClearAllText();
00498 QString currentItem;
00499
00500 currentItem = icon_list->GetItemText(icon_list->GetCurrentItem());
00501
00502 if (currentItem == QObject::tr("Listings Status"))
00503 helptext->SetText(QObject::tr("Listings Status shows the latest "
00504 "status information from "
00505 "mythfilldatabase"));
00506
00507 if (currentItem == QObject::tr("Schedule Status"))
00508 helptext->SetText(QObject::tr("Schedule Status shows current "
00509 "statistics from the scheduler."));
00510
00511 if (currentItem == QObject::tr("Tuner Status"))
00512 helptext->SetText(QObject::tr("Tuner Status shows the current "
00513 "information about the state of "
00514 "backend tuner cards"));
00515
00516 if (currentItem == QObject::tr("DVB Status"))
00517 helptext->SetText(QObject::tr("DVB Status shows the quality "
00518 "statistics of all DVB cards, if "
00519 "present"));
00520
00521 if (currentItem == QObject::tr("Log Entries"))
00522 helptext->SetText(QObject::tr("Log Entries shows any unread log "
00523 "entries from the system if you "
00524 "have logging enabled"));
00525 if (currentItem == QObject::tr("Job Queue"))
00526 helptext->SetText(QObject::tr("Job Queue shows any jobs currently "
00527 "in Myth's Job Queue such as a "
00528 "commercial flagging job."));
00529 if (currentItem == QObject::tr("Machine Status"))
00530 {
00531 QString machineStr = QObject::tr("Machine Status shows "
00532 "some operating system "
00533 "statistics of this machine");
00534 if (!isBackend)
00535 machineStr.append(" " + QObject::tr("and the MythTV server"));
00536
00537 helptext->SetText(machineStr);
00538 }
00539
00540 if (currentItem == QObject::tr("AutoExpire List"))
00541 helptext->SetText(QObject::tr("The AutoExpire List shows all "
00542 "recordings which may be expired and the order of their "
00543 "expiration. Recordings at the top of the list will be "
00544 "expired first."));
00545 }
00546 update(TopRect);
00547 }
00548
00549 void StatusBox::clicked()
00550 {
00551 QString currentItem = icon_list->GetItemText(icon_list->GetCurrentItem());
00552
00553 if (inContent)
00554 {
00555 if (currentItem == QObject::tr("Log Entries"))
00556 {
00557 DialogCode retval = MythPopupBox::Show2ButtonPopup(
00558 my_parent,
00559 QString("AckLogEntry"),
00560 QObject::tr("Acknowledge this log entry?"),
00561 QObject::tr("Yes"), QObject::tr("No"), kDialogCodeButton0);
00562
00563 if (kDialogCodeButton0 == retval)
00564 {
00565 MSqlQuery query(MSqlQuery::InitCon());
00566 query.prepare("UPDATE mythlog SET acknowledged = 1 "
00567 "WHERE logid = :LOGID ;");
00568 query.bindValue(":LOGID", contentData[contentPos]);
00569 query.exec();
00570 doLogEntries();
00571 }
00572 }
00573 else if (currentItem == QObject::tr("Job Queue"))
00574 {
00575 QStringList msgs;
00576 int jobStatus;
00577
00578 jobStatus = JobQueue::GetJobStatus(
00579 contentData[contentPos].toInt());
00580
00581 if (jobStatus == JOB_QUEUED)
00582 {
00583 DialogCode retval = MythPopupBox::Show2ButtonPopup(
00584 my_parent,
00585 QString("JobQueuePopup"), QObject::tr("Delete Job?"),
00586 QObject::tr("Yes"), QObject::tr("No"), kDialogCodeButton1);
00587 if (kDialogCodeButton0 == retval)
00588 {
00589 JobQueue::DeleteJob(contentData[contentPos].toInt());
00590 doJobQueueStatus();
00591 }
00592 }
00593 else if ((jobStatus == JOB_PENDING) ||
00594 (jobStatus == JOB_STARTING) ||
00595 (jobStatus == JOB_RUNNING))
00596 {
00597 msgs << QObject::tr("Pause");
00598 msgs << QObject::tr("Stop");
00599 msgs << QObject::tr("No Change");
00600 DialogCode retval = MythPopupBox::ShowButtonPopup(
00601 my_parent,
00602 QString("JobQueuePopup"),
00603 QObject::tr("Job Queue Actions:"),
00604 msgs, kDialogCodeButton2);
00605 if (kDialogCodeButton0 == retval)
00606 {
00607 JobQueue::PauseJob(contentData[contentPos].toInt());
00608 doJobQueueStatus();
00609 }
00610 else if (kDialogCodeButton1 == retval)
00611 {
00612 JobQueue::StopJob(contentData[contentPos].toInt());
00613 doJobQueueStatus();
00614 }
00615 }
00616 else if (jobStatus == JOB_PAUSED)
00617 {
00618 msgs << QObject::tr("Resume");
00619 msgs << QObject::tr("Stop");
00620 msgs << QObject::tr("No Change");
00621 DialogCode retval = MythPopupBox::ShowButtonPopup(
00622 my_parent,
00623 QString("JobQueuePopup"),
00624 QObject::tr("Job Queue Actions:"),
00625 msgs, kDialogCodeButton2);
00626
00627 if (kDialogCodeButton0 == retval)
00628 {
00629 JobQueue::ResumeJob(contentData[contentPos].toInt());
00630 doJobQueueStatus();
00631 }
00632 else if (kDialogCodeButton1 == retval)
00633 {
00634 JobQueue::StopJob(contentData[contentPos].toInt());
00635 doJobQueueStatus();
00636 }
00637 }
00638 else if (jobStatus & JOB_DONE)
00639 {
00640 DialogCode retval = MythPopupBox::Show2ButtonPopup(
00641 my_parent,
00642 QString("JobQueuePopup"),
00643 QObject::tr("Requeue Job?"),
00644 QObject::tr("Yes"), QObject::tr("No"), kDialogCodeButton0);
00645
00646 if (kDialogCodeButton0 == retval)
00647 {
00648 JobQueue::ChangeJobStatus(contentData[contentPos].toInt(),
00649 JOB_QUEUED);
00650 doJobQueueStatus();
00651 }
00652 }
00653 }
00654 else if (currentItem == QObject::tr("AutoExpire List"))
00655 {
00656 ProgramInfo* rec;
00657
00658 rec = expList[contentPos];
00659
00660 if (rec)
00661 {
00662 QStringList msgs;
00663
00664 msgs << QObject::tr("Delete Now");
00665 if ((rec)->recgroup == "LiveTV")
00666 msgs << QObject::tr("Move to Default group");
00667 else if ((rec)->recgroup == "Deleted")
00668 msgs << QObject::tr("Undelete");
00669 else
00670 msgs << QObject::tr("Disable AutoExpire");
00671 msgs << QObject::tr("No Change");
00672
00673 DialogCode retval = MythPopupBox::ShowButtonPopup(
00674 my_parent,
00675 QString("AutoExpirePopup"),
00676 QObject::tr("AutoExpire Actions:"),
00677 msgs, kDialogCodeButton2);
00678
00679 if ((kDialogCodeButton0 == retval) && REC_CAN_BE_DELETED(rec))
00680 {
00681 RemoteDeleteRecording(rec, false, false);
00682 }
00683 else if (kDialogCodeButton1 == retval)
00684 {
00685 if ((rec)->recgroup == "Deleted")
00686 RemoteUndeleteRecording(rec);
00687 else
00688 {
00689 rec->SetAutoExpire(0);
00690
00691 if ((rec)->recgroup == "LiveTV")
00692 rec->ApplyRecordRecGroupChange("Default");
00693 }
00694 }
00695
00696
00697 doAutoExpireList();
00698 if (contentPos >= (int)expList.size())
00699 contentPos = max((int)expList.size()-1,0);
00700 }
00701 }
00702 return;
00703 }
00704
00705
00706
00707 content->ClearAllText();
00708 list_area->ResetList();
00709 contentLines.clear();
00710 contentDetail.clear();
00711 contentFont.clear();
00712 contentData.clear();
00713
00714 if (currentItem == QObject::tr("Listings Status"))
00715 doListingsStatus();
00716 else if (currentItem == QObject::tr("Schedule Status"))
00717 doScheduleStatus();
00718 else if (currentItem == QObject::tr("Tuner Status"))
00719 doTunerStatus();
00720 else if (currentItem == QObject::tr("Log Entries"))
00721 doLogEntries();
00722 else if (currentItem == QObject::tr("Job Queue"))
00723 doJobQueueStatus();
00724 else if (currentItem == QObject::tr("Machine Status"))
00725 doMachineStatus();
00726 else if (currentItem == QObject::tr("AutoExpire List"))
00727 doAutoExpireList();
00728 }
00729
00730 void StatusBox::doListingsStatus()
00731 {
00732 QString mfdLastRunStart, mfdLastRunEnd, mfdLastRunStatus, mfdNextRunStart;
00733 QString querytext, Status, DataDirectMessage;
00734 int DaysOfData;
00735 QDateTime qdtNow, GuideDataThrough;
00736 int count = 0;
00737
00738 contentLines.clear();
00739 contentDetail.clear();
00740 contentFont.clear();
00741 doScroll = false;
00742
00743 qdtNow = QDateTime::currentDateTime();
00744
00745 MSqlQuery query(MSqlQuery::InitCon());
00746 query.prepare("SELECT max(endtime) FROM program WHERE manualid=0;");
00747 query.exec();
00748
00749 if (query.isActive() && query.size())
00750 {
00751 query.next();
00752 GuideDataThrough = QDateTime::fromString(query.value(0).toString(),
00753 Qt::ISODate);
00754 }
00755
00756 mfdLastRunStart = gContext->GetSetting("mythfilldatabaseLastRunStart");
00757 mfdLastRunEnd = gContext->GetSetting("mythfilldatabaseLastRunEnd");
00758 mfdLastRunStatus = gContext->GetSetting("mythfilldatabaseLastRunStatus");
00759 mfdNextRunStart = gContext->GetSetting("MythFillSuggestedRunTime");
00760 DataDirectMessage = gContext->GetSetting("DataDirectMessage");
00761
00762 mfdNextRunStart.replace("T", " ");
00763
00764 extern const char *myth_source_version;
00765 contentLines[count++] = QObject::tr("Myth version:") + " " +
00766 MYTH_BINARY_VERSION + " " +
00767 myth_source_version;
00768 contentLines[count++] = QObject::tr("Last mythfilldatabase guide update:");
00769 contentLines[count++] = QObject::tr("Started: ") + mfdLastRunStart;
00770
00771 if (mfdLastRunEnd >= mfdLastRunStart)
00772 contentLines[count++] = QObject::tr("Finished: ") + mfdLastRunEnd;
00773
00774 contentLines[count++] = QObject::tr("Result: ") + mfdLastRunStatus;
00775
00776
00777 if (mfdNextRunStart >= mfdLastRunStart)
00778 contentLines[count++] = QObject::tr("Suggested Next: ") +
00779 mfdNextRunStart;
00780
00781 DaysOfData = qdtNow.daysTo(GuideDataThrough);
00782
00783 if (GuideDataThrough.isNull())
00784 {
00785 contentLines[count++] = "";
00786 contentLines[count++] = QObject::tr("There's no guide data available!");
00787 contentLines[count++] = QObject::tr("Have you run mythfilldatabase?");
00788 }
00789 else
00790 {
00791 contentLines[count++] = QObject::tr("There is guide data until ") +
00792 QDateTime(GuideDataThrough)
00793 .toString("yyyy-MM-dd hh:mm");
00794
00795 if (DaysOfData > 0)
00796 {
00797 Status = QString("(%1 ").arg(DaysOfData);
00798 if (DaysOfData >1)
00799 Status += QObject::tr("days");
00800 else
00801 Status += QObject::tr("day");
00802 Status += ").";
00803 contentLines[count++] = Status;
00804 }
00805 }
00806
00807 if (DaysOfData <= 3)
00808 {
00809 contentLines[count++] = QObject::tr("WARNING: is mythfilldatabase "
00810 "running?");
00811 }
00812
00813 if (!DataDirectMessage.isNull())
00814 {
00815 contentLines[count++] = QObject::tr("DataDirect Status: ");
00816 contentLines[count++] = DataDirectMessage;
00817 }
00818
00819 contentTotalLines = count;
00820 update(ContentRect);
00821 }
00822
00823 void StatusBox::doScheduleStatus()
00824 {
00825 doScroll = true;
00826 contentLines.clear();
00827 contentDetail.clear();
00828 contentFont.clear();
00829
00830 uint count = 0;
00831
00832 MSqlQuery query(MSqlQuery::InitCon());
00833 query.prepare("SELECT COUNT(*) FROM record WHERE search = 0");
00834
00835 if (!query.exec() || !query.isActive())
00836 {
00837 MythContext::DBError("StatusBox::doScheduleStatus()", query);
00838 contentTotalLines = 0;
00839 update(ContentRect);
00840 return;
00841 }
00842 else
00843 {
00844 query.next();
00845 QString rules = QString("%1 %2").arg(query.value(0).toInt())
00846 .arg(tr("standard rules are defined"));
00847 contentLines[count] = rules;
00848 contentDetail[count] = rules;
00849 count++;
00850 }
00851 query.prepare("SELECT COUNT(*) FROM record WHERE search > 0");
00852
00853 if (!query.exec() || !query.isActive())
00854 {
00855 MythContext::DBError("StatusBox::doScheduleStatus()", query);
00856 contentTotalLines = 0;
00857 update(ContentRect);
00858 return;
00859 }
00860 else
00861 {
00862 query.next();
00863 QString rules = QString("%1 %2").arg(query.value(0).toInt())
00864 .arg(tr("search rules are defined"));
00865 contentLines[count] = rules;
00866 contentDetail[count] = rules;
00867 count++;
00868 }
00869
00870 QMap<RecStatusType, int> statusMatch;
00871 QMap<RecStatusType, QString> statusText;
00872 QMap<int, int> sourceMatch;
00873 QMap<int, QString> sourceText;
00874 QMap<int, int> inputMatch;
00875 QMap<int, QString> inputText;
00876 QString tmpstr;
00877 int maxSource = 0;
00878 int maxInput = 0;
00879 int hdflag = 0;
00880
00881 query.prepare("SELECT MAX(sourceid) FROM videosource");
00882 if (query.exec() && query.isActive() && query.size())
00883 {
00884 query.next();
00885 maxSource = query.value(0).toInt();
00886 }
00887
00888 query.prepare("SELECT sourceid,name FROM videosource");
00889 if (query.exec() && query.isActive() && query.size())
00890 {
00891 while (query.next())
00892 sourceText[query.value(0).toInt()] = query.value(1).toString();
00893 }
00894
00895 query.prepare("SELECT MAX(cardinputid) FROM cardinput");
00896 if (query.exec() && query.isActive() && query.size())
00897 {
00898 query.next();
00899 maxInput = query.value(0).toInt();
00900 }
00901
00902 query.prepare("SELECT cardinputid,cardid,inputname,displayname "
00903 "FROM cardinput");
00904 if (query.exec() && query.isActive() && query.size())
00905 {
00906 while (query.next())
00907 {
00908 if (query.value(3).toString() > "")
00909 inputText[query.value(0).toInt()] = query.value(3).toString();
00910 else
00911 inputText[query.value(0).toInt()] = QString("%1: %2")
00912 .arg(query.value(1).toInt())
00913 .arg(query.value(2).toString());
00914 }
00915 }
00916
00917 ProgramList schedList;
00918 schedList.FromScheduler();
00919
00920 tmpstr = QString("%1 %2").arg(schedList.count()).arg("matching showings");
00921 contentLines[count] = tmpstr;
00922 contentDetail[count] = tmpstr;
00923 count++;
00924
00925 ProgramInfo *s;
00926 for (s = schedList.first(); s; s = schedList.next())
00927 {
00928 if (statusMatch[s->recstatus] < 1)
00929 statusText[s->recstatus] = s->RecStatusText();
00930
00931 ++statusMatch[s->recstatus];
00932
00933 if (s->recstatus == rsWillRecord || s->recstatus == rsRecording)
00934 {
00935 ++sourceMatch[s->sourceid];
00936 ++inputMatch[s->inputid];
00937 if (s->videoproperties & VID_HDTV)
00938 ++hdflag;
00939 }
00940 }
00941 QMap<int, RecStatusType> statusMap;
00942 int i = 0;
00943 statusMap[i++] = rsRecording;
00944 statusMap[i++] = rsWillRecord;
00945 statusMap[i++] = rsConflict;
00946 statusMap[i++] = rsTooManyRecordings;
00947 statusMap[i++] = rsLowDiskSpace;
00948 statusMap[i++] = rsLaterShowing;
00949 statusMap[i++] = rsNotListed;
00950 int j = i;
00951
00952 for (i = 0; i < j; i++)
00953 {
00954 RecStatusType type = statusMap[i];
00955
00956 if (statusMatch[type] > 0)
00957 {
00958 tmpstr = QString("%1 %2").arg(statusMatch[type])
00959 .arg(statusText[type]);
00960 contentLines[count] = tmpstr;
00961 contentDetail[count] = tmpstr;
00962 count++;
00963 }
00964 }
00965
00966 QString willrec = statusText[rsWillRecord];
00967
00968 if (hdflag > 0)
00969 {
00970 tmpstr = QString("%1 %2 %3").arg(hdflag).arg(willrec)
00971 .arg(tr("marked as HDTV"));
00972 contentLines[count] = tmpstr;
00973 contentDetail[count] = tmpstr;
00974 count++;
00975 }
00976 for (i = 1; i <= maxSource; i++)
00977 {
00978 if (sourceMatch[i] > 0)
00979 {
00980 tmpstr = QString("%1 %2 %3 %4 \"%5\"")
00981 .arg(sourceMatch[i]).arg(willrec)
00982 .arg(tr("from source")).arg(i).arg(sourceText[i]);
00983 contentLines[count] = tmpstr;
00984 contentDetail[count] = tmpstr;
00985 count++;
00986 }
00987 }
00988 for (i = 1; i <= maxInput; i++)
00989 {
00990 if (inputMatch[i] > 0)
00991 {
00992 tmpstr = QString("%1 %2 %3 %4 \"%5\"")
00993 .arg(inputMatch[i]).arg(willrec)
00994 .arg(tr("on input")).arg(i).arg(inputText[i]);
00995 contentLines[count] = tmpstr;
00996 contentDetail[count] = tmpstr;
00997 count++;
00998 }
00999 }
01000 contentTotalLines = count;
01001 update(ContentRect);
01002 }
01003
01004 void StatusBox::doTunerStatus()
01005 {
01006 doScroll = true;
01007 contentLines.clear();
01008 contentDetail.clear();
01009 contentFont.clear();
01010
01011 MSqlQuery query(MSqlQuery::InitCon());
01012 query.prepare(
01013 "SELECT cardid, cardtype, videodevice "
01014 "FROM capturecard ORDER BY cardid");
01015
01016 if (!query.exec() || !query.isActive())
01017 {
01018 MythContext::DBError("StatusBox::doTunerStatus()", query);
01019 contentTotalLines = 0;
01020 update(ContentRect);
01021 return;
01022 }
01023
01024 uint count = 0;
01025 while (query.next())
01026 {
01027 int cardid = query.value(0).toInt();
01028
01029 QString cmd = QString("QUERY_REMOTEENCODER %1").arg(cardid);
01030 QStringList strlist = cmd;
01031 strlist << "GET_STATE";
01032
01033 gContext->SendReceiveStringList(strlist);
01034 int state = strlist[0].toInt();
01035
01036 QString status = "";
01037 if (state == kState_Error)
01038 status = tr("is unavailable");
01039 else if (state == kState_WatchingLiveTV)
01040 status = tr("is watching live TV");
01041 else if (state == kState_RecordingOnly ||
01042 state == kState_WatchingRecording)
01043 status = tr("is recording");
01044 else
01045 status = tr("is not recording");
01046
01047 QString tun = tr("Tuner %1 ").arg(cardid);
01048 QString devlabel = CardUtil::GetDeviceLabel(
01049 cardid, query.value(1).toString(), query.value(2).toString());
01050
01051 contentLines[count] = tun + status;
01052 contentDetail[count] = tun + devlabel + " " + status;
01053
01054 if (state == kState_RecordingOnly ||
01055 state == kState_WatchingRecording)
01056 {
01057 strlist = QString("QUERY_RECORDER %1").arg(cardid);
01058 strlist << "GET_RECORDING";
01059 gContext->SendReceiveStringList(strlist);
01060 ProgramInfo *proginfo = new ProgramInfo;
01061 proginfo->FromStringList(strlist, 0);
01062
01063 status += " " + proginfo->title;
01064 status += "\n";
01065 status += proginfo->subtitle;
01066 contentDetail[count] = tun + devlabel + " " + status;
01067 }
01068 count++;
01069 }
01070 contentTotalLines = count;
01071 update(ContentRect);
01072 }
01073
01074 void StatusBox::doLogEntries(void)
01075 {
01076 QString line;
01077 int count = 0;
01078
01079 doScroll = true;
01080
01081 contentLines.clear();
01082 contentDetail.clear();
01083 contentFont.clear();
01084 contentData.clear();
01085
01086 MSqlQuery query(MSqlQuery::InitCon());
01087 query.prepare("SELECT logid, module, priority, logdate, host, "
01088 "message, details "
01089 "FROM mythlog WHERE acknowledged = 0 "
01090 "AND priority <= :PRIORITY ORDER BY logdate DESC;");
01091 query.bindValue(":PRIORITY", min_level);
01092 query.exec();
01093
01094 if (query.isActive())
01095 {
01096 while (query.next())
01097 {
01098 line = QString("%1").arg(query.value(5).toString());
01099 contentLines[count] = line;
01100
01101 if (query.value(6).toString() != "")
01102 line = tr("On %1 %2 from %3.%4\n%5\n%6")
01103 .arg(query.value(3).toDateTime()
01104 .toString(dateFormat))
01105 .arg(query.value(3).toDateTime()
01106 .toString(timeFormat))
01107 .arg(query.value(4).toString())
01108 .arg(query.value(1).toString())
01109 .arg(query.value(5).toString())
01110 .arg(QString::fromUtf8(query.value(6).toString()));
01111 else
01112 line = tr("On %1 %2 from %3.%4\n%5\nNo other details")
01113 .arg(query.value(3).toDateTime()
01114 .toString(dateFormat))
01115 .arg(query.value(3).toDateTime()
01116 .toString(timeFormat))
01117 .arg(query.value(4).toString())
01118 .arg(query.value(1).toString())
01119 .arg(query.value(5).toString());
01120 contentDetail[count] = line;
01121 contentData[count++] = query.value(0).toString();
01122 }
01123 }
01124
01125 if (!count)
01126 {
01127 doScroll = false;
01128 contentLines[count++] = QObject::tr("No items found at priority "
01129 "level %1 or lower.")
01130 .arg(min_level);
01131 contentLines[count++] = QObject::tr("Use 1-8 to change priority "
01132 "level.");
01133 }
01134
01135 contentTotalLines = count;
01136 if (contentPos > (contentTotalLines - 1))
01137 contentPos = contentTotalLines - 1;
01138
01139 update(ContentRect);
01140 }
01141
01142 void StatusBox::doJobQueueStatus()
01143 {
01144 QMap<int, JobQueueEntry> jobs;
01145 QMap<int, JobQueueEntry>::Iterator it;
01146 int count = 0;
01147
01148 QString detail;
01149
01150 JobQueue::GetJobsInQueue(jobs,
01151 JOB_LIST_NOT_DONE | JOB_LIST_ERROR |
01152 JOB_LIST_RECENT);
01153
01154 doScroll = true;
01155
01156 contentLines.clear();
01157 contentDetail.clear();
01158 contentFont.clear();
01159 contentData.clear();
01160
01161 if (jobs.size())
01162 {
01163 for (it = jobs.begin(); it != jobs.end(); ++it)
01164 {
01165 QString chanid = it.data().chanid;
01166 QDateTime starttime = it.data().starttime;
01167 ProgramInfo *pginfo;
01168
01169 pginfo = ProgramInfo::GetProgramFromRecorded(chanid, starttime);
01170
01171 if (!pginfo)
01172 continue;
01173
01174 detail = pginfo->title + "\n" +
01175 pginfo->channame + " " + pginfo->chanstr +
01176 " @ " + starttime.toString(timeDateFormat) + "\n" +
01177 tr("Job:") + " " + JobQueue::JobText(it.data().type) +
01178 " " + tr("Status: ") +
01179 JobQueue::StatusText(it.data().status);
01180
01181 if (it.data().status != JOB_QUEUED)
01182 detail += " (" + it.data().hostname + ")";
01183
01184 if (it.data().schedruntime > QDateTime::currentDateTime())
01185 detail += "\n" + tr("Scheduled Run Time:") + " " +
01186 it.data().schedruntime.toString(timeDateFormat);
01187 else
01188 detail += "\n" + it.data().comment;
01189
01190 contentLines[count] = pginfo->title + " @ " +
01191 starttime.toString(timeDateFormat);
01192
01193 contentDetail[count] = detail;
01194 contentData[count] = QString("%1").arg(it.data().id);
01195
01196 if (it.data().status == JOB_ERRORED)
01197 contentFont[count] = "error";
01198 else if (it.data().status == JOB_ABORTED)
01199 contentFont[count] = "warning";
01200
01201 count++;
01202
01203 delete pginfo;
01204 }
01205 }
01206 else
01207 {
01208 contentLines[count++] = QObject::tr("Job Queue is currently empty.");
01209 doScroll = false;
01210 }
01211
01212 contentTotalLines = count;
01213 update(ContentRect);
01214 }
01215
01216
01217
01225 static const QString sm_str(long long sizeKB, int prec=1)
01226 {
01227 if (sizeKB>1024*1024*1024)
01228 {
01229 double sizeGB = sizeKB/(1024*1024*1024.0);
01230 return QString("%1 TB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
01231 }
01232 else if (sizeKB>1024*1024)
01233 {
01234 double sizeGB = sizeKB/(1024*1024.0);
01235 return QString("%1 GB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
01236 }
01237 else if (sizeKB>1024)
01238 {
01239 double sizeMB = sizeKB/1024.0;
01240 return QString("%1 MB").arg(sizeMB, 0, 'f', (sizeMB>10)?0:prec);
01241 }
01242
01243 return QString("%1 KB").arg(sizeKB);
01244 }
01245
01246 static const QString usage_str_kb(long long total,
01247 long long used,
01248 long long free)
01249 {
01250 QString ret = QObject::tr("Unknown");
01251 if (total > 0.0 && free > 0.0)
01252 {
01253 double percent = (100.0*free)/total;
01254 ret = QObject::tr("%1 total, %2 used, %3 (or %4%) free.")
01255 .arg(sm_str(total)).arg(sm_str(used))
01256 .arg(sm_str(free)).arg(percent, 0, 'f', (percent >= 10.0) ? 0 : 2);
01257 }
01258 return ret;
01259 }
01260
01261 static const QString usage_str_mb(float total, float used, float free)
01262 {
01263 return usage_str_kb((long long)(total*1024), (long long)(used*1024),
01264 (long long)(free*1024));
01265 }
01266
01267 static void disk_usage_with_rec_time_kb(QStringList& out, long long total,
01268 long long used, long long free,
01269 const recprof2bps_t& prof2bps)
01270 {
01271 const QString tail = QObject::tr(", using your %1 rate of %2 Kb/sec");
01272
01273 out<<usage_str_kb(total, used, free);
01274 if (free<0)
01275 return;
01276
01277 recprof2bps_t::const_iterator it = prof2bps.begin();
01278 for (; it != prof2bps.end(); ++it)
01279 {
01280 const QString pro =
01281 tail.arg(it.key()).arg((int)((float)it.data() / 1024.0));
01282
01283 long long bytesPerMin = (it.data() >> 1) * 15;
01284 uint minLeft = ((free<<5)/bytesPerMin)<<5;
01285 minLeft = (minLeft/15)*15;
01286 uint hoursLeft = minLeft/60;
01287 if (hoursLeft > 3)
01288 out<<QObject::tr("%1 hours left").arg(hoursLeft) + pro;
01289 else if (minLeft > 90)
01290 out<<QObject::tr("%1 hours and %2 minutes left")
01291 .arg(hoursLeft).arg(minLeft%60) + pro;
01292 else
01293 out<<QObject::tr("%1 minutes left").arg(minLeft) + pro;
01294 }
01295 }
01296
01297 static const QString uptimeStr(time_t uptime)
01298 {
01299 int days, hours, min, secs;
01300 QString str;
01301
01302 str = QString(" " + QObject::tr("Uptime") + ": ");
01303
01304 if (uptime == 0)
01305 return str + "unknown";
01306
01307 days = uptime/(60*60*24);
01308 uptime -= days*60*60*24;
01309 hours = uptime/(60*60);
01310 uptime -= hours*60*60;
01311 min = uptime/60;
01312 secs = uptime%60;
01313
01314 if (days > 0)
01315 {
01316 char buff[6];
01317 QString dayLabel;
01318
01319 if (days == 1)
01320 dayLabel = QObject::tr("day");
01321 else
01322 dayLabel = QObject::tr("days");
01323
01324 sprintf(buff, "%d:%02d", hours, min);
01325
01326 return str + QString("%1 %2, %3").arg(days).arg(dayLabel).arg(buff);
01327 }
01328 else
01329 {
01330 char buff[9];
01331
01332 sprintf(buff, "%d:%02d:%02d", hours, min, secs);
01333
01334 return str + buff;
01335 }
01336 }
01337
01341 void StatusBox::getActualRecordedBPS(QString hostnames)
01342 {
01343 recordingProfilesBPS.clear();
01344
01345 QString querystr;
01346 MSqlQuery query(MSqlQuery::InitCon());
01347
01348 querystr =
01349 "SELECT sum(filesize) * 8 / "
01350 "sum(((unix_timestamp(endtime) - unix_timestamp(starttime)))) "
01351 "AS avg_bitrate "
01352 "FROM recorded WHERE hostname in (%1) "
01353 "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
01354
01355 query.prepare(querystr.arg(hostnames));
01356
01357 if (query.exec() && query.isActive() && query.size() > 0 && query.next() &&
01358 query.value(0).toDouble() > 0)
01359 {
01360 recordingProfilesBPS[QObject::tr("average")] =
01361 (int)(query.value(0).toDouble());
01362 }
01363
01364 querystr =
01365 "SELECT max(filesize * 8 / "
01366 "(unix_timestamp(endtime) - unix_timestamp(starttime))) "
01367 "AS max_bitrate "
01368 "FROM recorded WHERE hostname in (%1) "
01369 "AND (unix_timestamp(endtime) - unix_timestamp(starttime)) > 300;";
01370
01371 query.prepare(querystr.arg(hostnames));
01372
01373 if (query.exec() && query.isActive() && query.size() > 0 && query.next() &&
01374 query.value(0).toDouble() > 0)
01375 {
01376 recordingProfilesBPS[QObject::tr("maximum")] =
01377 (int)(query.value(0).toDouble());
01378 }
01379 }
01380
01389 void StatusBox::doMachineStatus()
01390 {
01391 int count(0);
01392 int totalM, usedM, freeM;
01393 int totalS, usedS, freeS;
01394 time_t uptime;
01395 int detailBegin;
01396 QString detailString;
01397 int detailLoop;
01398
01399 contentLines.clear();
01400 contentDetail.clear();
01401 contentFont.clear();
01402 doScroll = true;
01403
01404 detailBegin = count;
01405 detailString = "";
01406
01407 if (isBackend)
01408 contentLines[count] = QObject::tr("System") + ":";
01409 else
01410 contentLines[count] = QObject::tr("This machine") + ":";
01411 detailString += contentLines[count] + "\n";
01412 count++;
01413
01414
01415 if (!getUptime(uptime))
01416 uptime = 0;
01417 contentLines[count] = uptimeStr(uptime);
01418
01419
01420 contentLines[count].append(". " + QObject::tr("Load") + ": ");
01421
01422 #ifdef _WIN32
01423 contentLines[count].append(
01424 QObject::tr("unknown") + " - getloadavg() " + QObject::tr("failed"));
01425 #else // if !_WIN32
01426 double loads[3];
01427 if (getloadavg(loads,3) == -1)
01428 contentLines[count].append(QObject::tr("unknown") +
01429 " - getloadavg() " + QObject::tr("failed"));
01430 else
01431 {
01432 char buff[30];
01433
01434 sprintf(buff, "%0.2lf, %0.2lf, %0.2lf", loads[0], loads[1], loads[2]);
01435 contentLines[count].append(QString(buff));
01436 }
01437 #endif // _WIN32
01438
01439 detailString += contentLines[count] + "\n";
01440 count++;
01441
01442
01443
01444 if (getMemStats(totalM, freeM, totalS, freeS))
01445 {
01446 usedM = totalM - freeM;
01447 if (totalM > 0)
01448 {
01449 contentLines[count] = " " + QObject::tr("RAM") +
01450 ": " + usage_str_mb(totalM, usedM, freeM);
01451 detailString += contentLines[count] + "\n";
01452 count++;
01453 }
01454 usedS = totalS - freeS;
01455 if (totalS > 0)
01456 {
01457 contentLines[count] = " " + QObject::tr("Swap") +
01458 ": " + usage_str_mb(totalS, usedS, freeS);
01459 detailString += contentLines[count] + "\n";
01460 count++;
01461 }
01462 }
01463
01464 for (detailLoop = detailBegin; detailLoop < count; detailLoop++)
01465 contentDetail[detailLoop] = detailString;
01466
01467 detailBegin = count;
01468 detailString = "";
01469
01470 if (!isBackend)
01471 {
01472 contentLines[count] = QObject::tr("MythTV server") + ":";
01473 detailString += contentLines[count] + "\n";
01474 count++;
01475
01476
01477 if (!RemoteGetUptime(uptime))
01478 uptime = 0;
01479 contentLines[count] = uptimeStr(uptime);
01480
01481
01482 contentLines[count].append(". " + QObject::tr("Load") + ": ");
01483 float loads[3];
01484 if (RemoteGetLoad(loads))
01485 {
01486 char buff[30];
01487
01488 sprintf(buff, "%0.2f, %0.2f, %0.2f", loads[0], loads[1], loads[2]);
01489 contentLines[count].append(QString(buff));
01490 }
01491 else
01492 contentLines[count].append(QObject::tr("unknown"));
01493
01494 detailString += contentLines[count] + "\n";
01495 count++;
01496
01497
01498 if (RemoteGetMemStats(totalM, freeM, totalS, freeS))
01499 {
01500 usedM = totalM - freeM;
01501 if (totalM > 0)
01502 {
01503 contentLines[count] = " " + QObject::tr("RAM") +
01504 ": " + usage_str_mb(totalM, usedM, freeM);
01505 detailString += contentLines[count] + "\n";
01506 count++;
01507 }
01508
01509 usedS = totalS - freeS;
01510 if (totalS > 0)
01511 {
01512 contentLines[count] = " " + QObject::tr("Swap") +
01513 ": " + usage_str_mb(totalS, usedS, freeS);
01514 detailString += contentLines[count] + "\n";
01515 count++;
01516 }
01517 }
01518 }
01519
01520 for (detailLoop = detailBegin; detailLoop < count; detailLoop++)
01521 contentDetail[detailLoop] = detailString;
01522
01523 detailBegin = count;
01524 detailString = "";
01525
01526
01527 QString hostnames;
01528
01529 vector<FileSystemInfo> fsInfos = RemoteGetFreeSpace();
01530 for (uint i=0; i<fsInfos.size(); i++)
01531 {
01532
01533 if ((fsInfos.size() == 2) && (i == 0) &&
01534 (fsInfos[i].directory != "TotalDiskSpace") &&
01535 (fsInfos[i+1].directory == "TotalDiskSpace"))
01536 i++;
01537
01538 hostnames = QString("\"%1\"").arg(fsInfos[i].hostname);
01539 hostnames.replace(QRegExp(" "), "");
01540 hostnames.replace(QRegExp(","), "\",\"");
01541
01542 getActualRecordedBPS(hostnames);
01543
01544 QStringList list;
01545 disk_usage_with_rec_time_kb(list,
01546 fsInfos[i].totalSpaceKB, fsInfos[i].usedSpaceKB,
01547 fsInfos[i].totalSpaceKB - fsInfos[i].usedSpaceKB,
01548 recordingProfilesBPS);
01549
01550 if (fsInfos[i].directory == "TotalDiskSpace")
01551 {
01552 contentLines[count] = QObject::tr("Total Disk Space:");
01553 detailString += contentLines[count] + "\n";
01554 count++;
01555 }
01556 else
01557 {
01558 contentLines[count] =
01559 QObject::tr("MythTV Drive #%1:")
01560 .arg(fsInfos[i].fsID);
01561 detailString += contentLines[count] + "\n";
01562 count++;
01563
01564 QStringList tokens = QStringList::split(",", fsInfos[i].directory);
01565
01566 if (tokens.size() > 1)
01567 {
01568 contentLines[count++] +=
01569 QString(" ") + QObject::tr("Directories:");
01570
01571 unsigned int curToken = 0;
01572 while (curToken < tokens.size())
01573 contentLines[count++] =
01574 QString(" ") + tokens[curToken++];
01575 }
01576 else
01577 {
01578 contentLines[count++] += QString(" " ) +
01579 QObject::tr("Directory:") + " " + fsInfos[i].directory;
01580 }
01581 }
01582
01583 QStringList::iterator it = list.begin();
01584 for (;it != list.end(); ++it)
01585 {
01586 contentLines[count] = QString(" ") + (*it);
01587 detailString += contentLines[count] + "\n";
01588 count++;
01589 }
01590
01591 for (detailLoop = detailBegin; detailLoop < count; detailLoop++)
01592 contentDetail[detailLoop] = detailString;
01593
01594 detailBegin = count;
01595 detailString = "";
01596 }
01597
01598 contentTotalLines = count;
01599 update(ContentRect);
01600 }
01601
01605 void StatusBox::doAutoExpireList()
01606 {
01607 int count(0);
01608 ProgramInfo* pginfo;
01609 QString contentLine;
01610 QString detailInfo;
01611 QString staticInfo;
01612 long long totalSize(0);
01613 long long liveTVSize(0);
01614 int liveTVCount(0);
01615 long long deletedGroupSize(0);
01616 int deletedGroupCount(0);
01617
01618 contentLines.clear();
01619 contentDetail.clear();
01620 contentFont.clear();
01621 doScroll = true;
01622
01623 vector<ProgramInfo *>::iterator it;
01624 for (it = expList.begin(); it != expList.end(); it++)
01625 delete *it;
01626 expList.clear();
01627
01628 RemoteGetAllExpiringRecordings(expList);
01629
01630 for (it = expList.begin(); it != expList.end(); it++)
01631 {
01632 pginfo = *it;
01633
01634 totalSize += pginfo->filesize;
01635 if (pginfo->recgroup == "LiveTV")
01636 {
01637 liveTVSize += pginfo->filesize;
01638 liveTVCount++;
01639 }
01640 else if (pginfo->recgroup == "Deleted")
01641 {
01642 deletedGroupSize += pginfo->filesize;
01643 deletedGroupCount++;
01644 }
01645 }
01646
01647 staticInfo = tr("%1 recordings consuming %2 are allowed to expire")
01648 .arg(expList.size()).arg(sm_str(totalSize / 1024)) + "\n";
01649
01650 if (liveTVCount)
01651 staticInfo += tr("%1 of these are LiveTV and consume %2")
01652 .arg(liveTVCount).arg(sm_str(liveTVSize / 1024)) + "\n";
01653
01654 if (deletedGroupCount)
01655 staticInfo += tr("%1 of these are Deleted and consume %2")
01656 .arg(deletedGroupCount).arg(sm_str(deletedGroupSize / 1024)) + "\n";
01657
01658 for (it = expList.begin(); it != expList.end(); it++)
01659 {
01660 pginfo = *it;
01661 contentLine = pginfo->recstartts.toString(dateFormat) + " - ";
01662
01663 if ((pginfo->recgroup == "LiveTV") ||
01664 (pginfo->recgroup == "Deleted"))
01665 contentLine += "(" + tr(pginfo->recgroup) + ") ";
01666 else
01667 contentLine += "(" + pginfo->recgroup + ") ";
01668
01669 contentLine += pginfo->title +
01670 " (" + sm_str(pginfo->filesize / 1024) + ")";
01671
01672 detailInfo = staticInfo;
01673 detailInfo += pginfo->recstartts.toString(timeDateFormat) + " - " +
01674 pginfo->recendts.toString(timeDateFormat);
01675
01676 detailInfo += " (" + sm_str(pginfo->filesize / 1024) + ")";
01677
01678 if ((pginfo->recgroup == "LiveTV") ||
01679 (pginfo->recgroup == "Deleted"))
01680 detailInfo += " (" + tr(pginfo->recgroup) + ")";
01681 else
01682 detailInfo += " (" + pginfo->recgroup + ")";
01683
01684 detailInfo += "\n" + pginfo->title;
01685
01686 if (pginfo->subtitle != "")
01687 detailInfo += " - " + pginfo->subtitle + "";
01688
01689 contentLines[count] = contentLine;
01690 contentDetail[count] = detailInfo;
01691 count++;
01692 }
01693
01694 contentTotalLines = count;
01695 update(ContentRect);
01696 }
01697
01698