Ticket #3334: #3334 libmythtv-importicons-18122007.patch

File #3334 libmythtv-importicons-18122007.patch, 35.9 KB (added by Matthew Wire <devel@…>, 16 years ago)

Update for svn. no changes

  • libs/libmythtv/channeleditor.cpp

     
    1919#include "sourceutil.h"
    2020
    2121#include "scanwizard.h"
     22#include "importicons.h"
    2223
    2324ChannelWizard::ChannelWizard(int id, int default_sourceid)
    2425    : ConfigurationWizard()
     
    110111        return 0;
    111112}
    112113
    113 void ChannelListSetting::fillSelections(void)
     114int ChannelListSetting::fillSelections(void)
    114115{
    115116    QString currentValue = getValue();
    116117    uint    currentIndex = max(getValueIndex(currentValue), 0);
     
    198199    // Make sure we select the current item, or the following one after
    199200    // deletion, with wrap around to "(New Channel)" after deleting last item.
    200201    setCurrentItem((!selidx && currentIndex < idx) ? currentIndex : selidx);
     202    return idx;
    201203}
    202204
    203205class SourceSetting : public ComboBoxSetting, public Storage
     
    278280    buttonScan->setLabel(QObject::tr("Channel Scanner"));
    279281    buttonScan->setHelpText(QObject::tr("Starts the channel scanner."));
    280282    buttonScan->setEnabled(SourceUtil::IsAnySourceScanable());
     283   
     284    buttonImportIcon = new TransButtonSetting();
     285    buttonImportIcon->setLabel(QObject::tr("Icon Download"));
     286    buttonImportIcon->setHelpText(QObject::tr("Starts the icon downloader"));
     287    buttonImportIcon->setEnabled(SourceUtil::IsAnySourceScanable());
    281288
    282289    buttonTransportEditor = new TransButtonSetting();
    283290    buttonTransportEditor->setLabel(QObject::tr("Transport Editor"));
     
    290297    HorizontalConfigurationGroup *h =
    291298        new HorizontalConfigurationGroup(false, false);
    292299    h->addChild(buttonScan);
     300    h->addChild(buttonImportIcon);
    293301    h->addChild(buttonTransportEditor);
    294302    addChild(h);
    295303
     
    305313            this, SLOT(menu(int)));
    306314    connect(buttonScan, SIGNAL(pressed()),
    307315            this, SLOT(scan()));
     316    connect(buttonImportIcon,  SIGNAL(pressed()),
     317            this, SLOT(channelIconImport()));
    308318    connect(buttonTransportEditor, SIGNAL(pressed()),
    309319            this, SLOT(transportEditor()));
    310320    connect(del,  SIGNAL(pressed()),
     
    399409    id = list->getValue().toInt();
    400410    ChannelWizard cw(id, source->getValue().toUInt());
    401411    cw.exec();
    402 
     412   
    403413    list->fillSelections();
    404414    list->setFocus();
    405415}
     
    480490    list->fillSelections();
    481491    list->setFocus();
    482492}
     493
     494void ChannelEditor::channelIconImport(void)
     495{
     496    if (list->fillSelections() == 0)
     497    {
     498        MythPopupBox::showOkPopup(gContext->GetMainWindow(), "",
     499                                        tr("Add some for channels first!"));
     500        return;
     501    }
     502   
     503    // Get selected channel name from database
     504    QString querystr = QString("SELECT channel.name FROM channel WHERE chanid='%1' ").arg(list->getValue());
     505    QString channelname = "";
     506    MSqlQuery query(MSqlQuery::InitCon());
     507    query.prepare(querystr);
     508   
     509    if (query.exec() && query.isActive() && query.size() > 0)
     510    {
     511        query.next();
     512        channelname = QString::fromUtf8(query.value(0).toString());
     513    }
     514   
     515    QStringList buttons;
     516    buttons.append(tr("Cancel"));
     517    buttons.append(tr("Download all icons.."));
     518    buttons.append(tr("Rescan for missing icons.."));
     519    if (channelname.isEmpty()==false)
     520        buttons.append(tr("Download icon for ") + channelname);
     521   
     522    int val = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
     523                                             "", "Channel Icon Import", buttons, kDialogCodeButton2);
     524    ImportIconsWizard *iconwizard;
     525    if (val == 0) // Cancel pressed
     526        return;
     527    else if (val == 1) // Import all icons pressed
     528        iconwizard = new ImportIconsWizard(false);
     529    else if (val == 2) // Rescan for missing pressed
     530        iconwizard = new ImportIconsWizard(true);
     531    else // (val == 3 ) Import a single channel icon
     532        iconwizard = new ImportIconsWizard(true, channelname);
     533
     534    iconwizard->exec();
     535    iconwizard->deleteLater();
     536   
     537    list->fillSelections();
     538    list->setFocus();
     539}
  • libs/libmythtv/libmythtv.pro

     
    141141HEADERS += playgroup.h              progdetails.h
    142142HEADERS += channeleditor.h          channelsettings.h
    143143HEADERS += previewgenerator.h       transporteditor.h
     144HEADERS += importicons.h
    144145
    145146SOURCES += programinfo.cpp          proglist.cpp
    146147SOURCES += storagegroup.cpp
     
    163164SOURCES += progdetails.cpp
    164165SOURCES += channeleditor.cpp        channelsettings.cpp
    165166SOURCES += previewgenerator.cpp     transporteditor.cpp
     167SOURCES += importicons.cpp
    166168
    167169# DiSEqC
    168170HEADERS += diseqc.h                 diseqcsettings.h
  • libs/libmythtv/importicons.h

     
     1/* -*- Mode: c++ -*-
     2 * vim: set expandtab tabstop=4 shiftwidth=4:
     3 *
     4 * Original Project
     5 *      MythTV      http://www.mythtv.org
     6 *
     7 * Author(s):
     8 *      John Pullan, Matthew Wire 
     9 *
     10 * Description:
     11 */
     12
     13#ifndef IMPORTICONS_H
     14#define IMPORTICONS_H
     15
     16#include <qsqldatabase.h>
     17#include <qurl.h>
     18
     19#include "settings.h"
     20
     21class ImportIconsWizard : public QObject, public ConfigurationWizard
     22{
     23    Q_OBJECT
     24public:
     25    ImportIconsWizard(bool fRefresh, QString channelname=""); //!< constructs an ImportIconWizard
     26    MythDialog *dialogWidget(MythMainWindow *parent, const char *widgetName);
     27
     28    int exec();
     29
     30private:
     31
     32    enum dialogState
     33    {
     34        STATE_NORMAL,
     35        STATE_SEARCHING,
     36        STATE_DISABLED
     37    };
     38   
     39    struct CSVEntry                  //! describes the TV channel name
     40    {
     41        QString strChanId;           //!< local channel id
     42        QString strName;             //!< channel name
     43        QString strXmlTvId;          //!< the xmltvid
     44        QString strCallsign;         //!< callsign
     45        QString strTransportId;      //!< transport id
     46        QString strAtscMajorChan;    //!< ATSC major number
     47        QString strAtscMinorChan;    //!< ATSC minor number
     48        QString strNetworkId;        //!< network id
     49        QString strServiceId;        //!< service id
     50        QString strIconCSV;          //!< icon name (csv form)
     51        QString strNameCSV;          //!< name (csv form)
     52    }; 
     53    //! List of CSV entries
     54    typedef QValueList<CSVEntry> ListEntries;     
     55    //! iterator over list of CSV entries
     56    typedef QValueListIterator<CSVEntry> ListEntriesIter;
     57
     58    ListEntries m_listEntries;       //!< list of TV channels to search for
     59    ListEntries m_missingEntries;    //!< list of TV channels with no unique icon
     60    ListEntriesIter m_iter;          //!< the current iterator
     61    ListEntriesIter m_missingIter;
     62
     63    struct SearchEntry               //! search entry results
     64    {
     65        QString strID;               //!< the remote channel id
     66        QString strName;             //!< the remote name
     67        QString strLogo;             //!< the actual logo
     68    };
     69    //! List of SearchEntry entries
     70    typedef QValueList<SearchEntry> ListSearchEntries;
     71    //! iterator over list of SearchEntry entries
     72    typedef QValueListIterator<SearchEntry> ListSearchEntriesIter;
     73
     74    ListSearchEntries m_listSearch;  //!< the list of SearchEntry
     75    QString m_strMatches;            //!< the string for the submit() call
     76
     77    static const QString url;        //!< the default url
     78    QString m_strChannelDir;         //!< the location of the channel icon dir
     79    QString m_strChannelname;        //!< the channel name if searching for a single channel icon
     80
     81    bool m_fRefresh;                 //!< are we doing a refresh or not
     82    int m_nMaxCount;                 //!< the maximum number of TV channels
     83    int m_nCount;                    //!< the current search point (0..m_nMaxCount)
     84    int m_missingMaxCount;           //!< the total number of missing icons
     85    int m_missingCount;              //!< the current search point (0..m_missingCount)
     86
     87    void startDialog();
     88    void importSingleIcon(const QString& channelname);
     89
     90    /*! \brief changes a string into csv format
     91     * \param str the string to change
     92     * \return the actual string
     93     */
     94    QString escape_csv(const QString& str);
     95
     96    /*! \brief extracts the csv values out of a string
     97     * \param str the string to work on
     98     * \return the actual QStringList
     99     */
     100    QStringList extract_csv(const QString& strLine);
     101
     102    /*! \brief use the equivalent of wget to fetch the POST command
     103     * \param url the url to send this to
     104     * \param strParam the string to send
     105     * \return the actual string
     106     */
     107    QString wget(QUrl& url,const QString& strParam);
     108 
     109    TransLineEditSetting *m_editName;    //!< name field for the icon
     110    TransListBoxSetting *m_listIcons;    //!< list of potential icons
     111    TransLineEditSetting *m_editManual;  //!< manual edit field
     112    TransButtonSetting *m_buttonManual;  //!< manual button field
     113    TransButtonSetting *m_buttonSkip;    //!< button skip
     114    TransButtonSetting *m_buttonSelect;    //!< button skip
     115
     116    /*! \brief determines if a particular icon is blocked
     117     * \param str the string to work on
     118     * \return true/false
     119     */
     120    bool isBlocked(const QString& strParam);
     121
     122    /*! \brief looks up the string to determine the caller/xmltvid
     123     * \param str the string to work on
     124     * \return true/false
     125     */
     126    bool lookup(const QString& strParam);
     127
     128    /*! \brief search the remote db for icons etc
     129     * \param str the string to work on
     130     * \return true/false
     131     */
     132    bool search(const QString& strParam);
     133
     134    /*! \brief submit the icon information back to the remote db
     135     * \param str the string to work on
     136     * \return true/false
     137     */
     138    bool submit(const QString& strParam);
     139
     140    /*! \brief retrieve the actual logo for the TV channel
     141     * \param str the string to work on
     142     * \return true/false
     143     */
     144    bool findmissing(const QString& strParam);
     145
     146    /*! \brief checks and attempts to download the logo file to the appropriate
     147     *   place
     148     * \param str the string of the downloaded url
     149     * \return true/false
     150     */
     151    bool checkAndDownload(const QString& str);
     152
     153    /*! \brief attempt the inital load of the TV channel information
     154     * \return the number of TV channels
     155     */
     156    unsigned initialLoad(QString name="");
     157
     158    /*! \brief attempts to move the itaration on one/more than one
     159     * \return true if we can go again or false if we can not
     160     */
     161    bool doLoad();
     162   
     163    bool m_closeDialog;
     164   
     165    ~ImportIconsWizard() { };
     166   
     167protected slots:
     168    void enableControls(dialogState state=STATE_NORMAL, bool selectEnabled=true);         //!< enable/disable the controls
     169    void manualSearch();           //!< process the manual search
     170    void menuSelect();
     171    void menuSelection(int nIndex);//!< process the icon selection
     172    void skip();                   //!< skip this icon
     173    void cancelPressed();
     174    void finishButtonPressed();
     175
     176};
     177
     178#endif // IMPORTICONS_H
  • libs/libmythtv/channeleditor.h

     
    2222    void edit();
    2323    void edit(int);
    2424    void scan(void);
    25     void transportEditor();
    26     void deleteChannels();
     25    void transportEditor(void);
     26    void channelIconImport(void);
     27    void deleteChannels(void);
    2728
    2829private:
    2930    int                 id;
    3031    SourceSetting      *source;
    3132    ChannelListSetting *list;
    3233    TransButtonSetting *buttonScan;
     34    TransButtonSetting *buttonImportIcon;
    3335    TransButtonSetting *buttonTransportEditor;
    3436};
    3537
     
    6870    bool getHideMode() { return currentHideMode; };
    6971
    7072public slots:
    71     void fillSelections(void);
     73    int fillSelections(void);
    7274    void setSortMode(const QString& sort) {
    7375        if (currentSortMode != sort) {
    7476            currentSortMode = sort;
  • libs/libmythtv/importicons.cpp

     
     1#include <sys/stat.h>
     2#include <qapplication.h>
     3#include <qregexp.h>
     4#include <qbuffer.h>
     5#include <qfileinfo.h>
     6
     7#include "mythwizard.h"
     8#include "httpcomms.h"
     9#include "importicons.h"
     10#include "util.h"
     11
     12ImportIconsWizard::ImportIconsWizard(bool fRefresh, QString channelname)
     13{
     14    m_fRefresh = fRefresh;   
     15    m_strChannelname = channelname;
     16    m_closeDialog = false;
     17    m_missingCount=0;
     18    m_missingMaxCount=0;
     19
     20}
     21
     22MythDialog *ImportIconsWizard::dialogWidget(MythMainWindow *parent,
     23                                     const char *widgetName)
     24{
     25    MythWizard *ret = (MythWizard*)ConfigurationWizard::dialogWidget(parent,widgetName);
     26    connect(ret->finishButton(), SIGNAL(pressed()), this, SLOT(finishButtonPressed()));
     27    return (MythDialog*)ret;
     28}
     29
     30int ImportIconsWizard::exec()
     31{
     32    m_strChannelDir =  MythContext::GetConfDir()+ "/channels";
     33    mkdir(MythContext::GetConfDir(),0776);
     34    mkdir(m_strChannelDir,0776);
     35    m_strChannelDir+="/";
     36
     37    if (m_strChannelname.isEmpty()){
     38        if (initialLoad() > 0)
     39        {
     40            startDialog();
     41            m_missingIter=m_missingEntries.begin();
     42            doLoad();
     43        }
     44    }
     45    else
     46    {
     47        importSingleIcon(m_strChannelname);
     48    }
     49
     50    if (m_closeDialog==false) // Need this if line to exit if cancel button is pressed
     51        while ((ConfigurationDialog::exec() == QDialog::Accepted) && (m_closeDialog == false))  {}
     52   
     53    return QDialog::Rejected;
     54}
     55
     56void ImportIconsWizard::importSingleIcon(const QString& channelname)
     57{
     58    m_fRefresh=false; // Does not apply so make sure it is false or m_iter won't get set
     59    initialLoad(channelname);
     60    startDialog();
     61    m_missingMaxCount=1;
     62    m_editName->setValue(channelname);
     63    search(channelname);
     64}
     65
     66void ImportIconsWizard::startDialog()
     67{
     68    VerticalConfigurationGroup *manSearch =
     69        new VerticalConfigurationGroup(false,false,true,true);
     70   
     71    manSearch->addChild(m_editName = new TransLineEditSetting(false));
     72    m_editName->setLabel(QObject::tr("Name"));
     73    m_editName->setHelpText(QObject::tr("Name of the icon file"));
     74
     75    manSearch->addChild(m_listIcons = new TransListBoxSetting());
     76    m_listIcons->setHelpText(QObject::tr("List of possible icon files"));
     77
     78    m_editManual = new TransLineEditSetting();
     79    m_editManual->setHelpText(QObject::tr("Enter text here for the manual search"));
     80
     81    m_buttonManual = new TransButtonSetting();
     82    m_buttonManual->setLabel(QObject::tr("&Search"));
     83    m_buttonManual->setHelpText(QObject::tr("Manually search for the text"));
     84
     85    m_buttonSkip = new TransButtonSetting();
     86    m_buttonSkip->setLabel(QObject::tr("S&kip"));
     87    m_buttonSkip->setHelpText(QObject::tr("Skip this icon"));
     88
     89    m_buttonSelect = new TransButtonSetting();
     90    m_buttonSelect->setLabel(QObject::tr("S&elect"));
     91    m_buttonSelect->setHelpText(QObject::tr("Select this icon"));
     92
     93    HorizontalConfigurationGroup *hrz1 =
     94        new HorizontalConfigurationGroup(false, false, true, true);
     95
     96    hrz1->addChild(m_editManual);
     97    hrz1->addChild(m_buttonManual);
     98    hrz1->addChild(m_buttonSkip);
     99    hrz1->addChild(m_buttonSelect);
     100    manSearch->addChild(hrz1);
     101   
     102    addChild(manSearch);
     103
     104    connect(m_buttonManual, SIGNAL(pressed()), this, SLOT(manualSearch()));
     105    connect(m_buttonSkip, SIGNAL(pressed()), this, SLOT(skip()));
     106    connect(m_listIcons,SIGNAL(accepted(int)),this,
     107             SLOT(menuSelection(int)));
     108    connect(m_buttonSelect,SIGNAL(pressed()),this,
     109            SLOT(menuSelect()));
     110
     111    enableControls(STATE_NORMAL);
     112}
     113
     114const QString ImportIconsWizard::url="http://services.mythtv.org/channel-icon/";
     115
     116void ImportIconsWizard::enableControls(dialogState state, bool selectEnabled)
     117{
     118    switch (state)
     119    {
     120        case STATE_NORMAL:
     121            if (m_editManual->getValue())
     122                 m_buttonManual->setEnabled(true);
     123            else
     124            m_buttonManual->setEnabled(false);
     125            if (m_missingCount < m_missingMaxCount)
     126            {
     127                if (m_missingMaxCount < 2) //When there's only one icon, nothing to skip to!
     128                    m_buttonSkip->setEnabled(false);
     129                else
     130                    m_buttonSkip->setEnabled(true);
     131                m_editName->setEnabled(true);
     132                m_listIcons->setEnabled(true);
     133                m_editManual->setEnabled(true);
     134                m_buttonSelect->setEnabled(selectEnabled);
     135            }
     136            else
     137            {
     138                m_buttonSkip->setEnabled(false);
     139                m_editName->setEnabled(false);
     140                m_listIcons->setEnabled(false);
     141                m_editManual->setEnabled(false);
     142                m_buttonManual->setEnabled(false);
     143                m_buttonSelect->setEnabled(false);
     144            }
     145            break;
     146        case STATE_SEARCHING:
     147            m_buttonSkip->setEnabled(false);
     148            m_buttonSelect->setEnabled(false);
     149            m_buttonManual->setEnabled(false);
     150            m_listIcons->setEnabled(false);
     151            m_listIcons->clearSelections();
     152            m_listIcons->addSelection("Please wait...");
     153            m_editManual->setValue("");
     154            break;
     155        case STATE_DISABLED:
     156            m_buttonSkip->setEnabled(false);
     157            m_buttonSelect->setEnabled(false);
     158            m_buttonManual->setEnabled(false);
     159            m_listIcons->setEnabled(false);
     160            m_listIcons->clearSelections();
     161            m_editName->setEnabled(false);
     162            m_editName->setValue("");
     163            m_editManual->setEnabled(false);
     164            m_editManual->setValue("");
     165            m_listIcons->setFocus();
     166            break;   
     167    }       
     168}
     169
     170void ImportIconsWizard::manualSearch()
     171{
     172    QString str = m_editManual->getValue();
     173    search(escape_csv(str));   
     174}
     175
     176void ImportIconsWizard::skip()
     177{
     178    if (m_missingMaxCount > 1)
     179    {
     180        m_missingCount++;
     181        m_missingIter++;   
     182        doLoad();
     183    }
     184}
     185
     186void ImportIconsWizard::menuSelect()
     187{
     188    menuSelection(m_listIcons->currentItem());   
     189}
     190
     191void ImportIconsWizard::menuSelection(int nIndex)
     192{
     193    enableControls(STATE_SEARCHING);
     194    SearchEntry entry = *(m_listSearch.at(nIndex));
     195
     196    if ((!isBlocked((*m_iter).strIconCSV)) &&
     197            (checkAndDownload(entry.strLogo)))
     198    {
     199        CSVEntry entry2 = (*m_iter);
     200        m_strMatches += QString("%1,%2,%3,%4,%5,%6,%7,%8,%9\n").
     201                              arg(escape_csv(entry.strID)).
     202                              arg(escape_csv(entry2.strName)).
     203                              arg(escape_csv(entry2.strXmlTvId)).
     204                              arg(escape_csv(entry2.strCallsign)).
     205                              arg(escape_csv(entry2.strTransportId)).
     206                              arg(escape_csv(entry2.strAtscMajorChan)).
     207                              arg(escape_csv(entry2.strAtscMinorChan)).
     208                              arg(escape_csv(entry2.strNetworkId)).
     209                              arg(escape_csv(entry2.strServiceId));
     210        if (m_missingMaxCount > 1)
     211        {
     212            m_missingCount++;
     213            m_missingIter++;
     214            doLoad();
     215        }
     216        else
     217        {
     218            enableControls(STATE_DISABLED);
     219            m_listIcons->addSelection(QString("Channel icon for %1 was downloaded successfully.")
     220                                      .arg(entry2.strName));
     221            m_listIcons->setFocus();
     222            if (!m_strMatches.isEmpty())
     223                submit(m_strMatches);
     224            m_closeDialog=true;
     225        }
     226    }
     227    else
     228    {
     229        MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     230                            QObject::tr("Error downloading"),
     231                            QObject::tr("Failed to download the icon file"));
     232        enableControls(STATE_DISABLED);
     233        m_closeDialog=true;
     234    }
     235
     236}
     237
     238unsigned ImportIconsWizard::initialLoad(QString name)
     239{
     240    // Do not try and access dialog within this function
     241    VERBOSE(VB_CHANNEL, "initialLoad");
     242   
     243    QString querystring=("SELECT chanid,name,xmltvid,callsign,"
     244                  "dtv_multiplex.transportid, "
     245                  "atsc_major_chan,atsc_minor_chan,dtv_multiplex.networkid,"
     246                  "channel.serviceid, "
     247                  "channel.mplexid, dtv_multiplex.mplexid,"
     248                  "channel.icon, channel.visible FROM "
     249                  "channel, dtv_multiplex WHERE "
     250                  "channel.visible && "
     251                  "channel.mplexid=dtv_multiplex.mplexid");
     252    if (name.isEmpty()==false)
     253        querystring+=" && name=\"" + name + "\"";
     254    querystring+=" ORDER BY name";
     255
     256    MSqlQuery query(MSqlQuery::InitCon());
     257    query.prepare(querystring);
     258       
     259    m_listEntries.clear();           
     260    m_nCount=0;
     261    m_nMaxCount=0;
     262    m_missingMaxCount=0;
     263
     264    if (query.exec() && query.isActive() && query.size() > 0)
     265    {
     266        MythProgressDialog *progressDialog = new MythProgressDialog("Initialising, please wait...", query.size());
     267       
     268        sleep(2); // Ensures dialog is drawn before ping freezes execution
     269       
     270        if (!ping("services.mythtv.org", 3))
     271        {
     272            progressDialog->Close();
     273            progressDialog->deleteLater();
     274            MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     275                                  tr("Bad Host"),
     276                                  tr("Failed to connect to the remote server"));
     277            return 0;
     278        }
     279
     280        while(query.next())
     281        {
     282            CSVEntry entry;
     283
     284            if (m_fRefresh)
     285            {
     286                QFileInfo file(query.value(11).toString());
     287                if (file.exists())
     288                    continue;
     289            }
     290           
     291            entry.strChanId=query.value(0).toString();
     292            entry.strName=query.value(1).toString();
     293            entry.strXmlTvId=query.value(2).toString();
     294            entry.strCallsign=query.value(3).toString();
     295            entry.strTransportId=query.value(4).toString();
     296            entry.strAtscMajorChan=query.value(5).toString();
     297            entry.strAtscMinorChan=query.value(6).toString();
     298            entry.strNetworkId=query.value(7).toString();
     299            entry.strServiceId=query.value(8).toString();
     300            entry.strIconCSV= QString("%1,%2,%3,%4,%5,%6,%7,%8,%9\n").
     301                              arg(escape_csv(entry.strChanId)).
     302                              arg(escape_csv(entry.strName)).
     303                              arg(escape_csv(entry.strXmlTvId)).
     304                              arg(escape_csv(entry.strCallsign)).
     305                              arg(escape_csv(entry.strTransportId)).
     306                              arg(escape_csv(entry.strAtscMajorChan)).
     307                              arg(escape_csv(entry.strAtscMinorChan)).
     308                              arg(escape_csv(entry.strNetworkId)).
     309                              arg(escape_csv(entry.strServiceId));
     310            entry.strNameCSV=escape_csv(entry.strName);
     311            VERBOSE(VB_CHANNEL,QString("chanid %1").arg(entry.strIconCSV));
     312
     313            m_listEntries.append(entry);
     314            m_nMaxCount++;
     315            progressDialog->setProgress(m_nMaxCount);
     316        }
     317       
     318        progressDialog->Close();
     319        progressDialog->deleteLater();
     320    }
     321   
     322    m_iter = m_listEntries.begin();
     323   
     324    if (name.isEmpty()) // Scanning for multiple icons
     325    {
     326        MythProgressDialog *progressDialog = new MythProgressDialog("Downloading, please wait...",
     327                                m_listEntries.size()+1, true, this, SLOT(cancelPressed()));
     328        while (!m_closeDialog && (m_iter != m_listEntries.end()))
     329        {
     330            progressDialog->setLabel(QString("Downloading %1 / %2 : ").arg(m_nCount+1)
     331                                     .arg(m_listEntries.size()+1) + (*m_iter).strName +
     332                                     QString("\nCould not find %1 icons.").arg(m_missingEntries.size()+1));
     333            if (!findmissing((*m_iter).strIconCSV))
     334                m_missingEntries.append((*m_iter));
     335            m_nCount++;
     336            m_iter++;
     337            m_missingMaxCount++;
     338            progressDialog->setProgress(m_nCount);
     339        }
     340        progressDialog->Close();
     341        progressDialog->deleteLater();
     342    }
     343   
     344    //Comment below for debugging - cancel button will continue to dialog
     345    if (m_closeDialog)
     346        m_nMaxCount=0;
     347    return m_nMaxCount;
     348}
     349
     350bool ImportIconsWizard::doLoad()
     351{
     352    VERBOSE(VB_CHANNEL, QString("%1 / %2").arg(m_missingCount).arg(m_missingMaxCount));
     353    if (m_missingCount >= m_missingMaxCount)
     354    {
     355        VERBOSE(VB_CHANNEL, "doLoad Icon search complete");
     356        enableControls(STATE_DISABLED);
     357        if (!m_strMatches.isEmpty())
     358            submit(m_strMatches);
     359        m_closeDialog=true;
     360        return false;
     361    }
     362    else
     363    {
     364        // Look for the next missing icon
     365        m_editName->setValue((*m_missingIter).strName);
     366        search((*m_missingIter).strNameCSV);
     367        return true;
     368    }
     369}
     370
     371QString ImportIconsWizard::escape_csv(const QString& str)
     372{
     373    VERBOSE(VB_CHANNEL, "escape_csv");
     374    QRegExp rxDblForEscape("\"");
     375    QString str2 = str;
     376    str2.replace(rxDblForEscape,"\\\"");
     377    return "\""+str2+"\"";
     378}
     379
     380QStringList ImportIconsWizard::extract_csv(const QString& strLine)
     381{
     382    VERBOSE(VB_CHANNEL, "extract_csv");
     383    QStringList ret;
     384    //Clean up the line and split out the fields
     385    QString str = strLine;
     386
     387    unsigned int pos = 0;
     388    bool fFinish = false;
     389    while(!fFinish)
     390    {
     391        str=str.stripWhiteSpace();
     392        while(!fFinish)
     393        {
     394            QString strLeft;
     395            switch (str.at(pos).unicode())
     396            {
     397            case '\\':
     398                if (pos>=1)
     399                    str.left(pos-1)+str.mid(pos+1);
     400                else
     401                    str=str.mid(pos+1);
     402                pos+=2;
     403                if (pos > str.length())
     404                {
     405                    strLeft = str.left(pos);
     406                    if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     407                        strLeft=strLeft.mid(1,strLeft.length()-2);
     408                    ret.append(strLeft);
     409                    fFinish = true;
     410                }
     411                break;
     412            case ',':
     413                strLeft = str.left(pos);
     414                if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     415                    strLeft=strLeft.mid(1,strLeft.length()-2);
     416                ret.append(strLeft);
     417                if ((pos+1) > str.length())
     418                   fFinish = true;
     419                str=str.mid(pos+1);
     420                pos=0;
     421                break;
     422            default:
     423                pos++;
     424                if (pos > str.length())
     425                {
     426                    strLeft = str.left(pos);
     427                    if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     428                        strLeft=strLeft.mid(1,strLeft.length()-2);
     429                    ret.append(strLeft);
     430                    fFinish = true;
     431                }
     432            }
     433        }
     434    }
     435    return ret;
     436}
     437
     438
     439QString ImportIconsWizard::wget(QUrl& url,const QString& strParam )
     440{
     441    VERBOSE(VB_CHANNEL, "wget");
     442    QByteArray raw;
     443    QTextStream rawStream(raw,IO_WriteOnly);
     444    rawStream << strParam;
     445
     446    QBuffer data(raw);
     447    QHttpRequestHeader header;
     448
     449    header.setContentType(QString("application/x-www-form-urlencoded"));
     450    header.setContentLength(raw.size());
     451
     452    header.setValue("User-Agent", "MythTV Channel Icon lookup bot");
     453
     454    QString str = HttpComms::postHttp(url,&header,&data);
     455
     456    return str;
     457}
     458
     459bool ImportIconsWizard::checkAndDownload(const QString& str)
     460{
     461    // Do not try and access dialog within this function
     462    VERBOSE(VB_CHANNEL, "checkAndDownload");
     463   
     464    int iIndex = str.findRev('/');
     465    QString str2;
     466    if (iIndex < 0)
     467        str2=str;
     468    else
     469        str2=str.mid(iIndex+1);
     470
     471    QString str3 = str;
     472    QFileInfo file(m_strChannelDir+str2);
     473
     474    bool fRet;
     475    if (!file.exists())
     476        fRet = HttpComms::getHttpFile(m_strChannelDir+str2,str3);   
     477    else
     478        fRet = true;
     479
     480    if (fRet)
     481    {
     482        MSqlQuery query(MSqlQuery::InitCon());
     483        QString  qstr = "UPDATE channel SET icon = :ICON "
     484                        "WHERE chanid = :CHANID";
     485
     486        query.prepare(qstr);
     487        query.bindValue(":ICON", m_strChannelDir+str2);
     488        query.bindValue(":CHANID", (*m_iter).strChanId);
     489
     490        if (!query.exec())
     491        {
     492            MythContext::DBError("Error inserting channel icon", query);
     493            return false;
     494        }
     495 
     496    }
     497
     498    return fRet;
     499}
     500
     501bool ImportIconsWizard::isBlocked(const QString& strParam)
     502{
     503    VERBOSE(VB_CHANNEL, "isBlocked");
     504    QString strParam1 = strParam;
     505    QUrl::encode(strParam1);
     506    QUrl url(ImportIconsWizard::url+"/checkblock");
     507    QString str = wget(url,"csv="+strParam1);
     508
     509    if (str.startsWith("Error",false))
     510    {
     511        VERBOSE(VB_IMPORTANT, QString("Error from isBlocked : %1").arg(str));
     512        return true;
     513    }
     514    else if (str.isEmpty() || str.startsWith("\r\n"))
     515        return false;
     516    else
     517    {
     518        VERBOSE(VB_CHANNEL, QString("Icon Import: Working isBlocked"));
     519        int nVal = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(),
     520                            QObject::tr("Icon is blocked"),
     521                            QObject::tr("This combination of channel and icon "
     522                                        "has been blocked by the MythTV "
     523                                        "admins. The most common reason for "
     524                                        "this is that there is a better match "
     525                                        "available.\n "
     526                                        "Are you still sure that you want to "
     527                                        "use this icon?"),
     528                          true);       
     529        if (nVal == 1) // Use the icon
     530            return false;
     531        else // Don't use the icon
     532            return true;
     533    }
     534}
     535
     536
     537bool ImportIconsWizard::lookup(const QString& strParam)
     538{
     539    QString strParam1 = "callsign="+strParam;
     540    QUrl::encode(strParam1);
     541    QUrl url(ImportIconsWizard::url+"/lookup");
     542
     543    QString str = wget(url,strParam1);
     544    if (str.isEmpty() || str.startsWith("Error",false))
     545    {
     546        VERBOSE(VB_IMPORTANT, QString("Error from lookup : %1").arg(str));
     547        return true;
     548    }
     549    else
     550    {
     551        VERBOSE(VB_CHANNEL, QString("Icon Import: Working lookup : %1").arg(str));
     552        return false;
     553    }
     554}
     555
     556bool ImportIconsWizard::search(const QString& strParam)
     557{
     558    QString strParam1 = strParam;
     559    bool retVal = false;
     560    enableControls(STATE_SEARCHING);
     561    QUrl::encode(strParam1);
     562    QUrl url(ImportIconsWizard::url+"/search");
     563
     564    QString str = wget(url,"s="+strParam1);
     565   
     566    m_listSearch.clear();
     567    m_listIcons->clearSelections();
     568
     569    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     570    {
     571        VERBOSE(VB_IMPORTANT, QString("Error from search : %1").arg(str));
     572        retVal=false;
     573    }
     574    else
     575    {
     576        VERBOSE(VB_CHANNEL, QString("Icon Import: Working search : %1").arg(str));
     577        QStringList strSplit=QStringList::split("\n",str);
     578
     579        for (QStringList::iterator begin=strSplit.begin();
     580             begin!=strSplit.end();begin++)
     581        {
     582            if (*begin != "#" )
     583            {
     584                QStringList ret = extract_csv(*begin);
     585                VERBOSE(VB_CHANNEL, QString("Icon Import: search : %1 %2 %3").arg(ret[0]).arg(ret[1]).arg(ret[2]));
     586                SearchEntry entry;
     587                entry.strID=ret[0];
     588                entry.strName=ret[1];
     589                entry.strLogo=ret[2];
     590                m_listSearch.append(entry);
     591                m_listIcons->addSelection(entry.strName);
     592            }
     593        }
     594        retVal=true;
     595    }
     596    enableControls(STATE_NORMAL, retVal);
     597    return retVal;
     598}
     599
     600bool ImportIconsWizard::findmissing(const QString& strParam)
     601{
     602    QString strParam1 = strParam;
     603    QUrl::encode(strParam1);
     604    QUrl url(ImportIconsWizard::url+"/findmissing");
     605
     606    QString str = wget(url,"csv="+strParam1);
     607    VERBOSE(VB_CHANNEL, QString("Icon Import: findmissing : strParam1 = %1. str = %2").arg(strParam1).arg(str));   
     608    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     609    {
     610        VERBOSE(VB_IMPORTANT, QString("Error from findmissing : %1").arg(str));
     611        return false;
     612    }
     613    else
     614    {
     615        VERBOSE(VB_CHANNEL, QString("Icon Import: Working findmissing : %1").arg(str));
     616        QStringList strSplit=QStringList::split("\n",str);
     617        for (QStringList::iterator begin=strSplit.begin();
     618             begin!=strSplit.end();begin++)
     619        {
     620            if (*begin != "#" )
     621            {
     622                QStringList ret = extract_csv(*begin);
     623                VERBOSE(VB_CHANNEL, QString("Icon Import: findmissing : %1 %2 %3 %4 %5").arg(ret[0]).arg(ret[1]).arg(ret[2]).arg(ret[3]).arg(ret[4]));
     624                checkAndDownload(ret[4]);
     625            }
     626        }
     627        return true;
     628    }
     629}
     630
     631bool ImportIconsWizard::submit(const QString& strParam)
     632{
     633    int nVal = MythPopupBox::showOkCancelPopup(
     634                            gContext->GetMainWindow(),
     635                            QObject::tr("Submit information"),
     636                            QObject::tr("You now have the opportunity to "
     637                                        "transmit your choices  back to "
     638                                        "mythtv.org so that others can "
     639                                        "benefit from your selections."),
     640                            true);       
     641    if (nVal == 0) // If cancel is pressed exit
     642    {
     643        m_listIcons->addSelection("Icon choices not submitted.");
     644        return false;
     645    }
     646   
     647    QString strParam1 = strParam;
     648    QUrl::encode(strParam1);
     649    QUrl url(ImportIconsWizard::url+"/submit");
     650
     651    QString str = wget(url,"csv="+strParam1);
     652    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     653    {
     654        VERBOSE(VB_IMPORTANT, QString("Error from submit : %1").arg(str));
     655        m_listIcons->addSelection("Failed to submit icon choices.");
     656        return false;
     657    }
     658    else
     659    {
     660        VERBOSE(VB_CHANNEL, QString("Icon Import: Working submit : %1").arg(str));
     661        QStringList strSplit=QStringList::split("\n",str);
     662        unsigned atsc =0, dvb =0, callsign =0, tv =0, xmltvid=0;
     663        for (QStringList::iterator begin=strSplit.begin();
     664             begin!=strSplit.end();begin++)
     665        {
     666            if (*begin != "#" )
     667            {
     668                QStringList strSplit2=QStringList::split(":",*begin);
     669                QString s=strSplit2[0].stripWhiteSpace();
     670                if (s=="a")
     671                     atsc=strSplit2[1].toUInt();
     672                else if (s=="c")
     673                     callsign=strSplit2[1].toUInt();
     674                else if (s=="d")
     675                     dvb=strSplit2[1].toUInt();
     676                else if (s=="t")
     677                     tv=strSplit2[1].toUInt();
     678                else if (s=="x")
     679                     xmltvid=strSplit2[1].toUInt();
     680            }
     681        }
     682        VERBOSE(VB_CHANNEL, QString("Icon Import: working submit : atsc=%1 callsign=%2 dvb=%3 tv=%4 xmltvid=%5")
     683                                              .arg(atsc).arg(callsign).arg(dvb).arg(tv).arg(xmltvid));
     684        m_listIcons->addSelection("Icon choices submitted successfully.");
     685        return true;
     686    }
     687}
     688
     689void ImportIconsWizard::cancelPressed()
     690{
     691    m_closeDialog=true;
     692}
     693
     694void ImportIconsWizard::finishButtonPressed()
     695{
     696    m_closeDialog = true;
     697}