Ticket #3334: importicons-libmythtv-23102007.diff

File importicons-libmythtv-23102007.diff, 36.4 KB (added by Matthew Wire <devel@…>, 16 years ago)

Small fix for importSingleIcon where m_iter was not getting filled

  • 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();
     117
    116118    clearSelections();
    117119    addSelection(QObject::tr("(New Channel)"));
    118120    bool fAllSources = true;
     121    int nCount = 0;
    119122
    120123    QString querystr = "SELECT channel.name,channum,chanid ";
    121124
    122     if ((currentSourceID == "") || (currentSourceID == "Unassigned"))
     125    if ((currentSourceID == "") || (currentSourceID == "Unassigned")
     126                                || (currentSourceID == "(All)"))
    123127    {
    124128        querystr += ",videosource.name FROM channel "
    125129                    "LEFT JOIN videosource ON "
     
    184188                name += " (" + sourceid  + ")";
    185189
    186190            addSelection(name, chanid, (chanid == currentValue) ? true : false);
     191
     192            nCount++;
     193           
     194            // nCount increments first since "(New Channel)" offsets list by one
     195            if (chanid == currentValue)
     196                setCurrentItem(nCount);
    187197        }
    188198    }
     199    return nCount;
    189200}
    190201
    191202class SourceSetting : public ComboBoxSetting, public Storage
     
    194205    SourceSetting() : ComboBoxSetting(this)
    195206    {
    196207        setLabel(QObject::tr("Video Source"));
    197         addSelection(QObject::tr("(All)"),"");
     208        addSelection(QObject::tr("(All)"),"(All)");
    198209    };
    199210
    200211    void load()
     
    266277    buttonScan->setLabel(QObject::tr("Channel Scanner"));
    267278    buttonScan->setHelpText(QObject::tr("Starts the channel scanner."));
    268279    buttonScan->setEnabled(SourceUtil::IsAnySourceScanable());
     280   
     281    buttonImportIcon = new TransButtonSetting();
     282    buttonImportIcon->setLabel(QObject::tr("Icon Download"));
     283    buttonImportIcon->setHelpText(QObject::tr("Starts the icon downloader"));
     284    buttonImportIcon->setEnabled(SourceUtil::IsAnySourceScanable());
    269285
    270286    buttonTransportEditor = new TransButtonSetting();
    271287    buttonTransportEditor->setLabel(QObject::tr("Transport Editor"));
     
    278294    HorizontalConfigurationGroup *h =
    279295        new HorizontalConfigurationGroup(false, false);
    280296    h->addChild(buttonScan);
     297    h->addChild(buttonImportIcon);
    281298    h->addChild(buttonTransportEditor);
    282299    addChild(h);
    283300
     
    293310            this, SLOT(menu(int)));
    294311    connect(buttonScan, SIGNAL(pressed()),
    295312            this, SLOT(scan()));
     313    connect(buttonImportIcon,  SIGNAL(pressed()),
     314            this, SLOT(channelIconImport()));
    296315    connect(buttonTransportEditor, SIGNAL(pressed()),
    297316            this, SLOT(transportEditor()));
    298317    connect(del,  SIGNAL(pressed()),
     
    377396    id = list->getValue().toInt();
    378397    ChannelWizard cw(id, source->getValue().toUInt());
    379398    cw.exec();
    380 
     399   
    381400    list->fillSelections();
    382401    list->setFocus();
    383402}
     
    459478    list->fillSelections();
    460479    list->setFocus();
    461480}
     481
     482void ChannelEditor::channelIconImport(void)
     483{
     484    if (list->fillSelections() == 0)
     485    {
     486        MythPopupBox::showOkPopup(gContext->GetMainWindow(), "",
     487                                        tr("Add some for channels first!"));
     488        return;
     489    }
     490   
     491    // Get selected channel name from database
     492    QString querystr = QString("SELECT channel.name FROM channel WHERE chanid='%1' ").arg(list->getValue());
     493    QString channelname = "";
     494    MSqlQuery query(MSqlQuery::InitCon());
     495    query.prepare(querystr);
     496   
     497    if (query.exec() && query.isActive() && query.size() > 0)
     498    {
     499        query.next();
     500        channelname = QString::fromUtf8(query.value(0).toString());
     501    }
     502   
     503    QStringList buttons;
     504    buttons.append(tr("Cancel"));
     505    buttons.append(tr("Download all icons.."));
     506    buttons.append(tr("Rescan for missing icons.."));
     507    if (channelname.isEmpty()==false)
     508        buttons.append(tr("Download icon for ") + channelname);
     509   
     510    int val = MythPopupBox::showButtonPopup(gContext->GetMainWindow(),
     511                                             "", "Channel Icon Import", buttons, 2);
     512    ImportIconsWizard *iconwizard;
     513    if (val == 0) // Cancel pressed
     514        return;
     515    else if (val == 1) // Import all icons pressed
     516        iconwizard = new ImportIconsWizard(false);
     517    else if (val == 2) // Rescan for missing pressed
     518        iconwizard = new ImportIconsWizard(true);
     519    else if (val == 3) // Import a single channel icon
     520        iconwizard = new ImportIconsWizard(true, channelname);
     521
     522    iconwizard->exec();
     523    iconwizard->deleteLater();
     524   
     525    list->fillSelections();
     526    list->setFocus();
     527}
  • libs/libmythtv/libmythtv.pro

     
    148148HEADERS += playgroup.h              progdetails.h
    149149HEADERS += channeleditor.h          channelsettings.h
    150150HEADERS += previewgenerator.h       transporteditor.h
     151HEADERS += importicons.h
    151152
    152153SOURCES += programinfo.cpp          proglist.cpp
    153154SOURCES += storagegroup.cpp
     
    170171SOURCES += progdetails.cpp
    171172SOURCES += channeleditor.cpp        channelsettings.cpp
    172173SOURCES += previewgenerator.cpp     transporteditor.cpp
     174SOURCES += importicons.cpp
    173175
    174176# DiSEqC
    175177HEADERS += 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    bool 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
     56bool 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_closeDialog=true;
     220            m_listIcons->addSelection(QString("Channel icon for %1 was downloaded successfully.")
     221                                      .arg(entry2.strName));
     222        }
     223    }
     224    else
     225    {
     226        MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     227                            QObject::tr("Error downloading"),
     228                            QObject::tr("Failed to download the icon file"));
     229        enableControls(STATE_DISABLED);
     230        m_closeDialog=true;
     231    }
     232
     233}
     234
     235unsigned ImportIconsWizard::initialLoad(QString name)
     236{
     237    // Do not try and access dialog within this function
     238    VERBOSE(VB_CHANNEL, "initialLoad");
     239   
     240    QString querystring=("SELECT chanid,name,xmltvid,callsign,"
     241                  "dtv_multiplex.transportid, "
     242                  "atsc_major_chan,atsc_minor_chan,dtv_multiplex.networkid,"
     243                  "channel.serviceid, "
     244                  "channel.mplexid, dtv_multiplex.mplexid,"
     245                  "channel.icon, channel.visible FROM "
     246                  "channel, dtv_multiplex WHERE "
     247                  "channel.visible && "
     248                  "channel.mplexid=dtv_multiplex.mplexid");
     249    if (name.isEmpty()==false)
     250        querystring+=" && name=\"" + name + "\"";
     251    querystring+=" ORDER BY name";
     252
     253    MSqlQuery query(MSqlQuery::InitCon());
     254    query.prepare(querystring);
     255       
     256    m_listEntries.clear();           
     257    m_nCount=0;
     258    m_nMaxCount=0;
     259    m_missingMaxCount=0;
     260
     261    if (query.exec() && query.isActive() && query.size() > 0)
     262    {
     263        MythProgressDialog *progressDialog = new MythProgressDialog("Initialising, please wait...", query.size());
     264       
     265        sleep(2); // Ensures dialog is drawn before ping freezes execution
     266       
     267        if (!ping("services.mythtv.org", 3))
     268        {
     269            progressDialog->Close();
     270            progressDialog->deleteLater();
     271            MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     272                                  tr("Bad Host"),
     273                                  tr("Failed to connect to the remote server"));
     274            return 0;
     275        }
     276
     277        while(query.next())
     278        {
     279            CSVEntry entry;
     280
     281            if (m_fRefresh)
     282            {
     283                QFileInfo file(query.value(11).toString());
     284                if (file.exists())
     285                    continue;
     286            }
     287           
     288            entry.strChanId=query.value(0).toString();
     289            entry.strName=query.value(1).toString();
     290            entry.strXmlTvId=query.value(2).toString();
     291            entry.strCallsign=query.value(3).toString();
     292            entry.strTransportId=query.value(4).toString();
     293            entry.strAtscMajorChan=query.value(5).toString();
     294            entry.strAtscMinorChan=query.value(6).toString();
     295            entry.strNetworkId=query.value(7).toString();
     296            entry.strServiceId=query.value(8).toString();
     297            entry.strIconCSV= QString("%1,%2,%3,%4,%5,%6,%7,%8,%9\n").
     298                              arg(escape_csv(entry.strChanId)).
     299                              arg(escape_csv(entry.strName)).
     300                              arg(escape_csv(entry.strXmlTvId)).
     301                              arg(escape_csv(entry.strCallsign)).
     302                              arg(escape_csv(entry.strTransportId)).
     303                              arg(escape_csv(entry.strAtscMajorChan)).
     304                              arg(escape_csv(entry.strAtscMinorChan)).
     305                              arg(escape_csv(entry.strNetworkId)).
     306                              arg(escape_csv(entry.strServiceId));
     307            entry.strNameCSV=escape_csv(entry.strName);
     308            VERBOSE(VB_CHANNEL,QString("chanid %1").arg(entry.strIconCSV));
     309
     310            m_listEntries.append(entry);
     311            m_nMaxCount++;
     312            progressDialog->setProgress(m_nMaxCount);
     313        }
     314       
     315        progressDialog->Close();
     316        progressDialog->deleteLater();
     317    }
     318   
     319    m_iter = m_listEntries.begin();
     320   
     321    if (name.isEmpty()) // Scanning for multiple icons
     322    {
     323        MythProgressDialog *progressDialog = new MythProgressDialog("Downloading, please wait...",
     324                                m_listEntries.size()+1, true, this, SLOT(cancelPressed()));
     325        while (!m_closeDialog && (m_iter != m_listEntries.end()))
     326        {
     327            progressDialog->setLabel(QString("Downloading %1 / %2 : ").arg(m_nCount+1)
     328                                     .arg(m_listEntries.size()+1) + (*m_iter).strName +
     329                                     QString("\nCould not find %1 icons.").arg(m_missingEntries.size()+1));
     330            if (!findmissing((*m_iter).strIconCSV))
     331                m_missingEntries.append((*m_iter));
     332            m_nCount++;
     333            m_iter++;
     334            m_missingMaxCount++;
     335            progressDialog->setProgress(m_nCount);
     336        }
     337        progressDialog->Close();
     338        progressDialog->deleteLater();
     339    }
     340   
     341    //Comment below for debugging - cancel button will continue to dialog
     342    if (m_closeDialog)
     343        m_nMaxCount=0;
     344    return m_nMaxCount;
     345}
     346
     347bool ImportIconsWizard::doLoad()
     348{
     349    VERBOSE(VB_CHANNEL, QString("%1 / %2").arg(m_missingCount).arg(m_missingMaxCount));
     350    if (m_missingCount >= m_missingMaxCount)
     351    {
     352        VERBOSE(VB_CHANNEL, "doLoad Icon search complete");
     353        if (!m_strMatches.isEmpty())
     354            submit(m_strMatches);
     355        m_closeDialog=true;
     356        return false;
     357    }
     358    else
     359    {
     360        // Look for the next missing icon
     361        m_editName->setValue((*m_missingIter).strName);
     362        search((*m_missingIter).strNameCSV);
     363        return true;
     364    }
     365}
     366
     367QString ImportIconsWizard::escape_csv(const QString& str)
     368{
     369    VERBOSE(VB_CHANNEL, "escape_csv");
     370    QRegExp rxDblForEscape("\"");
     371    QString str2 = str;
     372    str2.replace(rxDblForEscape,"\\\"");
     373    return "\""+str2+"\"";
     374}
     375
     376QStringList ImportIconsWizard::extract_csv(const QString& strLine)
     377{
     378    VERBOSE(VB_CHANNEL, "extract_csv");
     379    QStringList ret;
     380    //Clean up the line and split out the fields
     381    QString str = strLine;
     382
     383    unsigned int pos = 0;
     384    bool fFinish = false;
     385    while(!fFinish)
     386    {
     387        str=str.stripWhiteSpace();
     388        while(!fFinish)
     389        {
     390            QString strLeft;
     391            switch (str.at(pos).unicode())
     392            {
     393            case '\\':
     394                if (pos>=1)
     395                    str.left(pos-1)+str.mid(pos+1);
     396                else
     397                    str=str.mid(pos+1);
     398                pos+=2;
     399                if (pos > str.length())
     400                {
     401                    strLeft = str.left(pos);
     402                    if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     403                        strLeft=strLeft.mid(1,strLeft.length()-2);
     404                    ret.append(strLeft);
     405                    fFinish = true;
     406                }
     407                break;
     408            case ',':
     409                strLeft = str.left(pos);
     410                if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     411                    strLeft=strLeft.mid(1,strLeft.length()-2);
     412                ret.append(strLeft);
     413                if ((pos+1) > str.length())
     414                   fFinish = true;
     415                str=str.mid(pos+1);
     416                pos=0;
     417                break;
     418            default:
     419                pos++;
     420                if (pos > str.length())
     421                {
     422                    strLeft = str.left(pos);
     423                    if (strLeft.startsWith("\"") && strLeft.endsWith("\""))
     424                        strLeft=strLeft.mid(1,strLeft.length()-2);
     425                    ret.append(strLeft);
     426                    fFinish = true;
     427                }
     428            }
     429        }
     430    }
     431    return ret;
     432}
     433
     434
     435QString ImportIconsWizard::wget(QUrl& url,const QString& strParam )
     436{
     437    VERBOSE(VB_CHANNEL, "wget");
     438    QByteArray raw;
     439    QTextStream rawStream(raw,IO_WriteOnly);
     440    rawStream << strParam;
     441
     442    QBuffer data(raw);
     443    QHttpRequestHeader header;
     444
     445    header.setContentType(QString("application/x-www-form-urlencoded"));
     446    header.setContentLength(raw.size());
     447
     448    header.setValue("User-Agent", "MythTV Channel Icon lookup bot");
     449
     450    QString str = HttpComms::postHttp(url,&header,&data);
     451
     452    return str;
     453}
     454
     455bool ImportIconsWizard::checkAndDownload(const QString& str)
     456{
     457    // Do not try and access dialog within this function
     458    VERBOSE(VB_CHANNEL, "checkAndDownload");
     459   
     460    int iIndex = str.findRev('/');
     461    QString str2;
     462    if (iIndex < 0)
     463        str2=str;
     464    else
     465        str2=str.mid(iIndex+1);
     466
     467    QString str3 = str;
     468    QFileInfo file(m_strChannelDir+str2);
     469
     470    bool fRet;
     471    if (!file.exists())
     472        fRet = HttpComms::getHttpFile(m_strChannelDir+str2,str3);   
     473    else
     474        fRet = true;
     475
     476    if (fRet)
     477    {
     478        MSqlQuery query(MSqlQuery::InitCon());
     479        QString  qstr = "UPDATE channel SET icon = :ICON "
     480                        "WHERE chanid = :CHANID";
     481
     482        query.prepare(qstr);
     483        query.bindValue(":ICON", m_strChannelDir+str2);
     484        query.bindValue(":CHANID", (*m_iter).strChanId);
     485
     486        if (!query.exec())
     487        {
     488            MythContext::DBError("Error inserting channel icon", query);
     489            return false;
     490        }
     491 
     492    }
     493
     494    return fRet;
     495}
     496
     497bool ImportIconsWizard::isBlocked(const QString& strParam)
     498{
     499    VERBOSE(VB_CHANNEL, "isBlocked");
     500    QString strParam1 = strParam;
     501    QUrl::encode(strParam1);
     502    QUrl url(ImportIconsWizard::url+"/checkblock");
     503    QString str = wget(url,"csv="+strParam1);
     504
     505    if (str.startsWith("Error",false))
     506    {
     507        VERBOSE(VB_IMPORTANT, QString("Error from isBlocked : %1").arg(str));
     508        return true;
     509    }
     510    else if (str.isEmpty() || str.startsWith("\r\n"))
     511        return false;
     512    else
     513    {
     514        VERBOSE(VB_CHANNEL, QString("Icon Import: Working isBlocked"));
     515        int nVal = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(),
     516                            QObject::tr("Icon is blocked"),
     517                            QObject::tr("This combination of channel and icon "
     518                                        "has been blocked by the MythTV "
     519                                        "admins. The most common reason for "
     520                                        "this is that there is a better match "
     521                                        "available.\n "
     522                                        "Are you still sure that you want to "
     523                                        "use this icon?"),
     524                          true);       
     525        if (nVal == 1) // Use the icon
     526            return false;
     527        else // Don't use the icon
     528            return true;
     529    }
     530}
     531
     532
     533bool ImportIconsWizard::lookup(const QString& strParam)
     534{
     535    QString strParam1 = "callsign="+strParam;
     536    QUrl::encode(strParam1);
     537    QUrl url(ImportIconsWizard::url+"/lookup");
     538
     539    QString str = wget(url,strParam1);
     540    if (str.isEmpty() || str.startsWith("Error",false))
     541    {
     542        VERBOSE(VB_IMPORTANT, QString("Error from lookup : %1").arg(str));
     543        return true;
     544    }
     545    else
     546    {
     547        VERBOSE(VB_CHANNEL, QString("Icon Import: Working lookup : %1").arg(str));
     548        return false;
     549    }
     550}
     551
     552bool ImportIconsWizard::search(const QString& strParam)
     553{
     554    QString strParam1 = strParam;
     555    bool retVal = false;
     556    enableControls(STATE_SEARCHING);
     557    QUrl::encode(strParam1);
     558    QUrl url(ImportIconsWizard::url+"/search");
     559
     560    QString str = wget(url,"s="+strParam1);
     561   
     562    m_listSearch.clear();
     563    m_listIcons->clearSelections();
     564
     565    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     566    {
     567        VERBOSE(VB_IMPORTANT, QString("Error from search : %1").arg(str));
     568        retVal=false;
     569    }
     570    else
     571    {
     572        VERBOSE(VB_CHANNEL, QString("Icon Import: Working search : %1").arg(str));
     573        QStringList strSplit=QStringList::split("\n",str);
     574
     575        for (QStringList::iterator begin=strSplit.begin();
     576             begin!=strSplit.end();begin++)
     577        {
     578            if (*begin != "#" )
     579            {
     580                QStringList ret = extract_csv(*begin);
     581                VERBOSE(VB_CHANNEL, QString("Icon Import: search : %1 %2 %3").arg(ret[0]).arg(ret[1]).arg(ret[2]));
     582                SearchEntry entry;
     583                entry.strID=ret[0];
     584                entry.strName=ret[1];
     585                entry.strLogo=ret[2];
     586                m_listSearch.append(entry);
     587                m_listIcons->addSelection(entry.strName);
     588            }
     589        }
     590        retVal=true;
     591    }
     592    enableControls(STATE_NORMAL, retVal);
     593    return retVal;
     594}
     595
     596bool ImportIconsWizard::findmissing(const QString& strParam)
     597{
     598    QString strParam1 = strParam;
     599    QUrl::encode(strParam1);
     600    QUrl url(ImportIconsWizard::url+"/findmissing");
     601
     602    QString str = wget(url,"csv="+strParam1);
     603    VERBOSE(VB_CHANNEL, QString("Icon Import: findmissing : strParam1 = %1. str = %2").arg(strParam1).arg(str));   
     604    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     605    {
     606        VERBOSE(VB_IMPORTANT, QString("Error from findmissing : %1").arg(str));
     607        return false;
     608    }
     609    else
     610    {
     611        VERBOSE(VB_CHANNEL, QString("Icon Import: Working findmissing : %1").arg(str));
     612        QStringList strSplit=QStringList::split("\n",str);
     613        for (QStringList::iterator begin=strSplit.begin();
     614             begin!=strSplit.end();begin++)
     615        {
     616            if (*begin != "#" )
     617            {
     618                QStringList ret = extract_csv(*begin);
     619                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]));
     620                checkAndDownload(ret[4]);
     621            }
     622        }
     623        return true;
     624    }
     625}
     626
     627bool ImportIconsWizard::submit(const QString& strParam)
     628{
     629    enableControls(STATE_DISABLED);
     630   
     631    int nVal = MythPopupBox::showOkCancelPopup(
     632                            gContext->GetMainWindow(),
     633                            QObject::tr("Submit information"),
     634                            QObject::tr("You now have the opportunity to "
     635                                        "transmit your choices  back to "
     636                                        "mythtv.org so that others can "
     637                                        "benefit from your selections."),
     638                            true);       
     639    if (nVal == 0) // If cancel is pressed exit
     640        return false;
     641   
     642    QString strParam1 = strParam;
     643    QUrl::encode(strParam1);
     644    QUrl url(ImportIconsWizard::url+"/submit");
     645
     646    QString str = wget(url,"csv="+strParam1);
     647    if (str.isEmpty() || str.startsWith("#") || str.startsWith("Error",false))
     648    {
     649        VERBOSE(VB_IMPORTANT, QString("Error from submit : %1").arg(str));
     650        return false;
     651    }
     652    else
     653    {
     654        VERBOSE(VB_CHANNEL, QString("Icon Import: Working submit : %1").arg(str));
     655        QStringList strSplit=QStringList::split("\n",str);
     656        unsigned atsc =0, dvb =0, callsign =0, tv =0, xmltvid=0;
     657        for (QStringList::iterator begin=strSplit.begin();
     658             begin!=strSplit.end();begin++)
     659        {
     660            if (*begin != "#" )
     661            {
     662                QStringList strSplit2=QStringList::split(":",*begin);
     663                QString s=strSplit2[0].stripWhiteSpace();
     664                if (s=="a")
     665                     atsc=strSplit2[1].toUInt();
     666                else if (s=="c")
     667                     callsign=strSplit2[1].toUInt();
     668                else if (s=="d")
     669                     dvb=strSplit2[1].toUInt();
     670                else if (s=="t")
     671                     tv=strSplit2[1].toUInt();
     672                else if (s=="x")
     673                     xmltvid=strSplit2[1].toUInt();
     674            }
     675        }
     676        VERBOSE(VB_CHANNEL, QString("Icon Import: working submit : atsc=%1 callsign=%2 dvb=%3 tv=%4 xmltvid=%5")
     677                                              .arg(atsc).arg(callsign).arg(dvb).arg(tv).arg(xmltvid));
     678        return true;
     679    }
     680}
     681
     682void ImportIconsWizard::cancelPressed()
     683{
     684    m_closeDialog=true;
     685}
     686
     687void ImportIconsWizard::finishButtonPressed()
     688{
     689    m_closeDialog = true;
     690}