[mythtv] [PATCH] Updated Status Screen (uitypes)

Kevin Kuphal kuphal at dls.net
Sun Jul 25 10:51:07 EDT 2004


Kevin Kuphal wrote:

> Kevin Kuphal wrote:
>
>> This is the improved status screen now using uitypes instead of Qt.
>>
>> It currently displays the mythfilldatabase status (from the original 
>> system status screen), the state of each tuner, and the DVB 
>> statistics from the PrintDVBStatus function of the backend (I don't 
>> have DVB to test this with so if anyone wants to report on this or 
>> even send me a dump of their dvb_signal_quality table, I'd appreciate 
>> it)
>>
>> I'm working next on incorporating the functionality of the mythlog 
>> module to display and acknowledge entries from the database logging 
>> feature.
>>
> One of these days I'll submit a patch without updating it shortly 
> thereafter.
>
> Small update.  Splits the two sections of the screen into different 
> containers for independent updating.  I was trying to improve the 
> responsiveness of things but it didn't seem to make much difference.  
> Still, this is probably the "better" way to handle things.

Another update.  Changed to using a single text area and a single list 
area for the content side of the screen.  No need to duplicate it for 
each status category.

Kevin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: status-ui.xml
Type: text/xml
Size: 2995 bytes
Desc: not available
Url : http://mythtv.org/pipermail/mythtv-dev/attachments/20040725/f8400618/status-ui-0001.xml
-------------- next part --------------
#include <qlayout.h>
#include <qiconview.h>
#include <qsqldatabase.h>
#include <qwidgetstack.h>
#include <qvbox.h>
#include <qgrid.h>

#include <unistd.h>

#include <iostream>
using namespace std;

#include "statusbox.h"
#include "mythcontext.h"
#include "remoteutil.h"
#include "programinfo.h"
#include "tv.h"

StatusBox::StatusBox(MythMainWindow *parent, const char *name)
         : MythDialog(parent, name)
{
    current_icon = 0;
    // Set this value to the number of items in icon_list
    // to prevent scrolling off the bottom
    max_icons = 3;

    setNoErase();
    LoadTheme();
  
    icon_list->SetItemText(0, "Listings Status");
    icon_list->SetItemText(1, "Tuner Status");
    icon_list->SetItemText(2, "DVB Status");
    // icon_list->SetItemText(3, "Log Entries");
    icon_list->SetItemCurrent(current_icon);
    icon_list->SetActive(true);
}

void StatusBox::paintEvent(QPaintEvent *e)
{
    QRect r = e->rect();

    if (r.intersects(TopRect))
        updateTopBar();
    if (r.intersects(SelectRect))
        updateSelector();
    if (r.intersects(ContentRect))
        updateContent();
}

void StatusBox::updateContent()
{
    QRect pr = ContentRect;
    QPixmap pix(pr.size());
    pix.fill(this, pr.topLeft());
    QPainter tmp(&pix);
    QPainter p(this);
 
    if (content  == NULL) return;
    LayerSet *container = content;

    container->Draw(&tmp, 0, 0);
    container->Draw(&tmp, 1, 0);
    container->Draw(&tmp, 2, 0);
    container->Draw(&tmp, 3, 0);
    container->Draw(&tmp, 4, 0);
    container->Draw(&tmp, 5, 0);
    container->Draw(&tmp, 6, 0);
    container->Draw(&tmp, 7, 0);
    container->Draw(&tmp, 8, 0);
    tmp.end();
    p.drawPixmap(pr.topLeft(), pix);
}

void StatusBox::updateSelector()
{
    QRect pr = SelectRect;
    QPixmap pix(pr.size());
    pix.fill(this, pr.topLeft());
    QPainter tmp(&pix);
    QPainter p(this);
 
    if (selector == NULL) return;
    LayerSet *container = selector;

    container->Draw(&tmp, 0, 0);
    container->Draw(&tmp, 1, 0);
    container->Draw(&tmp, 2, 0);
    container->Draw(&tmp, 3, 0);
    container->Draw(&tmp, 4, 0);
    container->Draw(&tmp, 5, 0);
    container->Draw(&tmp, 6, 0);
    container->Draw(&tmp, 7, 0);
    container->Draw(&tmp, 8, 0);
    tmp.end();
    p.drawPixmap(pr.topLeft(), pix);
}

