Ticket #2482: mythmovies.patch

File mythmovies.patch, 70.5 KB (added by Josh Lefler <joshlefler@…>, 15 years ago)
  • configure

     
    2222controls="yes"
    2323flix="yes"
    2424archive="yes"
     25movies="yes"
    2526
    2627cc="gcc"
    2728
     
    104105
    105106MythWeather related options:
    106107  --enable-mythweather     build the mythweather plugin [$weather]
     108
     109MythMovies related options:
     110  --enable-mythmovies      build the mythmovies plugin [$movies]
    107111EOF
    108112exit 1
    109113fi
     
    198202  ;;
    199203  --disable-mythflix) flix="no"
    200204  ;;
     205  --enable-mythmovies) movies="yes"
     206  ;;
     207  --disable-mythmovies) movies="no"
     208  ;;
    201209  --enable-opengl) opengl="yes"
    202210  ;;
    203211  --disable-opengl) opengl="no"
     
    238246                 browser="yes";
    239247                 controls="yes";
    240248                 flix="yes";
     249                 movies="yes";
    241250                 sdl="yes";
    242251                 opengl="yes";
    243252                 fftw_lib="yes";
     
    260269                 browser="no";
    261270                 controls="no";
    262271                 flix="no";
     272                 movies="no";
    263273                 sdl="no"; 
    264274                 opengl="no";
    265275                 fftw_lib="no";
     
    618628  echo "        MythWeather    plugin will not be built"
    619629fi
    620630
     631if test "$movies" = "yes" ; then
     632  echo "        MythMovies     plugin will be built"
     633  echo "SUBDIRS += mythmovies" >> ./config.pro
     634else
     635    echo "      MythMovies     plugin will not be built"
     636fi
    621637###########################################################
    622638#                                                         #
    623639#   MythArchive related configuration options             #
  • mythmovies/ignyte/main.cpp

     
     1#include <qapplication.h>
     2#include "ignytegrabber.h"
     3
     4using namespace std;
     5
     6int main(int argc, char **argv)
     7{
     8    QString zip;
     9    QString radius;
     10    for(int i = 1; i + 1 < argc; ++i)
     11    {
     12        if (!strcmp(argv[i], "--zip"))
     13        {
     14            zip = argv[i + 1];
     15        }
     16        if (!strcmp(argv[i], "--radius"))
     17        {
     18            radius = argv[i + 1];
     19        }
     20    }
     21
     22    QApplication app(argc, argv, false);
     23    IgnyteGrabber *grab;
     24    grab = new IgnyteGrabber(zip, radius, &app);
     25    return app.exec();
     26}
     27
     28
  • mythmovies/ignyte/ignytegrabber.cpp

     
     1
     2#include "ignytegrabber.h"
     3 
     4IgnyteGrabber::IgnyteGrabber(QString zip, QString radius, QApplication *callingApp)
     5{
     6    app = callingApp;
     7    //this feels clumsy to me - should we store it in a file instead?
     8    QString fields ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
     9            "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
     10            "xmlns:tns=\"http://www.ignyte.com/whatsshowing\" xmlns:xs=\"http://www.w3.org"
     11            "/2001/XMLSchema\">\n"
     12            "<soap:Body>\n"
     13            "<tns:GetTheatersAndMovies>\n"
     14            "<tns:zipCode>"  + zip + "</tns:zipCode>\n"
     15            "<tns:radius>" + radius + "</tns:radius>\n"
     16            "</tns:GetTheatersAndMovies>\n"
     17            "</soap:Body>\n"
     18            "</soap:Envelope>\n");
     19    QString server("www.ignyte.com");
     20    QString path("/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx");
     21    QString soapAction("http://www.ignyte.com/whatsshowing/GetTheatersAndMovies");
     22    ms.doSoapRequest(server, path, soapAction, fields);
     23
     24    waitForSoap = new QTimer(this);
     25    connect(waitForSoap, SIGNAL(timeout()), this, SLOT(checkHttp()));
     26    waitForSoap->start(0, FALSE);
     27}
     28
     29void IgnyteGrabber::checkHttp()
     30{
     31    if (ms.isDone())
     32    {
     33        if (ms.hasError())
     34        {
     35            cerr << "Data Source Error" << endl << flush;
     36        }
     37        else
     38        {
     39            outputData(ms.getResponseData().data());
     40        }
     41        waitForSoap->stop();
     42        app->exit();
     43    }
     44}
     45
     46void IgnyteGrabber::outputData(QString data)
     47{
     48    int i =  data.find("<GetTheatersAndMoviesResult>");
     49    data = data.mid(i + 28);
     50    int x = data.find("</GetTheatersAndMoviesResult>");
     51    data = data.left(x);
     52    data = data.remove('\r');
     53    data = data.remove('\n');
     54    data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><MovieTimes>" + data + "</MovieTimes>";
     55    cout << data;
     56}
  • mythmovies/ignyte/mythsoap.cpp

     
     1#include <mythtv/mythcontext.h>
     2
     3#include "mythsoap.h"
     4
     5void MythSoap::doSoapRequest(QString host, QString path, QString soapAction,
     6                             QString query)
     7{
     8    connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)));
     9
     10    QHttpRequestHeader header("POST", path);
     11    header.setValue("Host", host);
     12    header.setValue("SOAPAction",  soapAction);
     13    header.setContentType("text/xml");
     14
     15    http.setHost(host);
     16    QByteArray bArray(query.utf8());
     17    bArray.resize(bArray.size() - 1);
     18    http.request(header, bArray);
     19}
     20
     21QByteArray MythSoap::getResponseData()
     22{
     23    return m_data;
     24}
     25
     26bool MythSoap::isDone()
     27{
     28    return m_done;
     29}
     30
     31bool MythSoap::hasError()
     32{
     33    return m_error;
     34}
     35
     36void MythSoap::httpDone(bool error)
     37{
     38    if (error)
     39    {
     40        cerr << "Error in mythsoap.o retrieving data: " << http.errorString() << endl << flush;
     41    }
     42    else
     43    {
     44        m_data = http.readAll();
     45        //cout << "Data: " << m_data.data() << endl << flush;
     46    }
     47    m_done = true;
     48}
     49
     50MythSoap::MythSoap()
     51{
     52    m_done = false;
     53    m_error = false;
     54}
  • mythmovies/ignyte/ignytegrabber.h

     
     1#include <qapplication.h>
     2#include <qtimer.h>
     3#include <qstring.h>
     4#include <iostream>
     5#include "mythsoap.h"
     6
     7using namespace std;
     8
     9class IgnyteGrabber : public QObject
     10{
     11    Q_OBJECT
     12
     13    public:
     14        IgnyteGrabber(QString, QString, QApplication*);
     15
     16    private:
     17        QTimer *waitForSoap;
     18        MythSoap ms;
     19        QApplication *app;
     20        void outputData(QString);
     21
     22    public slots:
     23        void checkHttp();
     24};
     25
  • mythmovies/ignyte/mythsoap.h

     
     1#ifndef MYTHSOAP_H_
     2#define MYTHSOAP_H_
     3
     4#include <qhttp.h>
     5#include <qstring.h>
     6
     7class MythSoap : public QObject
     8{
     9    Q_OBJECT
     10    public:
     11        void doSoapRequest(QString, QString, QString, QString);
     12        QByteArray getResponseData();
     13        bool isDone();
     14        bool hasError();
     15        MythSoap();
     16
     17    private:
     18        QHttp http;
     19        bool  m_done;
     20        bool m_error;
     21        QByteArray m_data;
     22
     23    public slots:
     24        void httpDone(bool);
     25};
     26
     27#endif
  • mythmovies/ignyte/ignyte.pro

     
     1include ( ../../mythconfig.mak )
     2include ( ../../settings.pro )
     3
     4TEMPLATE = app
     5CONFIG += thread
     6TARGET = ignyte
     7target.path = $${PREFIX}/bin
     8INSTALLS += target
     9
     10# Input
     11HEADERS += ignytegrabber.h mythsoap.h
     12SOURCES += main.cpp ignytegrabber.cpp mythsoap.cpp
  • mythmovies/mythmovies.pro

     
     1TEMPLATE = subdirs
     2
     3# Directories
     4SUBDIRS = mythmovies ignyte
     5
  • mythmovies/mythmovies/helperobjects.h

     
     1#ifndef HELPEROBJECTS_H_
     2#define HELPEROBJECTS_H_
     3
     4#include <qvaluevector.h>
     5
     6class Theater;
     7
     8typedef QValueVector<Theater> TheaterVector;
     9
     10class Movie
     11{
     12  public:
     13    QString rating;
     14    QString name;
     15    QString runningTime;
     16    QString showTimes;
     17    TheaterVector theaters;
     18    Movie()
     19    {
     20        rating = "";
     21        name = "";
     22        runningTime = "";
     23        showTimes = "";
     24    }
     25};
     26
     27typedef QValueVector<Movie> MovieVector;
     28
     29class Theater
     30{
     31  public:
     32    QString name;
     33    QString address;
     34    MovieVector movies;
     35    QString showTimes;
     36    Theater()
     37    {
     38        name = "";
     39        address = "";
     40    }
     41};
     42
     43#endif
  • mythmovies/mythmovies/moviesui.cpp

     
     1#include <qtimer.h>
     2#include <qapplication.h>
     3
     4#include <mythtv/mythcontext.h>
     5#include <mythtv/uitypes.h>
     6#include <qprocess.h>
     7
     8#include "moviesui.h"
     9
     10namespace
     11{
     12    struct sAscendingMovieOrder
     13    {
     14        bool operator()(const Movie& start,const Movie& end)
     15        {
     16            return start.name < end.name;
     17        }
     18    };
     19   
     20        //Taken from MythVideo
     21    // Execute an external command and return results in string
     22    // probably should make this routing async vs polling like this
     23    // but it would require a lot more code restructuring
     24    QString executeExternal(const QStringList &args, const QString &purpose)
     25    {
     26        QString ret = "";
     27        QString err = "";
     28
     29        VERBOSE(VB_GENERAL, QString("%1: Executing '%2'").arg(purpose).
     30                arg(args.join(" ")).local8Bit() );
     31        QProcess proc(args);
     32
     33        QString cmd = args[0];
     34        QFileInfo info(cmd);
     35
     36        if (!info.exists())
     37        {
     38            err = QString("\"%1\" failed: does not exist").arg(cmd.local8Bit());
     39        }
     40        else if (!info.isExecutable())
     41        {
     42            err = QString("\"%1\" failed: not executable").arg(cmd.local8Bit());
     43        }
     44        else if (proc.start())
     45        {
     46            while (true)
     47            {
     48                while (proc.canReadLineStdout() || proc.canReadLineStderr())
     49                {
     50                    if (proc.canReadLineStdout())
     51                    {
     52                        ret +=
     53                                QString::fromUtf8(proc.readLineStdout(), -1) + "\n";
     54                    }
     55
     56                    if (proc.canReadLineStderr())
     57                    {
     58                        if (err == "")
     59                        {
     60                            err = cmd + ": ";
     61                        }
     62
     63                        err +=
     64                                QString::fromUtf8(proc.readLineStderr(), -1) + "\n";
     65                    }
     66                }
     67
     68                if (proc.isRunning())
     69                {
     70                    qApp->processEvents();
     71                    usleep(10000);
     72                }
     73                else
     74                {
     75                    if (!proc.normalExit())
     76                    {
     77                        err = QString("\"%1\" failed: Process exited "
     78                                "abnormally").arg(cmd.local8Bit());
     79                    }
     80
     81                    break;
     82                }
     83            }
     84        }
     85        else
     86        {
     87            err = QString("\"%1\" failed: Could not start process")
     88                    .arg(cmd.local8Bit());
     89        }
     90
     91        while (proc.canReadLineStdout() || proc.canReadLineStderr())
     92        {
     93            if (proc.canReadLineStdout())
     94            {
     95                ret += QString::fromUtf8(proc.readLineStdout(),-1) + "\n";
     96            }
     97
     98            if (proc.canReadLineStderr())
     99            {
     100                if (err == "")
     101                {
     102                    err = cmd + ": ";
     103                }
     104
     105                err += QString::fromUtf8(proc.readLineStderr(), -1) + "\n";
     106            }
     107        }
     108
     109        if (err != "")
     110        {
     111            QString tempPurpose(purpose);
     112
     113            if (tempPurpose == "")
     114                tempPurpose = "Command";
     115
     116            VERBOSE(VB_IMPORTANT, err);
     117            MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     118                                      QObject::tr(tempPurpose + " failed"),
     119                                      QObject::tr(err + "\n\nCheck MythMovies Settings"));
     120            ret = "#ERROR";
     121        }
     122
     123        //VERBOSE(VB_IMPORTANT, ret);
     124        return ret;
     125    }
     126}
     127
     128MoviesUI::MoviesUI(MythMainWindow *parent, QString windowName,
     129                   QString themeFilename, const char *name)
     130    : MythThemedDialog(parent, windowName, themeFilename, name)
     131{
     132    query = new MSqlQuery(MSqlQuery::InitCon());
     133    subQuery = new MSqlQuery(MSqlQuery::InitCon());
     134    aboutPopup = NULL;
     135    menuPopup = NULL;
     136    //m_movieTree = new GenericTree("Theaters", 0, false);
     137    m_currentMode = "Undefined";
     138    setupTheme();
     139}
     140
     141MoviesUI::~MoviesUI()
     142{
     143    //do nothing, yet
     144}
     145
     146void MoviesUI::setupTheme(void)
     147{
     148    m_movieTreeUI = getUIManagedTreeListType("movietreelist");
     149    m_currentNode = NULL;
     150    m_movieTreeUI->showWholeTree(true);
     151    m_movieTreeUI->colorSelectables(true);
     152
     153    connect(m_movieTreeUI, SIGNAL(nodeSelected(int, IntVector*)),
     154            this, SLOT(handleTreeListSelection(int, IntVector*)));
     155    connect(m_movieTreeUI, SIGNAL(nodeEntered(int, IntVector*)),
     156            this, SLOT(handleTreeListEntry(int, IntVector*)));
     157
     158
     159    m_movieTitle = getUITextType("movietitle");
     160    if (!m_movieTitle)
     161        VERBOSE(VB_IMPORTANT, "moviesui.o: Couldn't find text area movietitle");
     162
     163    m_movieRating = getUITextType("ratingvalue");
     164    if (!m_movieRating)
     165        VERBOSE(VB_IMPORTANT,
     166                "moviesui.o: Couldn't find text area ratingvalue");
     167
     168    m_movieRunningTime = getUITextType("runningtimevalue");
     169    if (!m_movieRunningTime)
     170        VERBOSE(VB_IMPORTANT,
     171                "moviesui.o: Couldn't find text area runningtimevalue");
     172
     173    m_movieShowTimes = getUITextType("showtimesvalue");
     174    if (!m_movieShowTimes)
     175        VERBOSE(VB_IMPORTANT,
     176                "moviesui.o: Couldn't find text area showtimesvalue");
     177
     178    m_theaterName = getUITextType("theatername");
     179    if (!m_theaterName)
     180        VERBOSE(VB_IMPORTANT,
     181                "moviesui.o: Couldn't find text area theatername");
     182    gContext->ActivateSettingsCache(false);
     183    QString currentDate = QDate::currentDate().toString();
     184    QString lastDate = gContext->GetSetting("MythMovies.LastGrabDate");
     185    if (currentDate != lastDate)
     186    {
     187        VERBOSE(VB_IMPORTANT, "Movie Data Has Expired. Refreshing.");
     188        updateMovieTimes();
     189    }
     190
     191    gContext->ActivateSettingsCache(true);
     192
     193    updateDataTrees();
     194    drawDisplayTree();
     195    updateForeground();
     196}
     197
     198void MoviesUI::updateMovieTimes()
     199{
     200    gContext->ActivateSettingsCache(false);
     201    QString currentDate = QDate::currentDate().toString();
     202    query->exec("truncate table movies_showtimes");
     203    query->exec("truncate table movies_movies");
     204    query->exec("truncate table movies_theaters");
     205    QString grabber = gContext->GetSetting("MythMovies.Grabber");
     206    grabber.replace("%z", gContext->GetSetting("MythMovies.ZipCode"));
     207    grabber.replace("%r", gContext->GetSetting("MythMovies.Radius"));
     208    QStringList args = QStringList::split(' ', grabber);
     209    QString ret = executeExternal(args, "MythMovies Data Grabber");
     210    VERBOSE(VB_IMPORTANT, "Grabber Finished. Processing Data.");
     211    populateDatabaseFromGrabber(ret);
     212    gContext->SaveSetting("MythMovies.LastGrabDate", currentDate);
     213    gContext->ActivateSettingsCache(true);
     214}
     215
     216MovieVector MoviesUI::buildMovieDataTree()
     217{
     218    MovieVector ret;
     219    if (query->exec("select id, moviename, rating, runningtime from movies_movies order by moviename asc"))
     220    {
     221        while (query->next())
     222        {
     223            Movie m;
     224            m.name = query->value(1).toString();
     225            m.rating = query->value(2).toString();
     226            m.runningTime = query->value(3).toString();
     227            subQuery->prepare("select theatername, theateraddress, showtimes "
     228                    "from movies_showtimes left join movies_theaters "
     229                    "on movies_showtimes.theaterid = movies_theaters.id "
     230                    "where movies_showtimes.movieid = :MOVIEID");
     231            subQuery->bindValue(":MOVIEID", query->value(0).toString());
     232
     233            if (subQuery->exec())
     234            {
     235                while (subQuery->next())
     236                {
     237                    Theater t;
     238                    t.name = subQuery->value(0).toString();
     239                    t.address = subQuery->value(1).toString();
     240                    t.showTimes = subQuery->value(2).toString();
     241                    m.theaters.push_back(t);
     242                }
     243            }
     244            ret.push_back(m);
     245        }
     246    }
     247    return ret;
     248}
     249
     250TheaterVector MoviesUI::buildTheaterDataTree()
     251{
     252    TheaterVector ret;
     253    if (query->exec("select id, theatername, theateraddress from movies_theaters order by theatername asc"))
     254    {
     255        while (query->next())
     256        {
     257            Theater t;
     258            t.name = query->value(1).toString();
     259            t.address = query->value(2).toString();
     260            subQuery->prepare("select moviename, rating, runningtime, showtimes "
     261                    "from movies_showtimes left join movies_movies "
     262                    "on movies_showtimes.movieid = movies_movies.id "
     263                    "where movies_showtimes.theaterid = :THEATERID");
     264            subQuery->bindValue(":THEATERID", query->value(0).toString());
     265
     266            if (subQuery->exec())
     267            {
     268                while (subQuery->next())
     269                {
     270                    Movie m;
     271                    m.name = subQuery->value(0).toString();
     272                    m.rating = subQuery->value(1).toString();
     273                    m.runningTime = subQuery->value(2).toString();
     274                    m.showTimes = subQuery->value(3).toString();
     275                    t.movies.push_back(m);
     276                }
     277            }
     278
     279            ret.push_back(t);
     280        }
     281    }
     282    return ret;
     283}
     284
     285void MoviesUI::keyPressEvent(QKeyEvent *e)
     286{
     287    bool handled = false;
     288    QStringList actions;
     289    gContext->GetMainWindow()->TranslateKeyPress("Movies", e, actions);
     290
     291    for (unsigned int i = 0; i < actions.size() && !handled; i++)
     292    {
     293        QString action = actions[i];
     294        //cout << "Action: " << action << endl << flush;
     295        handled = true;
     296        if (action == "SELECT")
     297            m_movieTreeUI->select();
     298        else if (action == "MENU")
     299            showMenu();
     300        else if (action == "INFO")
     301            //todo: redirect info to an info screen via imdb.pl
     302            showAbout();
     303        else if (action == "UP")
     304            m_movieTreeUI->moveUp();
     305        else if (action == "DOWN")
     306            m_movieTreeUI->moveDown();
     307        else if (action == "LEFT")
     308            m_movieTreeUI->popUp();
     309        else if (action == "RIGHT")
     310            m_movieTreeUI->pushDown();
     311        else if (action == "PAGEUP")
     312            m_movieTreeUI->pageUp();
     313        else if (action == "PAGEDOWN")
     314            m_movieTreeUI->pageDown();
     315        else if (action == "INCSEARCH")
     316            m_movieTreeUI->incSearchStart();
     317        else if (action == "INCSEARCHNEXT")
     318            m_movieTreeUI->incSearchNext();
     319        else
     320            handled = false;
     321    }
     322
     323    if (!handled)
     324        MythThemedDialog::keyPressEvent(e);
     325}
     326
     327void MoviesUI::showMenu()
     328{
     329    if (menuPopup)
     330        return;
     331    menuPopup = new MythPopupBox(gContext->GetMainWindow(), "menuPopup");
     332    menuPopup->addLabel("MythMovies Menu");
     333    updateButton = menuPopup->addButton("Update Movie Times", this, SLOT(slotUpdateMovieTimes()));
     334    OKButton = menuPopup->addButton("Close Menu", this, SLOT(closeMenu()));
     335    OKButton->setFocus();
     336    menuPopup->ShowPopup(this, SLOT(closeMenu()));
     337}
     338
     339void MoviesUI::slotUpdateMovieTimes()
     340{
     341    VERBOSE(VB_IMPORTANT, "Doing Manual Movie Times Update");
     342    updateMovieTimes();
     343    updateDataTrees();
     344    drawDisplayTree();
     345    menuPopup->hide();
     346    delete menuPopup;
     347    menuPopup = NULL;
     348}
     349
     350void MoviesUI::closeMenu()
     351{
     352    if (!menuPopup)
     353        return;
     354    menuPopup->hide();
     355    delete menuPopup;
     356    menuPopup = NULL;
     357}
     358
     359void MoviesUI::showAbout()
     360{
     361    if (aboutPopup)
     362        return;
     363
     364    aboutPopup = new MythPopupBox(gContext->GetMainWindow(), "aboutPopup");
     365    aboutPopup->addLabel("MythMovies");
     366    aboutPopup->addLabel("Copyright (c) 2006 Josh Lefler.");
     367    aboutPopup->addLabel("Released under GNU GPL v2");
     368    aboutPopup->addLabel("Special Thanks to Ignyte.com for\nproviding the "
     369                         "listings data.\n and the #mythtv IRC channel for "
     370                         "assistance.");
     371    OKButton = aboutPopup->addButton(QString("Close"), this,
     372                                     SLOT(closeAboutPopup()));
     373    OKButton->setFocus();
     374    aboutPopup->ShowPopup(this,SLOT(closeAboutPopup()));
     375}
     376
     377void MoviesUI::closeAboutPopup(void)
     378{
     379    if (!aboutPopup)
     380        return;
     381
     382    aboutPopup->hide();
     383    delete aboutPopup;
     384    aboutPopup = NULL;
     385}
     386
     387void MoviesUI::handleTreeListEntry(int nodeInt, IntVector *)
     388{
     389    m_currentNode = m_movieTreeUI->getCurrentNode();
     390    if (nodeInt == 0)
     391    {
     392        m_currentMode = m_currentNode->getString();
     393        m_theaterName->SetText("");
     394        m_movieTitle->SetText("");
     395        m_movieRunningTime->SetText("");
     396    }
     397    else
     398    {
     399        if (m_currentMode == "By Theater")
     400        {
     401            if (nodeInt < 0)
     402            {
     403                int theaterInt = -nodeInt;
     404                m_currentTheater = &m_dataTreeByTheater.at(theaterInt - 1);
     405                m_theaterName->SetText(m_currentTheater->name + " - " +
     406                                       m_currentTheater->address);
     407                m_movieTitle->SetText("");
     408                m_movieRating->SetText("");
     409                m_movieShowTimes->SetText("");
     410                m_movieRunningTime->SetText("");
     411            }
     412            else
     413            {
     414                int theaterInt = nodeInt / 100;
     415                int movieInt = nodeInt - (theaterInt * 100);
     416                Theater t = m_dataTreeByTheater.at(theaterInt - 1);
     417                Movie m = t.movies.at(movieInt - 1);
     418                m_movieTitle->SetText(m.name);
     419                m_movieRating->SetText(m.rating);
     420                m_movieRunningTime->SetText(m.runningTime);
     421                QStringList st = QStringList::split("|", m.showTimes);
     422                QString buf;
     423                int i = 0;
     424                for (QStringList::Iterator it = st.begin(); it != st.end();
     425                     ++it)
     426                {
     427                    if (i % 4 == 0 && i != 0)
     428                        buf+= "\n";
     429                    buf += (*it).stripWhiteSpace() + " ";
     430                    i++;
     431                }
     432                m_movieShowTimes->SetText(buf);
     433            }
     434        }
     435        else if (m_currentMode == "By Movie")
     436        {
     437            if (nodeInt < 0)
     438            {
     439                int movieInt = -nodeInt;
     440                m_currentMovie = &m_dataTreeByMovie.at(movieInt - 1);
     441                m_movieTitle->SetText(m_currentMovie->name);
     442                m_movieRating->SetText(m_currentMovie->rating);
     443                m_movieRunningTime->SetText(m_currentMovie->runningTime);
     444                m_movieShowTimes->SetText("");
     445                m_theaterName->SetText("");
     446            }
     447            else
     448            {
     449                int movieInt =  nodeInt / 100;
     450                int theaterInt = nodeInt - (movieInt * 100);
     451                Movie m = m_dataTreeByMovie.at(movieInt - 1);
     452                Theater t = m.theaters.at(theaterInt - 1);
     453                QStringList st = QStringList::split("|", t.showTimes);
     454                QString buf;
     455                int i = 0;
     456                for (QStringList::Iterator it = st.begin(); it != st.end();
     457                     ++it)
     458                {
     459                    if (i % 4 == 0 && i != 0)
     460                        buf+= "\n";
     461                    buf += (*it).stripWhiteSpace() + " ";
     462                    i++;
     463                }
     464                m_movieShowTimes->SetText(buf);
     465                m_theaterName->SetText(t.name + " - " + t.address);
     466            }
     467        }
     468        else
     469        {
     470            //cerr << "Entry was called with an undefined mode." << endl << flush;
     471        }
     472    }
     473}
     474
     475void MoviesUI::handleTreeListSelection(int nodeInt, IntVector *)
     476{
     477    //perhaps the same as info?
     478    //VERBOSE(VB_IMPORTANT, QString("In Selection with %1").arg(nodeInt));
     479}
     480
     481GenericTree* MoviesUI::getDisplayTreeByTheater()
     482{
     483    TheaterVector *theaters;
     484    theaters = &m_dataTreeByTheater;
     485    int tbase = 0;
     486    GenericTree *parent = new GenericTree("By Theater", 0, false);
     487    for (unsigned int i = 0; i < theaters->size(); i++)
     488    {
     489        int mbase = 0;
     490        Theater x = theaters->at(i);
     491        GenericTree *node = new GenericTree(x.name, --tbase, false);
     492        for (unsigned int m =0; m < x.movies.size(); m++)
     493        {
     494            Movie y = x.movies.at(m);
     495            node->addNode(y.name, (tbase * -100) + ++mbase, true);
     496        }
     497        parent->addNode(node);
     498    }
     499    return parent;
     500}
     501
     502GenericTree* MoviesUI::getDisplayTreeByMovie()
     503{
     504    MovieVector *movies;
     505    movies = &m_dataTreeByMovie;
     506    int mbase = 0;
     507    GenericTree *parent = new GenericTree("By Movie", 0, false);
     508    for (unsigned int i = 0; i < movies->size(); i++)
     509    {
     510        int tbase = 0;
     511        Movie x = movies->at(i);
     512        GenericTree *node = new GenericTree(x.name, --mbase, false);
     513        for (unsigned int m = 0; m < x.theaters.size(); m++)
     514        {
     515            Theater y = x.theaters.at(m);
     516            node->addNode(y.name, (mbase * -100) + ++tbase, true);
     517        }
     518        parent->addNode(node);
     519    }
     520    return parent;
     521}
     522void MoviesUI::updateDataTrees()
     523{
     524    m_dataTreeByTheater = buildTheaterDataTree();
     525    m_dataTreeByMovie = buildMovieDataTree();
     526}
     527
     528void MoviesUI::drawDisplayTree()
     529{
     530    m_movieTree = new GenericTree("Theaters", 0, false);
     531    m_movieTree->addNode(getDisplayTreeByTheater());
     532    m_movieTree->addNode(getDisplayTreeByMovie());
     533    m_movieTreeUI->assignTreeData(m_movieTree);
     534    m_movieTreeUI->popUp();
     535    m_movieTreeUI->popUp();
     536    m_movieTreeUI->popUp();
     537    m_movieTreeUI->enter();
     538    m_currentMode = m_movieTreeUI->getCurrentNode()->getString();
     539}
     540
     541void MoviesUI::populateDatabaseFromGrabber(QString ret)
     542{
     543     //stores error returns
     544    QString error;
     545    int errorLine;
     546    int errorColumn;
     547    QDomDocument doc;
     548    QDomNode n;
     549    if (!doc.setContent(ret, false, &error, &errorLine, &errorColumn))
     550    {
     551        VERBOSE(VB_IMPORTANT, QString("Error parsing data from grabber: "
     552                "Error: %1 Location Line: %2 Column %3")
     553                .arg(error) .arg(errorLine) .arg(errorColumn));
     554        exit(-1);
     555    }
     556    QDomElement root = doc.documentElement();
     557    n = root.firstChild();
     558    //loop through each theater
     559    while (!n.isNull())
     560    {
     561        processTheatre(n);
     562        //list.push_back(t);
     563        n = n.nextSibling();
     564    }
     565}
     566
     567void MoviesUI::processTheatre(QDomNode &n)
     568{
     569    Theater t;
     570    //Movie m;
     571    QDomNode movieNode;
     572    const QDomElement theater = n.toElement();
     573    QDomNode child = theater.firstChild();
     574    while (!child.isNull())
     575    {
     576        if (!child.isNull())
     577        {
     578            if (child.toElement().tagName() == "Name")
     579            {
     580                t.name = child.firstChild().toText().data();
     581                if (t.name.isNull())
     582                    t.name = "";
     583            }
     584
     585            if (child.toElement().tagName() == "Address")
     586            {
     587                t.address = child.firstChild().toText().data();
     588                if (t.address.isNull())
     589                    t.address = "";
     590            }
     591            if (child.toElement().tagName() == "Movies")
     592            {
     593                query->prepare("INSERT INTO movies_theaters "
     594                        "(theatername, theateraddress)"
     595                        "values (:NAME,:ADDRESS)");
     596
     597                query->bindValue(":NAME", t.name.utf8());
     598                query->bindValue(":ADDRESS", t.address.utf8());
     599                if (!query->exec())
     600                {
     601                    VERBOSE(VB_IMPORTANT, "Failure to Insert Theater");
     602                }
     603                int lastid = query->lastInsertId().toInt();
     604                movieNode = child.firstChild();
     605                while (!movieNode.isNull())
     606                {
     607                    processMovie(movieNode, lastid);
     608                    //t.movies.push_back(m);
     609                    movieNode = movieNode.nextSibling();
     610                }
     611            }
     612
     613            child = child.nextSibling();
     614        }
     615    }
     616}
     617
     618void MoviesUI::processMovie(QDomNode &n, int theaterId)
     619{
     620    Movie m;
     621    QDomNode mi = n.firstChild();
     622    int movieId = 0;
     623    while (!mi.isNull())
     624    {
     625        if (mi.toElement().tagName() == "Name")
     626        {
     627            m.name = mi.firstChild().toText().data();
     628            if (m.name.isNull())
     629                m.name = "";
     630        }
     631        if (mi.toElement().tagName() == "Rating")
     632        {
     633            m.rating = mi.firstChild().toText().data();
     634            if (m.rating.isNull())
     635                m.rating = "";
     636        }
     637        if (mi.toElement().tagName() == "ShowTimes")
     638        {
     639            m.showTimes = mi.firstChild().toText().data();
     640            if (m.showTimes.isNull())
     641                m.showTimes = "";
     642        }
     643        if (mi.toElement().tagName() == "RunningTime")
     644        {
     645            m.runningTime = mi.firstChild().toText().data();
     646            if (m.runningTime.isNull())
     647                m.runningTime = "";
     648        }
     649        mi = mi.nextSibling();
     650    }
     651   
     652    query->prepare("SELECT id FROM movies_movies Where moviename = :NAME");
     653    query->bindValue(":NAME", m.name.utf8());
     654    if (query->exec() && query->next())
     655    {
     656        movieId = query->value(0).toInt();
     657    }
     658    else
     659    {
     660        query->prepare("INSERT INTO movies_movies ("
     661                "moviename, rating, runningtime) values ("
     662                ":NAME, :RATING, :RUNNINGTIME)");
     663        query->bindValue(":NAME", m.name.utf8());
     664        query->bindValue(":RATING", m.rating.utf8());
     665        query->bindValue(":RUNNINGTIME", m.runningTime.utf8());
     666        if (query->exec())
     667        {
     668            movieId = query->lastInsertId().toInt();
     669        }
     670        else
     671        {
     672            VERBOSE(VB_IMPORTANT, "Failure to Insert Movie");
     673        }
     674    }
     675    query->prepare("INSERT INTO movies_showtimes ("
     676            "theaterid, movieid, showtimes) values ("
     677            ":THEATERID, :MOVIEID, :SHOWTIMES)");
     678    query->bindValue(":THEATERID", theaterId);
     679    query->bindValue(":MOVIEID", movieId);
     680    query->bindValue(":SHOWTIMES", m.showTimes);
     681
     682    if (!query->exec())
     683    {
     684        VERBOSE(VB_IMPORTANT, "Failure to Link Movie to Theater");
     685    }
     686}
     687
     688
  • mythmovies/mythmovies/movies-ui-wide.xml

    Property changes on: mythmovies/mythmovies/moviesui.cpp
    ___________________________________________________________________
    Name: svn:executable
       + *
    
     
     1<mythuitheme>
     2    <window name="moviesui">
     3        <font name="active" face="Trebuchet MS">
     4            <color>#ffffff</color>
     5            <size>18</size>
     6            <bold>yes</bold>
     7        </font>
     8
     9        <font name="inactive" face="Trebuchet MS">
     10            <color>#9999cc</color>
     11            <size>18</size>
     12            <bold>yes</bold>
     13        </font>
     14
     15        <font name="selectable" face="Trebuchet MS">
     16            <color>#8cdeff</color>
     17            <size>18</size>
     18            <bold>yes</bold>
     19        </font>
     20
     21        <font name="largetitle" face="Trebuchet MS">
     22            <color>#ffffff</color>
     23            <dropcolor>#000000</dropcolor>
     24            <size>32</size>
     25            <shadow>3,3</shadow>
     26            <bold>yes</bold>
     27        </font>
     28
     29        <font name="infofont" face="Trebuchet MS">
     30            <color>#ffffff</color>
     31            <size>16</size>
     32            <bold>yes</bold>
     33        </font>
     34
     35        <font name="infofontunderline" face="Arial">
     36            <color>#ffffff</color>
     37            <size>16</size>
     38            <bold>yes</bold>
     39            <underline>yes</underline>
     40        </font>
     41
     42        <container name="background">
     43            <image name="filler" draworder="0" fleximage="yes">
     44                <filename>background.png</filename> <!-- 1280x326 -->
     45                <position>0,48</position>
     46            </image>
     47            <image name="titlelines" draworder="0" fleximage="no">
     48                <filename>trans-titles.png</filename> <!-- 1280x326 -->
     49                <position>0,48</position>
     50            </image>
     51            <image name="infofiller" draworder="0" fleximage="no">
     52                <filename>pf-top.png</filename> <!-- 1152x260 -->
     53                <position>64,412</position>
     54            </image>
     55        </container>
     56
     57        <container name="movieselector">
     58            <area>8,52,1264,310</area>
     59            <managedtreelist name="movietreelist" draworder="1" bins="2">
     60                <area>32,0,1200,296</area>
     61                <image function="selectionbar" filename="mv_selectionbar.png"></image>
     62                <image function="uparrow" filename="mv_up_arrow.png"></image>
     63                <image function="downarrow" filename="mv_down_arrow.png"></image>
     64                <image function="leftarrow" filename="mv_left_arrow.png"></image>
     65                <image function="rightarrow" filename="mv_right_arrow.png"></image>
     66                <bin number="1">
     67                    <area>56,28,288,250</area>
     68                    <fcnfont name="active" function="active"></fcnfont>
     69                    <fcnfont name="inactive" function="inactive"></fcnfont>
     70                    <fcnfont name="active" function="selected"></fcnfont>
     71                    <fcnfont name="selectable" function="selectable"></fcnfont>
     72                </bin>
     73                <bin number="2">
     74                    <area>384,0,816,296</area>
     75                    <fcnfont name="active" function="active"></fcnfont>
     76                    <fcnfont name="active" function="selected"></fcnfont>
     77                    <fcnfont name="inactive" function="inactive"></fcnfont>
     78                    <fcnfont name="selectable" function="selectable"></fcnfont>
     79                </bin>
     80            </managedtreelist>
     81
     82            <image name="showinglines" draworder="2" fleximage="yes">
     83                <filename>showings.png</filename>
     84                <position>0,0</position>
     85            </image>
     86        </container>
     87
     88        <container name="theater_info">
     89            <area>25,363,750,55</area>
     90            <textarea name="theatername" draworder="6">
     91                <area>10,10,2000,55</area>
     92                <font>infofont</font>
     93            </textarea>
     94        </container>
     95
     96        <container name="movie_info">
     97            <area>64,412,1152,260</area>
     98
     99            <textarea name="movietitle" draworder="6">
     100                <area>32,15,752,60</area>
     101                <font>largetitle</font>
     102            </textarea>
     103
     104            <textarea name="rating" draworder="6">
     105                <area>32,100,140,35</area>
     106                <font>infofont</font>
     107                <value>Rating:</value>
     108            </textarea>
     109
     110            <textarea name="ratingvalue" draworder="6">
     111                <area>172,100,580,35</area>
     112                <font>infofont</font>
     113            </textarea>
     114
     115            <textarea name="runningtime" draworder="6">
     116                <area>32,75,300,35</area>
     117                <font>infofont</font>
     118                <value>Running Time:</value>
     119            </textarea>
     120
     121            <textarea name="runningtimevalue" draworder="6">
     122                <area>270,75,500,35</area>
     123                <font>infofont</font>
     124            </textarea>
     125
     126            <textarea name="showtimes" draworder="6">
     127                <area>32,130,140,35</area>
     128                <font>infofontunderline</font>
     129                <value>Showtimes</value>
     130            </textarea>
     131
     132            <textarea name="showtimesvalue" draworder="6">
     133                <area>32,160,10000,100</area><!--set absurdly large to prevent trimming-->
     134                <font>infofont</font>
     135            </textarea> 
     136
     137        </container>
     138
     139    </window>
     140
     141</mythuitheme>
  • mythmovies/mythmovies/mythmovies.pro

     
     1include ( ../../mythconfig.mak )
     2include ( ../../settings.pro )
     3
     4TEMPLATE = lib
     5CONFIG += plugin thread
     6TARGET = mythmovies
     7target.path = $${LIBDIR}/mythtv/plugins
     8INSTALLS += target
     9
     10installfiles.path = $${PREFIX}/share/mythtv
     11installfiles.files = movie_settings.xml
     12uifiles.path = $${PREFIX}/share/mythtv/themes/default
     13uifiles.files = movies-ui.xml
     14
     15INSTALLS += uifiles installfiles
     16
     17# Input
     18HEADERS += moviesui.h helperobjects.h moviessettings.h
     19
     20SOURCES += main.cpp moviesui.cpp moviessettings.cpp
     21
     22macx {
     23    QMAKE_LFLAGS += -flat_namespace -undefined suppress
     24}
  • mythmovies/mythmovies/moviessettings.cpp

     
     1#include "moviessettings.h"
     2
     3static HostLineEdit *ZipCode()
     4{
     5    HostLineEdit *gc = new HostLineEdit("MythMovies.ZipCode");
     6    gc->setLabel("Zip Code");
     7    gc->setValue("00000");
     8    gc->setHelpText("Enter your zip code here. "
     9                    "MythMovies will use it to find local theaters.");
     10    return gc;
     11}
     12
     13static HostLineEdit *Radius()
     14{
     15    HostLineEdit *gc = new HostLineEdit("MythMovies.Radius");
     16    gc->setLabel("Radius");
     17    gc->setValue("20");
     18    gc->setHelpText("Enter the radius (in miles) to search for theaters. "
     19            "Numbers larger than 50 will be reduced to 50.");
     20    return gc;
     21}
     22
     23static HostLineEdit *Grabber()
     24{
     25    HostLineEdit *gc = new HostLineEdit("MythMovies.Grabber");
     26    gc->setLabel("Grabber:");
     27    gc->setValue(QString("%1/bin/ignyte --zip %z --radius %r").arg(gContext->GetInstallPrefix()));
     28    gc->setHelpText("This is the path to the data grabber to use."
     29                    "If you are in the United States, the default grabber "
     30                    "should be fine. If you are elsewhere, you'll need a "
     31                    "different grabber. %z will be replaced by the zip code"
     32                    "setting. %r will be replaced by the radius setting."
     33                   );
     34    return gc;
     35}
     36MoviesSettings::MoviesSettings()
     37{
     38    VerticalConfigurationGroup *settings =
     39            new VerticalConfigurationGroup(false);
     40    settings->setLabel("MythMovies Settings");
     41    settings->addChild(ZipCode());
     42    settings->addChild(Radius());
     43    settings->addChild(Grabber());
     44    addChild(settings);
     45}
  • mythmovies/mythmovies/main.cpp

     
     1#include <mythtv/mythcontext.h>
     2#include <mythtv/mythdbcon.h>
     3
     4#include "moviesui.h"
     5#include "moviessettings.h"
     6
     7extern "C" {
     8    int mythplugin_init(const char *libversion);
     9    int mythplugin_run(void);
     10    int mythplugin_config(void);
     11}
     12
     13void runMovies(void);
     14int setupDatabase();
     15MythPopupBox *configPopup;
     16const QString dbVersion = "4";
     17
     18void setupKeys(void)
     19{
     20    //REG_JUMP("MythMovies", "Movie Times Screen", "", runMovies);
     21}
     22
     23int mythplugin_init(const char *libversion)
     24{
     25    if (!gContext->TestPopupVersion("mythmovies", libversion,
     26                                    MYTH_BINARY_VERSION))
     27    {
     28        VERBOSE(VB_IMPORTANT,
     29                QString("libmythmovies.so/main.o: binary version mismatch"));
     30        return -1;
     31    }
     32    int dbSetup = setupDatabase();
     33    if (dbSetup == -1)
     34    {
     35        VERBOSE(VB_IMPORTANT, "MythMovies cannot continue without"
     36                "a proper database setup.");
     37        return -1;
     38    }
     39    setupKeys();
     40    return 0;
     41}
     42
     43void runMovies(void)
     44{
     45    gContext->addCurrentLocation("mythmovies");
     46    MoviesUI moviesui(gContext->GetMainWindow(), "moviesui", "movies-");
     47    moviesui.exec();
     48    gContext->removeCurrentLocation();
     49}
     50
     51void runConfig()
     52{
     53    MoviesSettings settings;
     54    settings.exec();
     55}
     56
     57int mythplugin_run(void)
     58{
     59    gContext->ActivateSettingsCache(false);
     60    if (gContext->GetSetting("MythMovies.ZipCode") == "" ||
     61        gContext->GetSetting("MythMovies.Radius") == "" ||
     62        gContext->GetSetting("MythMovies.Grabber") == "")
     63    {
     64        runConfig();
     65    }
     66    if (gContext->GetSetting("MythMovies.ZipCode") == "" ||
     67        gContext->GetSetting("MythMovies.Radius") == "" ||
     68        gContext->GetSetting("MythMovies.Grabber") == "")
     69    {
     70        VERBOSE(VB_IMPORTANT,
     71                QString("Invalid configuration options supplied."));
     72        gContext->ActivateSettingsCache(true);
     73        return 0;
     74    }
     75    gContext->ActivateSettingsCache(true);
     76    runMovies();
     77    return 0;
     78}
     79
     80int mythplugin_config(void)
     81{
     82    runConfig();
     83    return 0;
     84}
     85
     86int setupDatabase()
     87{
     88    //we just throw away the old tables rather than worry about a database upgrade since movie times data
     89    //is highly transient and losing it isn't harmful
     90    if (dbVersion == gContext->GetSetting("MythMovies.DatabaseVersion"))
     91        return 0;
     92
     93    gContext->SaveSetting("MythMovies.LastGrabDate", "");
     94
     95    VERBOSE(VB_GENERAL, "Setting Up MythMovies Database Tables");
     96
     97    MSqlQuery query(MSqlQuery::InitCon());
     98    if (query.exec("DROP TABLE IF EXISTS movies_showtimes, movies_theaters, movies_movies"))
     99    {
     100        bool a = query.exec("CREATE TABLE movies_theaters ("
     101                "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
     102                "theatername VARCHAR(100),"
     103                "theateraddress VARCHAR(100)"
     104                ");");
     105
     106        bool b = query.exec("CREATE TABLE movies_movies ("
     107                "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
     108                "moviename VARCHAR(255),"
     109                "rating VARCHAR(10),"
     110                "runningtime VARCHAR(50)"
     111                ");");
     112
     113        bool c = query.exec("CREATE TABLE movies_showtimes ("
     114                "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
     115                "theaterid INT NOT NULL,"
     116                "movieid INT NOT NULL,"
     117                "showtimes VARCHAR(255)"
     118                ");");
     119
     120        if (!a || !b || !c)
     121        {
     122            VERBOSE(VB_IMPORTANT, "Failed to create MythMovies Tables");
     123            return -1;
     124        }
     125        else
     126        {
     127            gContext->SaveSetting("MythMovies.DatabaseVersion", dbVersion);
     128            VERBOSE(VB_GENERAL, "MythMovies Database Setup Complete");
     129            return 0;
     130        }
     131    }
     132    else
     133    {
     134        VERBOSE(VB_IMPORTANT, "Failed to delete old MythMovies Tables");
     135        return -1;
     136    }
     137}
     138
  • mythmovies/mythmovies/moviesui.h

     
     1#ifndef MOVIESUI_H_
     2#define MOVIESUI_H_
     3
     4#include <mythtv/mythdialogs.h>
     5#include <mythtv/mythdbcon.h>
     6
     7#include "helperobjects.h"
     8
     9
     10class QTimer;
     11
     12class MoviesUI : public MythThemedDialog
     13{
     14    Q_OBJECT
     15  public:
     16    typedef QValueVector<int> IntVector;
     17
     18    MoviesUI(MythMainWindow *parent, QString windowName,
     19             QString themeFilename, const char *name = 0);
     20    ~MoviesUI();
     21
     22  protected:
     23    void keyPressEvent(QKeyEvent *e);
     24    void showAbout();
     25    void showMenu();
     26  private:
     27    void updateDataTrees();
     28    void updateMovieTimes();
     29    void setupTheme(void);
     30    TheaterVector loadTrueTreeFromFile(QString);
     31    void drawDisplayTree();
     32    GenericTree* getDisplayTreeByMovie();
     33    GenericTree* getDisplayTreeByTheater();
     34    void populateDatabaseFromGrabber(QString ret);
     35    void processTheatre(QDomNode &n);
     36    void processMovie(QDomNode &n, int theaterId);
     37    TheaterVector buildTheaterDataTree();
     38    MovieVector buildMovieDataTree();
     39    TheaterVector m_dataTreeByTheater;
     40    Theater *m_currentTheater;
     41    MovieVector m_dataTreeByMovie;
     42    Movie *m_currentMovie;
     43    GenericTree           *m_movieTree;
     44    UIManagedTreeListType *m_movieTreeUI;
     45    GenericTree *m_currentNode;
     46    QString m_currentMode;
     47    QTimer *waitForReady;
     48    MSqlQuery *query;
     49    MSqlQuery *subQuery;
     50
     51    UITextType  *m_movieTitle;
     52    UITextType  *m_movieRating;
     53    UITextType  *m_movieRunningTime;
     54    UITextType  *m_movieShowTimes;
     55    UITextType  *m_theaterName;
     56    MythPopupBox *aboutPopup;
     57    MythPopupBox *menuPopup;
     58    QButton *OKButton;
     59    QButton *updateButton;
     60
     61  public slots:
     62    void handleTreeListSelection(int, IntVector*);
     63    void handleTreeListEntry(int, IntVector*);
     64    void checkDataReady();
     65
     66  protected slots:
     67    void closeAboutPopup();
     68    void closeMenu();
     69    void slotUpdateMovieTimes();
     70};
     71
     72#endif
  • mythmovies/mythmovies/moviessettings.h

     
     1#ifndef MOVIESSETTINGS_H
     2#define MOVIESSETTINGS_H
     3
     4#include <mythtv/settings.h>
     5
     6class MoviesSettings : virtual public ConfigurationWizard
     7{
     8  public:
     9    MoviesSettings();
     10};
     11
     12#endif
  • mythmovies/mythmovies/movies-ui.xml

     
     1<mythuitheme>
     2
     3    <window name="moviesui">
     4        <font name="active" face="Arial">
     5            <color>#ffffff</color>
     6            <size>18</size>
     7            <bold>yes</bold>
     8        </font>
     9   
     10        <font name="inactive" face="Arial">
     11            <color>#9999cc</color>
     12            <size>18</size>
     13            <bold>yes</bold>
     14        </font>
     15
     16        <font name="selectable" face="Arial">
     17            <color>#8cdeff</color>
     18            <size>18</size>
     19            <bold>yes</bold>
     20        </font>
     21
     22        <font name="largetitle" face="Arial">
     23            <color>#ffffff</color>
     24            <dropcolor>#000000</dropcolor>
     25            <size>20</size>
     26            <shadow>3,3</shadow>
     27        </font>
     28
     29        <font name="infofont" face="Arial">
     30            <color>#ffffff</color>
     31            <size>16</size>
     32            <bold>yes</bold>
     33        </font>
     34
     35        <font name="infofontunderline" face="Arial">
     36            <color>#ffffff</color>
     37            <size>16</size>
     38            <bold>yes</bold>
     39            <underline>yes</underline>
     40        </font>
     41   
     42        <container name="background">
     43            <image name="filler" draworder="0" fleximage="yes">
     44                <filename>background.png</filename>
     45                <position>0,10</position>
     46            </image>
     47            <image name="titlelines" draworder="0" fleximage="no">
     48                <filename>trans-titles.png</filename>
     49                <position>0,13</position>
     50            </image>
     51            <image name="infofiller" draworder="0" fleximage="no">
     52                <filename>pf-top.png</filename>
     53                <position>26,350</position>
     54            </image>
     55        </container>
     56        <container name="movieselector">
     57            <area>0,10,800,310</area>
     58            <managedtreelist name="movietreelist" draworder="2" bins="2">
     59                <area>40,10,720,270</area>
     60                <image function="selectionbar" filename="mv_selectionbar.png"></image>
     61                <image function="uparrow" filename="mv_up_arrow.png"></image>
     62                <image function="downarrow" filename="mv_down_arrow.png"></image>
     63                <image function="leftarrow" filename="mv_left_arrow.png"></image>
     64                <image function="rightarrow" filename="mv_right_arrow.png"></image>
     65                <bin number="1">
     66                    <area>30,16,190,250</area>
     67                    <fcnfont name="active" function="active"></fcnfont>
     68                    <fcnfont name="inactive" function="inactive"></fcnfont>
     69                    <fcnfont name="active" function="selected"></fcnfont>
     70                    <fcnfont name="selectable" function="selectable"></fcnfont>
     71                </bin>
     72                <bin number="2">
     73                    <area>235,10,535,270</area>
     74                    <fcnfont name="active" function="active"></fcnfont>
     75                    <fcnfont name="active" function="selected"></fcnfont>
     76                    <fcnfont name="inactive" function="inactive"></fcnfont>
     77                    <fcnfont name="selectable" function="selectable"></fcnfont>
     78                </bin>
     79            </managedtreelist>
     80
     81            <image name="showinglines" draworder="2" fleximage="yes">
     82                <filename>showings.png</filename>
     83                <position>0,0</position>
     84            </image>
     85        </container>
     86   
     87        <container name="theater_info">
     88            <area>25,300,750,55</area>
     89            <textarea name="theatername" draworder="6">
     90                <area>10,10,750,55</area>
     91                <font>infofont</font>
     92                <value>Theater name</value>
     93            </textarea>
     94        </container>
     95   
     96   
     97        <container name="movie_info">
     98            <area>25,355,750,220</area>
     99            <textarea name="movietitle" draworder="6">
     100                <area>13,5,500,50</area>
     101                <font>largetitle</font>
     102            </textarea>
     103
     104            <textarea name="rating" draworder="6">
     105                <area>13,50,150,35</area>
     106                <font>infofont</font>
     107                <value>Rating:</value>
     108            </textarea>
     109
     110            <textarea name="ratingvalue" draworder="6">
     111                <area>153,50,500,35</area>
     112                <font>infofont</font>
     113            </textarea>
     114           
     115            <textarea name="runningtime" draworder="6">
     116                <area>13,80,300,35</area>
     117                <font>infofont</font>
     118                <value>Running Time:</value>
     119            </textarea>
     120
     121            <textarea name="runningtimevalue" draworder="6">
     122                <area>303,80,500,35</area>
     123                <font>infofont</font>
     124            </textarea>
     125
     126
     127            <textarea name="showtimes" draworder="6">
     128                <area>13,110,300,35</area>
     129                <font>infofontunderline</font>
     130                <value>Show Times</value>
     131            </textarea>
     132
     133            <textarea name="showtimesvalue" draworder="6">
     134                <area>13,140,10000,100</area><!--set absurdly large to prevent trimming-->
     135                <font>infofont</font>
     136            </textarea>         
     137       
     138        </container>
     139   
     140    </window>
     141
     142</mythuitheme>
  • mythmovies/TODO

     
     1Rewrite the tree code once the new libmythui is ready
     2
  • mythmovies/COPYING

     
     1                    GNU GENERAL PUBLIC LICENSE
     2                       Version 2, June 1991
     3
     4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
     5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     6 Everyone is permitted to copy and distribute verbatim copies
     7 of this license document, but changing it is not allowed.
     8
     9                            Preamble
     10
     11  The licenses for most software are designed to take away your
     12freedom to share and change it.  By contrast, the GNU General Public
     13License is intended to guarantee your freedom to share and change free
     14software--to make sure the software is free for all its users.  This
     15General Public License applies to most of the Free Software
     16Foundation's software and to any other program whose authors commit to
     17using it.  (Some other Free Software Foundation software is covered by
     18the GNU Lesser General Public License instead.)  You can apply it to
     19your programs, too.
     20
     21  When we speak of free software, we are referring to freedom, not
     22price.  Our General Public Licenses are designed to make sure that you
     23have the freedom to distribute copies of free software (and charge for
     24this service if you wish), that you receive source code or can get it
     25if you want it, that you can change the software or use pieces of it
     26in new free programs; and that you know you can do these things.
     27
     28  To protect your rights, we need to make restrictions that forbid
     29anyone to deny you these rights or to ask you to surrender the rights.
     30These restrictions translate to certain responsibilities for you if you
     31distribute copies of the software, or if you modify it.
     32
     33  For example, if you distribute copies of such a program, whether
     34gratis or for a fee, you must give the recipients all the rights that
     35you have.  You must make sure that they, too, receive or can get the
     36source code.  And you must show them these terms so they know their
     37rights.
     38
     39  We protect your rights with two steps: (1) copyright the software, and
     40(2) offer you this license which gives you legal permission to copy,
     41distribute and/or modify the software.
     42
     43  Also, for each author's protection and ours, we want to make certain
     44that everyone understands that there is no warranty for this free
     45software.  If the software is modified by someone else and passed on, we
     46want its recipients to know that what they have is not the original, so
     47that any problems introduced by others will not reflect on the original
     48authors' reputations.
     49
     50  Finally, any free program is threatened constantly by software
     51patents.  We wish to avoid the danger that redistributors of a free
     52program will individually obtain patent licenses, in effect making the
     53program proprietary.  To prevent this, we have made it clear that any
     54patent must be licensed for everyone's free use or not licensed at all.
     55
     56  The precise terms and conditions for copying, distribution and
     57modification follow.
     58
     59                    GNU GENERAL PUBLIC LICENSE
     60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
     61
     62  0. This License applies to any program or other work which contains
     63a notice placed by the copyright holder saying it may be distributed
     64under the terms of this General Public License.  The "Program", below,
     65refers to any such program or work, and a "work based on the Program"
     66means either the Program or any derivative work under copyright law:
     67that is to say, a work containing the Program or a portion of it,
     68either verbatim or with modifications and/or translated into another
     69language.  (Hereinafter, translation is included without limitation in
     70the term "modification".)  Each licensee is addressed as "you".
     71
     72Activities other than copying, distribution and modification are not
     73covered by this License; they are outside its scope.  The act of
     74running the Program is not restricted, and the output from the Program
     75is covered only if its contents constitute a work based on the
     76Program (independent of having been made by running the Program).
     77Whether that is true depends on what the Program does.
     78
     79  1. You may copy and distribute verbatim copies of the Program's
     80source code as you receive it, in any medium, provided that you
     81conspicuously and appropriately publish on each copy an appropriate
     82copyright notice and disclaimer of warranty; keep intact all the
     83notices that refer to this License and to the absence of any warranty;
     84and give any other recipients of the Program a copy of this License
     85along with the Program.
     86
     87You may charge a fee for the physical act of transferring a copy, and
     88you may at your option offer warranty protection in exchange for a fee.
     89
     90  2. You may modify your copy or copies of the Program or any portion
     91of it, thus forming a work based on the Program, and copy and
     92distribute such modifications or work under the terms of Section 1
     93above, provided that you also meet all of these conditions:
     94
     95    a) You must cause the modified files to carry prominent notices
     96    stating that you changed the files and the date of any change.
     97
     98    b) You must cause any work that you distribute or publish, that in
     99    whole or in part contains or is derived from the Program or any
     100    part thereof, to be licensed as a whole at no charge to all third
     101    parties under the terms of this License.
     102
     103    c) If the modified program normally reads commands interactively
     104    when run, you must cause it, when started running for such
     105    interactive use in the most ordinary way, to print or display an
     106    announcement including an appropriate copyright notice and a
     107    notice that there is no warranty (or else, saying that you provide
     108    a warranty) and that users may redistribute the program under
     109    these conditions, and telling the user how to view a copy of this
     110    License.  (Exception: if the Program itself is interactive but
     111    does not normally print such an announcement, your work based on
     112    the Program is not required to print an announcement.)
     113
     114These requirements apply to the modified work as a whole.  If
     115identifiable sections of that work are not derived from the Program,
     116and can be reasonably considered independent and separate works in
     117themselves, then this License, and its terms, do not apply to those
     118sections when you distribute them as separate works.  But when you
     119distribute the same sections as part of a whole which is a work based
     120on the Program, the distribution of the whole must be on the terms of
     121this License, whose permissions for other licensees extend to the
     122entire whole, and thus to each and every part regardless of who wrote it.
     123
     124Thus, it is not the intent of this section to claim rights or contest
     125your rights to work written entirely by you; rather, the intent is to
     126exercise the right to control the distribution of derivative or
     127collective works based on the Program.
     128
     129In addition, mere aggregation of another work not based on the Program
     130with the Program (or with a work based on the Program) on a volume of
     131a storage or distribution medium does not bring the other work under
     132the scope of this License.
     133
     134  3. You may copy and distribute the Program (or a work based on it,
     135under Section 2) in object code or executable form under the terms of
     136Sections 1 and 2 above provided that you also do one of the following:
     137
     138    a) Accompany it with the complete corresponding machine-readable
     139    source code, which must be distributed under the terms of Sections
     140    1 and 2 above on a medium customarily used for software interchange; or,
     141
     142    b) Accompany it with a written offer, valid for at least three
     143    years, to give any third party, for a charge no more than your
     144    cost of physically performing source distribution, a complete
     145    machine-readable copy of the corresponding source code, to be
     146    distributed under the terms of Sections 1 and 2 above on a medium
     147    customarily used for software interchange; or,
     148
     149    c) Accompany it with the information you received as to the offer
     150    to distribute corresponding source code.  (This alternative is
     151    allowed only for noncommercial distribution and only if you
     152    received the program in object code or executable form with such
     153    an offer, in accord with Subsection b above.)
     154
     155The source code for a work means the preferred form of the work for
     156making modifications to it.  For an executable work, complete source
     157code means all the source code for all modules it contains, plus any
     158associated interface definition files, plus the scripts used to
     159control compilation and installation of the executable.  However, as a
     160special exception, the source code distributed need not include
     161anything that is normally distributed (in either source or binary
     162form) with the major components (compiler, kernel, and so on) of the
     163operating system on which the executable runs, unless that component
     164itself accompanies the executable.
     165
     166If distribution of executable or object code is made by offering
     167access to copy from a designated place, then offering equivalent
     168access to copy the source code from the same place counts as
     169distribution of the source code, even though third parties are not
     170compelled to copy the source along with the object code.
     171
     172  4. You may not copy, modify, sublicense, or distribute the Program
     173except as expressly provided under this License.  Any attempt
     174otherwise to copy, modify, sublicense or distribute the Program is
     175void, and will automatically terminate your rights under this License.
     176However, parties who have received copies, or rights, from you under
     177this License will not have their licenses terminated so long as such
     178parties remain in full compliance.
     179
     180  5. You are not required to accept this License, since you have not
     181signed it.  However, nothing else grants you permission to modify or
     182distribute the Program or its derivative works.  These actions are
     183prohibited by law if you do not accept this License.  Therefore, by
     184modifying or distributing the Program (or any work based on the
     185Program), you indicate your acceptance of this License to do so, and
     186all its terms and conditions for copying, distributing or modifying
     187the Program or works based on it.
     188
     189  6. Each time you redistribute the Program (or any work based on the
     190Program), the recipient automatically receives a license from the
     191original licensor to copy, distribute or modify the Program subject to
     192these terms and conditions.  You may not impose any further
     193restrictions on the recipients' exercise of the rights granted herein.
     194You are not responsible for enforcing compliance by third parties to
     195this License.
     196
     197  7. If, as a consequence of a court judgment or allegation of patent
     198infringement or for any other reason (not limited to patent issues),
     199conditions are imposed on you (whether by court order, agreement or
     200otherwise) that contradict the conditions of this License, they do not
     201excuse you from the conditions of this License.  If you cannot
     202distribute so as to satisfy simultaneously your obligations under this
     203License and any other pertinent obligations, then as a consequence you
     204may not distribute the Program at all.  For example, if a patent
     205license would not permit royalty-free redistribution of the Program by
     206all those who receive copies directly or indirectly through you, then
     207the only way you could satisfy both it and this License would be to
     208refrain entirely from distribution of the Program.
     209
     210If any portion of this section is held invalid or unenforceable under
     211any particular circumstance, the balance of the section is intended to
     212apply and the section as a whole is intended to apply in other
     213circumstances.
     214
     215It is not the purpose of this section to induce you to infringe any
     216patents or other property right claims or to contest validity of any
     217such claims; this section has the sole purpose of protecting the
     218integrity of the free software distribution system, which is
     219implemented by public license practices.  Many people have made
     220generous contributions to the wide range of software distributed
     221through that system in reliance on consistent application of that
     222system; it is up to the author/donor to decide if he or she is willing
     223to distribute software through any other system and a licensee cannot
     224impose that choice.
     225
     226This section is intended to make thoroughly clear what is believed to
     227be a consequence of the rest of this License.
     228
     229  8. If the distribution and/or use of the Program is restricted in
     230certain countries either by patents or by copyrighted interfaces, the
     231original copyright holder who places the Program under this License
     232may add an explicit geographical distribution limitation excluding
     233those countries, so that distribution is permitted only in or among
     234countries not thus excluded.  In such case, this License incorporates
     235the limitation as if written in the body of this License.
     236
     237  9. The Free Software Foundation may publish revised and/or new versions
     238of the General Public License from time to time.  Such new versions will
     239be similar in spirit to the present version, but may differ in detail to
     240address new problems or concerns.
     241
     242Each version is given a distinguishing version number.  If the Program
     243specifies a version number of this License which applies to it and "any
     244later version", you have the option of following the terms and conditions
     245either of that version or of any later version published by the Free
     246Software Foundation.  If the Program does not specify a version number of
     247this License, you may choose any version ever published by the Free Software
     248Foundation.
     249
     250  10. If you wish to incorporate parts of the Program into other free
     251programs whose distribution conditions are different, write to the author
     252to ask for permission.  For software which is copyrighted by the Free
     253Software Foundation, write to the Free Software Foundation; we sometimes
     254make exceptions for this.  Our decision will be guided by the two goals
     255of preserving the free status of all derivatives of our free software and
     256of promoting the sharing and reuse of software generally.
     257
     258                            NO WARRANTY
     259
     260  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
     261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
     262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
     263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
     264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
     266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
     267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
     268REPAIR OR CORRECTION.
     269
     270  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
     271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
     272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
     273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
     274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
     275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
     276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
     277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
     278POSSIBILITY OF SUCH DAMAGES.
     279
     280                     END OF TERMS AND CONDITIONS
     281
     282            How to Apply These Terms to Your New Programs
     283
     284  If you develop a new program, and you want it to be of the greatest
     285possible use to the public, the best way to achieve this is to make it
     286free software which everyone can redistribute and change under these terms.
     287
     288  To do so, attach the following notices to the program.  It is safest
     289to attach them to the start of each source file to most effectively
     290convey the exclusion of warranty; and each file should have at least
     291the "copyright" line and a pointer to where the full notice is found.
     292
     293    <one line to give the program's name and a brief idea of what it does.>
     294    Copyright (C) <year>  <name of author>
     295
     296    This program is free software; you can redistribute it and/or modify
     297    it under the terms of the GNU General Public License as published by
     298    the Free Software Foundation; either version 2 of the License, or
     299    (at your option) any later version.
     300
     301    This program is distributed in the hope that it will be useful,
     302    but WITHOUT ANY WARRANTY; without even the implied warranty of
     303    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     304    GNU General Public License for more details.
     305
     306    You should have received a copy of the GNU General Public License along
     307    with this program; if not, write to the Free Software Foundation, Inc.,
     308    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     309
     310Also add information on how to contact you by electronic and paper mail.
     311
     312If the program is interactive, make it output a short notice like this
     313when it starts in an interactive mode:
     314
     315    Gnomovision version 69, Copyright (C) year name of author
     316    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     317    This is free software, and you are welcome to redistribute it
     318    under certain conditions; type `show c' for details.
     319
     320The hypothetical commands `show w' and `show c' should show the appropriate
     321parts of the General Public License.  Of course, the commands you use may
     322be called something other than `show w' and `show c'; they could even be
     323mouse-clicks or menu items--whatever suits your program.
     324
     325You should also get your employer (if you work as a programmer) or your
     326school, if any, to sign a "copyright disclaimer" for the program, if
     327necessary.  Here is a sample; alter the names:
     328
     329  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
     330  `Gnomovision' (which makes passes at compilers) written by James Hacker.
     331
     332  <signature of Ty Coon>, 1 April 1989
     333  Ty Coon, President of Vice
     334
     335This General Public License does not permit incorporating your program into
     336proprietary programs.  If your program is a subroutine library, you may
     337consider it more useful to permit linking proprietary applications with the
     338library.  If this is what you want to do, use the GNU Lesser General
     339Public License instead of this License.
  • mythmovies/README

     
     1MythMovies is Copyright (c) 2006, Josh Lefler.
     2
     3You may contact the original author at joshlefler@leflerinc.com.
     4
     5See the INSTALL file for installation instructions.
     6
     7This program is free software; you can redistribute it and/or modify
     8it under the terms of tne GNU General Public License as public by
     9the Free Software Foundation; version 2.
     10
     11This program is distributed in the hope that it will be useful,
     12but WITHOUT ANY WARRANTY; without even the implied warranty of
     13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     14GNU General Public License for more details.
     15
     16You should have received a copy of the GNU General Public License
     17along with this program; if not, write to the Free Software
     18Foundation, Inc. 51 Frankling St, Fifth Floor, Boston, MA, 02110-1201 USA