void StatusBox::updateTopBar()
{
    QRect pr = TopRect;
    QPixmap pix(pr.size());
    pix.fill(this, pr.topLeft());
    QPainter tmp(&pix);
    QPainter p(this);

    if (topbar == NULL) return;
    LayerSet *container = topbar;

    container->Draw(&tmp, 0, 0);
    tmp.end();
    p.drawPixmap(pr.topLeft(), pix);
}

void StatusBox::LoadTheme()
{
    int screenheight = 0, screenwidth = 0;
    float wmult = 0, hmult = 0;

    gContext->GetScreenSettings(screenwidth, wmult, screenheight, hmult);

    theme = new XMLParse();
    theme->SetWMult(wmult);
    theme->SetHMult(hmult);
    theme->LoadTheme(xmldata, "status", "status-");

    for (QDomNode child = xmldata.firstChild(); !child.isNull();
         child = child.nextSibling()) {

        QDomElement e = child.toElement();
        if (!e.isNull()) {
            if (e.tagName() == "font") {
                theme->parseFont(e);
            }
            else if (e.tagName() == "container") {
                QRect area;
                QString name;
                int context;
                theme->parseContainer(e, name, context, area);

                if (name.lower() == "topbar")
                    TopRect = area;
                if (name.lower() == "selector")
                    SelectRect = area;
                if (name.lower() == "content")
                    ContentRect = area;
            }
            else {
                cerr << "Unknown element: " << e.tagName()
                          << endl;
                exit(-1);
            }
        }
    }

    selector = theme->GetSet("selector");
    if (!selector) {
        cerr << "StatusBox: Failed to get selector container." << endl;
        exit(-1);
    }

    icon_list = (UIListType*)selector->GetType("icon_list");
    if (!icon_list) {
        cerr << "StatusBox: Failed to get icon list area." << endl;
        exit(-1);
    }

    content = theme->GetSet("content");
    if (!content) {
        cerr << "StatusBox: Failed to get content container." << endl;
        exit(-1);
    }

    list_area = (UIListType*)content->GetType("list_area");
    if (!list_area) {
        cerr << "StatusBox: Failed to get list area." << endl;
        exit(-1);
    }

    text_area = (UITextType*)content->GetType("text_area");
    if (!text_area) {
        cerr << "StatusBox: Failed to get text area." << endl;
        exit(-1);
    }

    topbar = theme->GetSet("topbar");
    if (!topbar) {
        cerr << "StatusBox: Failed to get topbar container." << endl;
        exit(-1);
    }

    heading = (UITextType*)topbar->GetType("heading");
    if (!heading) {
        cerr << "StatusBox: Failed to get heading area." << endl;
        exit(-1);
    }

    helptext = (UITextType*)topbar->GetType("helptext");
    if (!helptext) {
        cerr << "StatusBox: Failed to get helptext area." << endl;
        exit(-1);
    }
}

void StatusBox::keyPressEvent(QKeyEvent *e)
{
    bool handled = false;
    QStringList actions;
    gContext->GetMainWindow()->TranslateKeyPress("Status", e, actions);

    for (unsigned int i = 0; i < actions.size() && !handled; i++)
    {
        QString action = actions[i];
        handled = true;

        if (action == "SELECT")
        {
            clicked();
        }
        else if (action == "UP")
        {
            if (current_icon > 0)
                current_icon--;
            icon_list->SetItemCurrent(current_icon);
            setHelpText();
            update(SelectRect);
        }
        else if (action == "DOWN")
        {
            if (current_icon < (max_icons - 1))
                current_icon++;
            icon_list->SetItemCurrent(current_icon);
            setHelpText();
            update(SelectRect);
        }
        else
            handled = false;
    }

    if (!handled)
        MythDialog::keyPressEvent(e);
}

void StatusBox::setHelpText()
{
    topbar->ClearAllText();
    switch (current_icon)
    {
        case 0:
            helptext->SetText("Listings Status shows the latest status information from mythfilldatabase");
            break;
        case 1:
            helptext->SetText("Tuner Status shows the current information about the state of backend tuner cards");
            break;
        case 2:
            helptext->SetText("DVB Status shows the quality statistics of all DVB cards, if present");
            break;
        case 3:
            helptext->SetText("Log Entries shows any unread log entries from the system if you have logging enabled");
            break;
    }
    update(TopRect);
}

void StatusBox::clicked()
{
    // Clear all visible content elements here
    // I'm sure there's a better way to do this but I can't find it
    content->ClearAllText();
    list_area->ResetList();

    switch (current_icon)
    {
        case 0:
            doListingsStatus();
            break;
        case 1:
            doTunerStatus();
            break;
        case 2:
            doDVBStatus();
            break;
        case 3:
            doLogEntries();
            break;
    }
}

void StatusBox::doListingsStatus()
{
    QString mfdLastRunStart, mfdLastRunEnd, mfdLastRunStatus, Status;
    QString querytext, DataDirectMessage;
    int DaysOfData;
    QDateTime qdtNow, GuideDataThrough;
    QSqlDatabase *db = QSqlDatabase::database();

    qdtNow = QDateTime::currentDateTime();
    querytext = QString("SELECT max(endtime) FROM program;");

    QSqlQuery query = db->exec(querytext);

    if (query.isActive() && query.numRowsAffected())
    {
        query.next();
        GuideDataThrough = QDateTime::fromString(query.value(0).toString(),
                                                 Qt::ISODate);
    }

    mfdLastRunStart = gContext->GetSetting("mythfilldatabaseLastRunStart");
    mfdLastRunEnd = gContext->GetSetting("mythfilldatabaseLastRunEnd");
    mfdLastRunStatus = gContext->GetSetting("mythfilldatabaseLastRunStatus");
    DataDirectMessage = gContext->GetSetting("DataDirectMessage");

    Status = QObject::tr("Myth version:") + " " + MYTH_BINARY_VERSION + "\n";

    Status += QObject::tr("Last mythfilldatabase guide update:");
    Status += "\n   ";
    Status += QObject::tr("Started:   ");
    Status += mfdLastRunStart;
    if (mfdLastRunEnd > mfdLastRunStart)  //if end < start, it's still running.
    {
        Status += "\n   ";
        Status += QObject::tr("Finished: ");
        Status += mfdLastRunEnd;
    }

    Status += "\n   ";
    Status += QObject::tr("Result: ");
    Status += mfdLastRunStatus;

    DaysOfData = qdtNow.daysTo(GuideDataThrough);

    if (GuideDataThrough.isNull())
    {
        Status += "\n\n";
        Status += QObject::tr("There's no guide data available! ");
        Status += QObject::tr("Have you run mythfilldatabase?");
        Status += "\n";
    }
    else
    {
        Status += "\n\n";
        Status += QObject::tr("There is guide data until ");
        Status += QDateTime(GuideDataThrough).toString("yyyy-MM-dd hh:mm");

        if (DaysOfData > 0)
        {
            Status += QString("\n(%1 ").arg(DaysOfData);
            if (DaysOfData >1)
                Status += QObject::tr("days");
            else
                Status += QObject::tr("day");
            Status += ").";
        }
        else
            Status += ".";
    }

    if (DaysOfData <= 3)
    {
        Status += "\n";
        Status += QObject::tr("WARNING: is mythfilldatabase running?");
    }

    if (!DataDirectMessage.isNull())
    {
        Status += "\n";
        Status += QObject::tr("DataDirect Status: \n");
        Status += DataDirectMessage;
    }
   
    text_area->SetText(Status);
    update(ContentRect);
}

void StatusBox::doTunerStatus()
{
    int count = 0;

    QString querytext = QString("SELECT cardid FROM capturecard;");
    QSqlDatabase *db = QSqlDatabase::database();
    QSqlQuery query = db->exec(querytext);
    if (query.isActive() && query.numRowsAffected())
    {
        list_area->ResetList();
        while(query.next())
        {
            int cardid = query.value(0).toInt();

            QString cmd = QString("QUERY_REMOTEENCODER %1").arg(cardid);
            QStringList strlist = cmd;
            strlist << "GET_STATE";

            gContext->SendReceiveStringList(strlist);
  
            QString Status = QString("Tuner %1 ").arg(cardid);
            if (strlist[0].toInt()==kState_WatchingLiveTV)
                Status += "is watching live TV";
            else if (strlist[0].toInt()==kState_RecordingOnly ||
                     strlist[0].toInt()==kState_WatchingRecording)
                Status += "is recording";
            else 
                Status += "is not recording";

            if (strlist[0].toInt()==kState_RecordingOnly)
            {
                strlist = QString("QUERY_RECORDER %1").arg(cardid);
                strlist << "GET_RECORDING";
                gContext->SendReceiveStringList(strlist);
                ProgramInfo *proginfo = new ProgramInfo;
                proginfo->FromStringList(strlist, 0);
                Status += "\n";
                Status += proginfo->title;
                Status += " - ";
                Status += proginfo->subtitle;
            }
            list_area->SetItemText(count, Status);
            count++;
        }
    }
    update(ContentRect);
}

void StatusBox::doDVBStatus(void)
{
    QString querytext;

    bool doneAnything = false;
    
    QString Status = QString("Details of DVB error statistics for last 48 hours:\n");

    QString outerqry =
        "SELECT starttime,endtime FROM recorded "
        "WHERE starttime >= DATE_SUB(NOW(), INTERVAL 48 HOUR) "
        "ORDER BY starttime;";

    QSqlDatabase *db = QSqlDatabase::database();
    QSqlQuery oquery = db->exec(outerqry);

    if (oquery.isActive() && oquery.numRowsAffected())
    {
        querytext = QString("SELECT cardid,"
                            "max(fe_ss),min(fe_ss),avg(fe_ss),"
                            "max(fe_snr),min(fe_snr),avg(fe_snr),"
                            "max(fe_ber),min(fe_ber),avg(fe_ber),"
                            "max(fe_unc),min(fe_unc),avg(fe_unc),"
                            "max(myth_cont),max(myth_over),max(myth_pkts) "
                            "FROM dvb_signal_quality "
                            "WHERE sampletime BETWEEN ? AND ? "
                            "GROUP BY cardid");

        QSqlQuery query = db->exec(NULL);
        query.prepare(querytext);
        
        while (oquery.next())
        {
            QDateTime t_start = oquery.value(0).toDateTime();
            QDateTime t_end = oquery.value(1).toDateTime();

            query.bindValue(0, t_start);
            query.bindValue(1, t_end);

            if (!query.exec())
                cout << query.lastError().databaseText() << "\r\n" 
                     << query.lastError().driverText() << "\r\n";
            
            if (query.isActive() && query.numRowsAffected())
            {
                Status += QString("Recording period from %1 to %2\n").arg(t_start.toString()).arg(t_end.toString());
                
                while (query.next())
                {
		    Status += QString("Encoder %1 Min SNR: %2 Avg SNR: %3 Min BER %4 Avg BER %5 Cont Errs: %6 Overflows: %7\n")
                              .arg(query.value(0).toInt())
                              .arg(query.value(5).toInt())
                              .arg(query.value(6).toInt())
                              .arg(query.value(8).toInt())
                              .arg(query.value(9).toInt())
                              .arg(query.value(13).toInt())
                              .arg(query.value(14).toInt());

                    doneAnything = true;
                }
            }
        }
    }

    if (!doneAnything)
    {
        Status += QString("There is no DVB signal quality data available to display.\n");
    }

    text_area->SetText(Status);
    update(ContentRect);
}

void StatusBox::doLogEntries(void)
{
/*
    // int minlevel = gContext->GetNumSetting("LogDefaultView",0);
    int minlevel = 8;

    log_list->clear();
    QSqlDatabase *db = QSqlDatabase::database();
    QString thequery = QString("SELECT logid, module, priority, logdate, host, message, "
                               "details FROM mythlog WHERE acknowledged = 0 and priority <= %1 "
                               "order by logdate").arg(minlevel);
    QSqlQuery query = db->exec(thequery);
    if (query.isActive())
        while (query.next())
            log_list->insertItem(QString("%1 %2").arg(query.value(3).toString()).arg(query.value(5).toString()));
*/
}

StatusBox::~StatusBox(void)
{
}

-------------- next part --------------
#ifndef STATUSBOX_H_
#define STATUSBOX_H_

#include "mythwidgets.h"
#include "mythdialogs.h"
#include "uitypes.h"
#include "xmlparse.h"

class LayerSet;

class StatusBox : public MythDialog
{
    Q_OBJECT
  public:
    StatusBox(MythMainWindow *parent, const char *name = 0);
   ~StatusBox(void);

  protected slots:

  protected:
    void keyPressEvent(QKeyEvent *e);
    void paintEvent(QPaintEvent *e);

  private:
    void updateTopBar();
    void updateSelector();
    void updateContent();
    void LoadTheme();
    void doListingsStatus();
    void doTunerStatus();
    void doDVBStatus();
    void doLogEntries();
    void clicked();
    void setHelpText();

    XMLParse *theme;
    QDomElement xmldata;
    QRect TopRect, SelectRect, ContentRect;
    UITextType *heading, *helptext, *text_area;
    UIListType *icon_list, *list_area;
    LayerSet *selector, *topbar, *content;

    int current_icon, max_icons;
};

#endif


More information about the mythtv-dev mailing list