Ticket #8494: 8494-v1.patch

File 8494-v1.patch, 119.4 KB (added by danielk, 11 years ago)

Fixes a number of problems with proglist

  • libs/libmyth/autodeletedeque.h

     
    1515    typedef typename std::deque< T > List;
    1616    typedef typename List::iterator iterator;
    1717    typedef typename List::const_iterator const_iterator;
     18    typedef typename List::reverse_iterator reverse_iterator;
     19    typedef typename List::const_reverse_iterator const_reverse_iterator;
    1820
    1921    T operator[](uint index)
    2022    {
     
    5052    iterator end(void)               { return list.end();   }
    5153    const_iterator begin(void) const { return list.begin(); }
    5254    const_iterator end(void)   const { return list.end();   }
     55    reverse_iterator rbegin(void)             { return list.rbegin(); }
     56    reverse_iterator rend(void)               { return list.rend();   }
     57    const_reverse_iterator rbegin(void) const { return list.rbegin(); }
     58    const_reverse_iterator rend(void)   const { return list.rend();   }
    5359
    5460    T back(void)                     { return list.back();  }
    5561    const T back(void)         const { return list.back();  }
  • programs/mythfrontend/proglist.h

     
    33
    44// Qt headers
    55#include <QDateTime>
     6#include <QString>
    67
    78// MythTV headers
    8 #include "mythscreentype.h"
    9 #include "programinfo.h"
    10 #include "mythwidgets.h"
    11 
    12 // mythfrontend
     9#include "programinfo.h" // for ProgramList
    1310#include "schedulecommon.h"
     11#include "proglist_helpers.h"
    1412
    1513enum ProgListType {
    1614    plUnknown = 0,
     
    3028    plPreviouslyRecorded
    3129};
    3230
    33 class MythUIText;
    34 class MythUIButtonList;
    35 class ProgLister;
    36 
    37 class PhrasePopup : public MythScreenType
     31class ProgLister : public ScheduleCommon
    3832{
    39     Q_OBJECT
     33    friend class PhrasePopup;
     34    friend class TimePopup;
     35    friend class PowerSearchPopup;
     36    friend class EditPowerSearchPopup;
    4037
    41   public:
    42     PhrasePopup(MythScreenStack *parentStack,
    43                 ProgLister *parent,
    44                 RecSearchType searchType,
    45                 const QStringList &list,
    46                 const QString &currentValue);
    47 
    48     bool Create();
    49 
    50   signals:
    51     void haveResult(QString item);
    52 
    53   private slots:
    54     void okClicked(void);
    55     void deleteClicked(void);
    56     void recordClicked(void);
    57     void phraseClicked(MythUIButtonListItem *item);
    58     void phraseSelected(MythUIButtonListItem *item);
    59     void editChanged(void);
    60 
    61   private:
    62     ProgLister      *m_parent;
    63     RecSearchType    m_searchType;
    64     QStringList      m_list;
    65     QString          m_currentValue;
    66 
    67     MythUIText       *m_titleText;
    68     MythUIButtonList *m_phraseList;
    69     MythUITextEdit   *m_phraseEdit;
    70     MythUIButton     *m_okButton;
    71     MythUIButton     *m_deleteButton;
    72     MythUIButton     *m_recordButton;
    73 };
    74 
    75 class TimePopup : public MythScreenType
    76 {
    7738    Q_OBJECT
    7839
    7940  public:
    80     TimePopup(MythScreenStack *parentStack, ProgLister *parent);
    81 
    82     bool Create();
    83 
    84   signals:
    85     void haveResult(QDateTime time);
    86 
    87   private slots:
    88     void okClicked(void);
    89 
    90   private:
    91     ProgLister      *m_parent;
    92     QStringList      m_list;
    93     QString          m_currentValue;
    94 
    95     MythUIButtonList *m_dateList;
    96     MythUIButtonList *m_timeList;
    97     MythUIButton     *m_okButton;
    98 };
    99 
    100 class PowerSearchPopup : public MythScreenType
    101 {
    102     Q_OBJECT
    103 
    104   public:
    105     PowerSearchPopup(MythScreenStack *parentStack,
    106                 ProgLister *parent,
    107                 RecSearchType searchType,
    108                 const QStringList &list,
    109                 const QString &currentValue);
    110 
    111     bool Create();
    112 
    113   signals:
    114     void haveResult(QString item);
    115 
    116   private slots:
    117     void editClicked(void);
    118     void deleteClicked(void);
    119     void recordClicked(void);
    120     void phraseClicked(MythUIButtonListItem *item);
    121     void phraseSelected(MythUIButtonListItem *item);
    122 
    123   private:
    124     ProgLister      *m_parent;
    125     RecSearchType    m_searchType;
    126     QStringList      m_list;
    127     QString          m_currentValue;
    128 
    129     MythUIText       *m_titleText;
    130     MythUIButtonList *m_phraseList;
    131     MythUITextEdit   *m_phraseEdit;
    132     MythUIButton     *m_editButton;
    133     MythUIButton     *m_deleteButton;
    134     MythUIButton     *m_recordButton;
    135 };
    136 
    137 class EditPowerSearchPopup : public MythScreenType
    138 {
    139     Q_OBJECT
    140 
    141   public:
    142     EditPowerSearchPopup(MythScreenStack *parentStack, ProgLister *parent,
    143                          const QString &currentValue);
    144 
    145     bool Create();
    146 
    147   private slots:
    148     void okClicked(void);
    149 
    150   private:
    151     void initLists(void);
    152 
    153     ProgLister      *m_parent;
    154     QStringList      m_categories;
    155     QStringList      m_genres;
    156     QStringList      m_channels;
    157 
    158     QString          m_currentValue;
    159 
    160     MythUITextEdit   *m_titleEdit;
    161     MythUITextEdit   *m_subtitleEdit;
    162     MythUITextEdit   *m_descEdit;
    163     MythUIButtonList *m_categoryList;
    164     MythUIButtonList *m_genreList;
    165     MythUIButtonList *m_channelList;
    166 
    167     MythUIButton     *m_okButton;
    168 };
    169 
    170 class ProgLister : public ScheduleCommon
    171 {
    172   friend class PhrasePopup;
    173   friend class TimePopup;
    174   friend class PowerSearchPopup;
    175   friend class EditPowerSearchPopup;
    176 
    177   Q_OBJECT
    178 
    179   public:
    18041    ProgLister(MythScreenStack *parent, ProgListType pltype,
    18142               const QString &view, const QString &from);
    182     explicit ProgLister(MythScreenStack *parent, int recid = 0,
     43    explicit ProgLister(MythScreenStack *parent, uint recid = 0,
    18344                        const QString &title = QString());
    18445    ~ProgLister();
    18546
     
    19253    void nextView(void);
    19354    void setViewFromTime(QDateTime searchTime);
    19455    void select(void);
    195     void edit(void);
    196     void customEdit(void);
     56    void edit(void) { EditScheduled(GetCurrent()); }
     57    void customEdit(void) { EditCustom(GetCurrent()); }
    19758    void deleteItem(void);
    19859    void deleteRule(void);
    19960    void deleteOldEpisode(void);
    20061    void deleteOldTitle(void);
    20162    void oldRecordedActions(void);
    20263    void upcoming(void);
    203     void details(void);
     64    void details(void) { ShowDetails(GetCurrent()); }
    20465    void chooseView(void);
    20566    void updateInfo(MythUIButtonListItem *item);
    20667    void setViewFromList(QString item);
    20768    void doDeleteOldEpisode(bool ok);
    20869    void doDeleteOldTitle(bool ok);
    209     void showSortMenu();
    210 
    211   protected:
     70    void showSortMenu(void);
    21271    void quickRecord(void);
    21372
    21473  private:
     
    22584    void updateKeywordInDB(const QString &text, const QString &oldValue);
    22685
    22786    void ShowMenu(void);
    228    
    229     ProgListType m_type;
    230     int          m_recid;
    231     QString      m_title;
    232     QString      m_addTables;
    233     QDateTime    m_startTime;
    234     QDateTime    m_searchTime;
    235     QString      m_dayFormat;
    236     QString      m_hourFormat;
    237     QString      m_timeFormat;
    238     QString      m_fullDateFormat;
    239     QString      m_channelOrdering;
    240     QString      m_channelFormat;
    24187
    242     RecSearchType m_searchType;
     88    const ProgramInfo *GetCurrent(void) const;
     89    ProgramInfo *GetCurrent(void);
    24390
    244     QString       m_view;
    245     int           m_curView;
    246     QStringList   m_viewList;
    247     QStringList   m_viewTextList;
     91    typedef enum { kTimeSort, kPrevTitleSort, kTitleSort, } SortBy;
     92    SortBy GetSortBy(void) const;
     93    void SortList(SortBy sortby, bool reverseSort);
    24894
    249     ProgramList   m_itemList;
    250     ProgramList   m_schedList;
     95  private:
     96    ProgListType      m_type;
     97    uint              m_recid;
     98    QString           m_title;
     99    QString           m_addTables;
     100    QDateTime         m_startTime;
     101    QDateTime         m_searchTime;
     102    QString           m_dayFormat;
     103    QString           m_hourFormat;
     104    QString           m_timeFormat;
     105    QString           m_fullDateFormat;
     106    QString           m_channelOrdering;
     107    QString           m_channelFormat;
    251108
    252     QStringList   m_typeList;
    253     QStringList   m_genreList;
    254     QStringList   m_stationList;
     109    RecSearchType     m_searchType;
    255110
    256     bool m_allowEvents;
    257     bool m_titleSort;
    258     bool m_reverseSort;
    259     bool m_useGenres;
     111    QString           m_view;
     112    int               m_curView;
     113    QStringList       m_viewList;
     114    QStringList       m_viewTextList;
    260115
     116    ProgramList       m_itemList;
     117    ProgramList       m_schedList;
     118
     119    QStringList       m_typeList;
     120    QStringList       m_genreList;
     121    QStringList       m_stationList;
     122
     123    bool              m_allowEvents;
     124    bool              m_titleSort;
     125    bool              m_reverseSort;
     126    bool              m_useGenres;
     127
    261128    MythUIText       *m_schedText;
    262129    MythUIText       *m_curviewText;
    263130    MythUIText       *m_positionText;
  • programs/mythfrontend/proglist_helpers.h

     
     1#ifndef _PROGLIST_HELPERS_H_
     2#define _PROGLIST_HELPERS_H_
     3
     4// Qt headers
     5#include <QDateTime>
     6
     7// MythTV headers
     8#include "mythscreentype.h"
     9#include "mythwidgets.h"
     10#include "recordingtypes.h"
     11
     12class MythUIText;
     13class MythUIButtonList;
     14class ProgLister;
     15
     16class PhrasePopup : public MythScreenType
     17{
     18    Q_OBJECT
     19
     20  public:
     21    PhrasePopup(MythScreenStack *parentStack,
     22                ProgLister *parent,
     23                RecSearchType searchType,
     24                const QStringList &list,
     25                const QString &currentValue);
     26
     27    bool Create();
     28
     29  signals:
     30    void haveResult(QString item);
     31
     32  private slots:
     33    void okClicked(void);
     34    void deleteClicked(void);
     35    void recordClicked(void);
     36    void phraseClicked(MythUIButtonListItem *item);
     37    void phraseSelected(MythUIButtonListItem *item);
     38    void editChanged(void);
     39
     40  private:
     41    ProgLister      *m_parent;
     42    RecSearchType    m_searchType;
     43    QStringList      m_list;
     44    QString          m_currentValue;
     45
     46    MythUIText       *m_titleText;
     47    MythUIButtonList *m_phraseList;
     48    MythUITextEdit   *m_phraseEdit;
     49    MythUIButton     *m_okButton;
     50    MythUIButton     *m_deleteButton;
     51    MythUIButton     *m_recordButton;
     52};
     53
     54class TimePopup : public MythScreenType
     55{
     56    Q_OBJECT
     57
     58  public:
     59    TimePopup(MythScreenStack *parentStack, ProgLister *parent);
     60
     61    bool Create();
     62
     63  signals:
     64    void haveResult(QDateTime time);
     65
     66  private slots:
     67    void okClicked(void);
     68
     69  private:
     70    ProgLister      *m_parent;
     71    QStringList      m_list;
     72    QString          m_currentValue;
     73
     74    MythUIButtonList *m_dateList;
     75    MythUIButtonList *m_timeList;
     76    MythUIButton     *m_okButton;
     77};
     78
     79class PowerSearchPopup : public MythScreenType
     80{
     81    Q_OBJECT
     82
     83  public:
     84    PowerSearchPopup(MythScreenStack *parentStack,
     85                ProgLister *parent,
     86                RecSearchType searchType,
     87                const QStringList &list,
     88                const QString &currentValue);
     89
     90    bool Create();
     91
     92  signals:
     93    void haveResult(QString item);
     94
     95  private slots:
     96    void editClicked(void);
     97    void deleteClicked(void);
     98    void recordClicked(void);
     99    void phraseClicked(MythUIButtonListItem *item);
     100    void phraseSelected(MythUIButtonListItem *item);
     101
     102  private:
     103    ProgLister      *m_parent;
     104    RecSearchType    m_searchType;
     105    QStringList      m_list;
     106    QString          m_currentValue;
     107
     108    MythUIText       *m_titleText;
     109    MythUIButtonList *m_phraseList;
     110    MythUITextEdit   *m_phraseEdit;
     111    MythUIButton     *m_editButton;
     112    MythUIButton     *m_deleteButton;
     113    MythUIButton     *m_recordButton;
     114};
     115
     116class EditPowerSearchPopup : public MythScreenType
     117{
     118    Q_OBJECT
     119
     120  public:
     121    EditPowerSearchPopup(MythScreenStack *parentStack, ProgLister *parent,
     122                         const QString &currentValue);
     123
     124    bool Create();
     125
     126  private slots:
     127    void okClicked(void);
     128
     129  private:
     130    void initLists(void);
     131
     132    ProgLister      *m_parent;
     133    QStringList      m_categories;
     134    QStringList      m_genres;
     135    QStringList      m_channels;
     136
     137    QString          m_currentValue;
     138
     139    MythUITextEdit   *m_titleEdit;
     140    MythUITextEdit   *m_subtitleEdit;
     141    MythUITextEdit   *m_descEdit;
     142    MythUIButtonList *m_categoryList;
     143    MythUIButtonList *m_genreList;
     144    MythUIButtonList *m_channelList;
     145
     146    MythUIButton     *m_okButton;
     147};
     148
     149#endif // _PROGLIST_HELPERS_H_
  • programs/mythfrontend/mythfrontend.pro

     
    2424HEADERS += manualschedule.h programrecpriority.h channelrecpriority.h
    2525HEADERS += statusbox.h networkcontrol.h custompriority.h
    2626HEADERS += mediarenderer.h mythfexml.h playbackboxlistitem.h
    27 HEADERS += mythappearance.h exitprompt.h proglist.h
     27HEADERS += mythappearance.h exitprompt.h
    2828HEADERS += action.h mythcontrols.h keybindings.h keygrabber.h
    2929HEADERS += mythosdmenueditor.h progfind.h guidegrid.h customedit.h
    3030HEADERS += schedulecommon.h progdetails.h scheduleeditor.h
    31 HEADERS += backendconnectionmanager.h programinfocache.h
    32 HEADERS += playbackboxhelper.h
    33 HEADERS += viewschedulediff.h
     31HEADERS += backendconnectionmanager.h   programinfocache.h
     32HEADERS += proglist.h                   proglist_helpers.h
     33HEADERS += playbackboxhelper.h          viewschedulediff.h
    3434
    3535SOURCES += main.cpp playbackbox.cpp viewscheduled.cpp
    3636SOURCES += globalsettings.cpp manualschedule.cpp programrecpriority.cpp
    3737SOURCES += channelrecpriority.cpp statusbox.cpp networkcontrol.cpp
    3838SOURCES += mediarenderer.cpp mythfexml.cpp playbackboxlistitem.cpp
    39 SOURCES += custompriority.cpp mythappearance.cpp exitprompt.cpp proglist.cpp
     39SOURCES += custompriority.cpp mythappearance.cpp exitprompt.cpp
    4040SOURCES += action.cpp actionset.cpp  mythcontrols.cpp keybindings.cpp
    4141SOURCES += keygrabber.cpp mythosdmenueditor.cpp progfind.cpp guidegrid.cpp
    4242SOURCES += customedit.cpp schedulecommon.cpp progdetails.cpp scheduleeditor.cpp
    4343SOURCES += backendconnectionmanager.cpp programinfocache.cpp
    44 SOURCES += playbackboxhelper.cpp
    45 SOURCES += viewschedulediff.cpp
     44SOURCES += proglist.cpp                 proglist_helpers.cpp
     45SOURCES += playbackboxhelper.cpp        viewschedulediff.cpp
    4646
    4747macx {
    4848    mac_bundle {
  • programs/mythfrontend/proglist.cpp

     
    1 
    2 #include "proglist.h"
    3 
    41// C/C++
    5 #include <iostream>
    6 #include <map>
    72#include <vector>
    83#include <algorithm>
    94using namespace std;
     
    138#include <QRegExp>
    149
    1510// MythTV
    16 #include "mythcorecontext.h"
    17 #include "remoteutil.h"
    1811#include "scheduledrecording.h"
     12#include "mythuibuttonlist.h"
     13#include "mythcorecontext.h"
     14#include "mythdialogbox.h"
     15#include "recordinginfo.h"
    1916#include "recordingrule.h"
    2017#include "channelutil.h"
    21 #include "recordinginfo.h"
     18#include "proglist.h"
    2219#include "mythdb.h"
    23 #include "mythdbcon.h"
    24 #include "mythverbose.h"
    25 #include "mythuitext.h"
    26 #include "mythuibutton.h"
    27 #include "mythuibuttonlist.h"
    28 #include "mythdialogbox.h"
    2920
    30 // MythFrontend
    31 #include "customedit.h"
    32 #include "scheduleeditor.h"
     21#define LOC      QString("ProgLister: ")
     22#define LOC_WARN QString("ProgLister, Warning: ")
     23#define LOC_ERR  QString("ProgLister, Error: ")
    3324
    3425ProgLister::ProgLister(MythScreenStack *parent, ProgListType pltype,
    35                const QString &view, const QString &from)
    36           : ScheduleCommon(parent, "ProgLister")
    37 {
    38     m_type = pltype;
    39     m_addTables = from;
    40     m_startTime = QDateTime::currentDateTime();
    41     m_searchTime = m_startTime;
     26                       const QString &view, const QString &from) :
     27    ScheduleCommon(parent, "ProgLister"),
     28    m_type(pltype),
     29    m_recid(0),
     30    m_title(),
     31    m_addTables(from),
     32    m_startTime(QDateTime::currentDateTime()),
     33    m_searchTime(m_startTime),
     34    m_dayFormat(gCoreContext->GetSetting("DateFormat")),
     35    m_hourFormat(gCoreContext->GetSetting("TimeFormat")),
     36    m_timeFormat(),
     37    m_fullDateFormat(
     38        QString("%1 %2").arg(m_dayFormat).arg(m_hourFormat)),
     39    m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
     40    m_channelFormat(gCoreContext->GetSetting("ChannelFormat", "<num> <sign>")),
    4241
    43     m_dayFormat = gCoreContext->GetSetting("DateFormat");
    44     m_hourFormat = gCoreContext->GetSetting("TimeFormat");
    45     m_fullDateFormat = m_dayFormat + ' ' + m_hourFormat;
    46     m_channelOrdering = gCoreContext->GetSetting("ChannelOrdering", "channum");
    47     m_channelFormat = gCoreContext->GetSetting("ChannelFormat", "<num> <sign>");
     42    m_searchType(kNoSearch),
    4843
    49     m_schedText = m_curviewText = m_positionText = m_messageText = NULL;
    50     m_positionText = NULL;
    51     m_progList = NULL;
     44    m_view(view),
     45    m_curView(-1),
     46    m_viewList(),
     47    m_viewTextList(),
    5248
     49    m_itemList(),
     50    m_schedList(),
     51
     52    m_typeList(),
     53    m_genreList(),
     54    m_stationList(),
     55
     56    m_allowEvents(true),
     57    m_titleSort(false),
     58    m_reverseSort(false),
     59    m_useGenres(false),
     60
     61    m_schedText(NULL),
     62    m_curviewText(NULL),
     63    m_positionText(NULL),
     64    m_progList(NULL),
     65    m_messageText(NULL)
     66{
    5367    switch (pltype)
    5468    {
    5569        case plTitleSearch:   m_searchType = kTitleSearch;   break;
     
    6074        case plStoredSearch:  m_searchType = kPowerSearch;   break;
    6175        default:              m_searchType = kNoSearch;      break;
    6276    }
    63 
    64     m_allowEvents = true;
    65     m_titleSort = false;
    66     m_reverseSort = false;
    67     m_useGenres = false;
    68 
    69     m_curView = -1;
    70     m_view = view;
    71     m_view.detach();
    7277}
    7378
    7479// previously recorded ctor
    75 ProgLister::ProgLister(MythScreenStack *parent, int recid, const QString &title)
    76           : ScheduleCommon(parent, "PreviousList")
    77 {
    78     m_type = plPreviouslyRecorded;
    79     m_recid = recid;
    80     m_title = title;
     80ProgLister::ProgLister(
     81    MythScreenStack *parent, uint recid, const QString &title) :
     82    ScheduleCommon(parent, "PreviousList"),
     83    m_type(plPreviouslyRecorded),
     84    m_recid(recid),
     85    m_title(title),
     86    m_addTables(),
     87    m_startTime(QDateTime::currentDateTime()),
     88    m_searchTime(m_startTime),
     89    m_dayFormat(gCoreContext->GetSetting("DateFormat")),
     90    m_hourFormat(gCoreContext->GetSetting("TimeFormat")),
     91    m_timeFormat(
     92        QString("%1 %2")
     93        .arg(gCoreContext->GetSetting("ShortDateFormat"))
     94        .arg(m_hourFormat)),
     95    m_fullDateFormat(
     96        QString("%1 %2").arg(m_dayFormat).arg(m_hourFormat)),
     97    m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
     98    m_channelFormat(gCoreContext->GetSetting("ChannelFormat", "<num> <sign>")),
    8199
    82     m_addTables.clear();
    83     m_startTime = QDateTime::currentDateTime();
    84     m_searchTime = m_startTime;
     100    m_searchType(kNoSearch),
    85101
    86     m_dayFormat = gCoreContext->GetSetting("DateFormat");
    87     m_hourFormat = gCoreContext->GetSetting("TimeFormat");
    88     m_timeFormat = gCoreContext->GetSetting("ShortDateFormat") + ' ' + m_hourFormat;
    89     m_fullDateFormat = m_dayFormat + ' ' + m_hourFormat;
    90     m_channelOrdering = gCoreContext->GetSetting("ChannelOrdering", "channum");
    91     m_channelFormat = gCoreContext->GetSetting("ChannelFormat", "<num> <sign>");
     102    m_view("reverse time"),
     103    m_curView(-1),
     104    m_viewList(),
     105    m_viewTextList(),
    92106
    93     m_schedText = m_curviewText = m_positionText = m_messageText = NULL;
    94     m_positionText = NULL;
    95     m_progList = NULL;
    96     m_searchType = kNoSearch;
     107    m_itemList(),
     108    m_schedList(),
    97109
    98     m_allowEvents = true;
    99     m_titleSort = false;
    100     m_reverseSort = true;
    101     m_useGenres = false;
     110    m_typeList(),
     111    m_genreList(),
     112    m_stationList(),
    102113
    103     m_curView = -1;
    104     m_view = "reverse time";
     114    m_allowEvents(true),
     115    m_titleSort(false),
     116    m_reverseSort(false),
     117    m_useGenres(false),
     118
     119    m_schedText(NULL),
     120    m_curviewText(NULL),
     121    m_positionText(NULL),
     122    m_progList(NULL),
     123    m_messageText(NULL)
     124{
    105125}
    106126
    107127ProgLister::~ProgLister()
     
    129149    }
    130150
    131151    connect(m_progList, SIGNAL(itemSelected(MythUIButtonListItem*)),
    132             SLOT(updateInfo(MythUIButtonListItem*)));
     152            this,       SLOT(  updateInfo(  MythUIButtonListItem*)));
    133153
    134154    connect(m_progList, SIGNAL(itemClicked(MythUIButtonListItem*)),
    135             SLOT(select()));
     155            this,       SLOT(  select()));
    136156
    137     m_progList->SetLCDTitles(tr("Program List"), "title|channel|shortstarttimedate");
     157    m_progList->SetLCDTitles(
     158        tr("Program List"), "title|channel|shortstarttimedate");
    138159
    139160    BuildFocusList();
    140161
    141162    QString value;
    142163    switch (m_type)
    143164    {
    144         case plTitle: value = tr("Program Listings"); break;
    145         case plNewListings: value = tr("New Title Search"); break;
    146         case plTitleSearch: value = tr("Title Search"); break;
    147         case plKeywordSearch: value = tr("Keyword Search"); break;
    148         case plPeopleSearch: value = tr("People Search"); break;
    149         case plStoredSearch: value = tr("Stored Search"); break;
    150         case plPowerSearch: value = tr("Power Search"); break;
    151         case plSQLSearch: value = tr("Power Search"); break;
    152         case plRecordid: value = tr("Rule Search"); break;
    153         case plCategory: value = tr("Category Search"); break;
    154         case plChannel: value = tr("Channel Search"); break;
    155         case plMovies: value = tr("Movie Search"); break;
    156         case plTime: value = tr("Time Search"); break;
     165        case plTitle:              value = tr("Program Listings"); break;
     166        case plNewListings:        value = tr("New Title Search"); break;
     167        case plTitleSearch:        value = tr("Title Search");    break;
     168        case plKeywordSearch:      value = tr("Keyword Search");  break;
     169        case plPeopleSearch:       value = tr("People Search");    break;
     170        case plStoredSearch:       value = tr("Stored Search");    break;
     171        case plPowerSearch:        value = tr("Power Search");    break;
     172        case plSQLSearch:          value = tr("Power Search");    break;
     173        case plRecordid:           value = tr("Rule Search");      break;
     174        case plCategory:           value = tr("Category Search"); break;
     175        case plChannel:            value = tr("Channel Search");  break;
     176        case plMovies:             value = tr("Movie Search");    break;
     177        case plTime:               value = tr("Time Search");      break;
    157178        case plPreviouslyRecorded: value = tr("Previously Recorded"); break;
    158         default: value = tr("Unknown Search"); break;
     179        default:                   value = tr("Unknown Search");  break;
    159180    }
    160181
    161182    if (m_schedText)
     
    185206    if (!m_allowEvents)
    186207        return true;
    187208
    188     m_allowEvents = false;
    189 
    190209    if (GetFocusWidget() && GetFocusWidget()->keyPressEvent(e))
    191210    {
    192211        m_allowEvents = true;
    193212        return true;
    194213    }
    195214
    196     bool handled = false;
    197     bool needUpdate = false;
     215    m_allowEvents = false;
    198216
    199217    QStringList actions;
    200     handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", e, actions);
     218    bool handled = GetMythMainWindow()->TranslateKeyPress(
     219        "TV Frontend", e, actions);
    201220
    202     for (int i = 0; i < actions.size() && !handled; ++i)
     221    bool needUpdate = false;
     222    for (uint i = 0; i < uint(actions.size()) && !handled; ++i)
    203223    {
    204224        QString action = actions[i];
    205225        handled = true;
     
    247267            needUpdate = true;
    248268        }
    249269        else
     270        {
    250271            handled = false;
     272        }
    251273    }
    252274
    253275    if (!handled && MythScreenType::keyPressEvent(e))
     
    266288    QString label = tr("Options");
    267289
    268290    MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    269     MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
     291    MythDialogBox *menuPopup = new MythDialogBox(
     292        label, popupStack, "menuPopup");
    270293
    271     if (menuPopup->Create())
     294    if (!menuPopup->Create())
    272295    {
    273         menuPopup->SetReturnEvent(this, "menu");
    274         if (m_type != plPreviouslyRecorded)
    275             menuPopup->AddButton(tr("Choose Search Phrase..."));
    276         menuPopup->AddButton(tr("Sort"), NULL, true);
    277         if (m_type != plPreviouslyRecorded)
    278             menuPopup->AddButton(tr("Record"));
    279         menuPopup->AddButton(tr("Edit Schedule"));
    280         menuPopup->AddButton(tr("Program Details"));
    281         menuPopup->AddButton(tr("Upcoming"));
    282         menuPopup->AddButton(tr("Custom Edit"));
     296        delete menuPopup;
     297        return;
     298    }
    283299
    284         ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    285         if (m_type != plPreviouslyRecorded)
    286         {
    287             if (pi && pi->GetRecordingRuleID())
    288                 menuPopup->AddButton(tr("Delete Rule"));
    289         }
    290         else
    291             menuPopup->AddButton(tr("Delete Episode"));
     300    menuPopup->SetReturnEvent(this, "menu");
    292301
    293         menuPopup->AddButton(tr("Cancel"));
     302    if (m_type != plPreviouslyRecorded)
     303    {
     304        menuPopup->AddButton(tr("Choose Search Phrase..."),
     305                             SLOT(chooseView()));
     306    }
    294307
    295         popupStack->AddScreen(menuPopup);
     308    menuPopup->AddButton(tr("Sort"), SLOT(showSortMenu()), true);
     309
     310    if (m_type != plPreviouslyRecorded)
     311        menuPopup->AddButton(tr("Record"), SLOT(quickRecord()));
     312
     313    menuPopup->AddButton(tr("Edit Schedule"), SLOT(edit()));
     314    menuPopup->AddButton(tr("Program Details"), SLOT(details()));
     315    menuPopup->AddButton(tr("Upcoming"), SLOT(upcoming()));
     316    menuPopup->AddButton(tr("Custom Edit"), SLOT(customEdit()));
     317
     318    ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     319    if (m_type != plPreviouslyRecorded)
     320    {
     321        if (pi && pi->GetRecordingRuleID())
     322            menuPopup->AddButton(tr("Delete Rule"), SLOT(deleteRule()));
    296323    }
    297324    else
    298325    {
    299         delete menuPopup;
     326        menuPopup->AddButton(tr("Delete Episode"), SLOT(deleteOldEpisode()));
    300327    }
     328
     329    menuPopup->AddButton(tr("Cancel"));
     330
     331    popupStack->AddScreen(menuPopup);
    301332}
    302333
    303334void ProgLister::showSortMenu(void)
    304335{
    305     QString label = tr("Sort Options");
    306 
    307336    MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    308     MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
     337    MythDialogBox *menuPopup = new MythDialogBox(
     338        tr("Sort Options"), popupStack, "menuPopup");
    309339
    310     if (menuPopup->Create())
     340    if (!menuPopup->Create())
    311341    {
    312         menuPopup->SetReturnEvent(this, "sortmenu");
    313 
    314         menuPopup->AddButton(tr("Reverse Sort Order"));
    315         menuPopup->AddButton(tr("Sort By Title"));
    316         menuPopup->AddButton(tr("Sort By Time"));
    317         menuPopup->AddButton(tr("Cancel"));
    318 
    319         popupStack->AddScreen(menuPopup);
    320     }
    321     else
    322     {
    323342        delete menuPopup;
     343        return;
    324344    }
     345
     346    menuPopup->SetReturnEvent(this, "sortmenu");
     347
     348    menuPopup->AddButton(tr("Reverse Sort Order"));
     349    menuPopup->AddButton(tr("Sort By Title"));
     350    menuPopup->AddButton(tr("Sort By Time"));
     351    menuPopup->AddButton(tr("Cancel"));
     352
     353    popupStack->AddScreen(menuPopup);
    325354}
    326355
    327356void ProgLister::prevView(void)
    328357{
    329     if (m_type == plTime)
     358    if (m_type == plTime && !m_viewList.empty() && !m_viewTextList.empty())
    330359    {
    331360        m_searchTime = m_searchTime.addSecs(-3600);
    332361        m_curView = 0;
    333         m_viewList[m_curView] = m_searchTime.toString(m_fullDateFormat);
     362        m_viewList[m_curView]     = m_searchTime.toString(m_fullDateFormat);
    334363        m_viewTextList[m_curView] = m_viewList[m_curView];
    335364        LoadInBackground();
    336 
    337365        return;
    338366    }
    339367
    340     if (m_viewList.count() < 2)
     368    if (m_viewList.size() <= 1)
    341369        return;
    342370
    343371    m_curView--;
    344372    if (m_curView < 0)
    345         m_curView = m_viewList.count() - 1;
     373        m_curView = m_viewList.size() - 1;
    346374
    347375    LoadInBackground();
    348376}
    349377
    350378void ProgLister::nextView(void)
    351379{
    352     if (m_type == plTime)
     380    if (m_type == plTime && !m_viewList.empty() && !m_viewTextList.empty())
    353381    {
    354382        m_searchTime = m_searchTime.addSecs(3600);
    355383        m_curView = 0;
     
    359387
    360388        return;
    361389    }
    362     if (m_viewList.count() < 2)
     390
     391    if (m_viewList.size() <= 1)
    363392        return;
    364393
    365394    m_curView++;
    366     if (m_curView >= (int)m_viewList.count())
     395    if (m_curView >= (int)m_viewList.size())
    367396        m_curView = 0;
    368397
    369398    LoadInBackground();
     
    374403    int oldview = m_viewList.indexOf(oldValue);
    375404    int newview = m_viewList.indexOf(text);
    376405
    377     if (newview < 0 || newview != oldview)
     406    if (newview >= 0 && newview == oldview)
     407        return;
     408
     409    if (oldview >= 0)
    378410    {
    379         QString qphrase;
    380         if (oldview >= 0)
    381         {
    382             qphrase = m_viewList[oldview];
     411        QString qphrase = m_viewList[oldview];
    383412
    384             MSqlQuery query(MSqlQuery::InitCon());
    385             query.prepare("DELETE FROM keyword "
    386                           "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
    387             query.bindValue(":PHRASE", qphrase);
    388             query.bindValue(":TYPE", m_searchType);
    389             if (!query.exec())
    390                 MythDB::DBError("ProgLister::updateKeywordInDB -- delete",
    391                                 query);
    392 
    393             m_viewList.removeAll(qphrase);
    394             m_viewTextList.removeAll(qphrase);
    395         }
    396         if (newview < 0)
     413        MSqlQuery query(MSqlQuery::InitCon());
     414        query.prepare("DELETE FROM keyword "
     415                      "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
     416        query.bindValue(":PHRASE", qphrase);
     417        query.bindValue(":TYPE", m_searchType);
     418        if (!query.exec())
    397419        {
    398             qphrase = text;
     420            MythDB::DBError(
     421                "ProgLister::updateKeywordInDB -- delete", query);
     422        }
     423        m_viewList.removeAll(qphrase);
     424        m_viewTextList.removeAll(qphrase);
     425    }
    399426
    400             MSqlQuery query(MSqlQuery::InitCon());
    401             query.prepare("REPLACE INTO keyword (phrase, searchtype)"
    402                           "VALUES(:PHRASE, :TYPE );");
    403             query.bindValue(":PHRASE", qphrase);
    404             query.bindValue(":TYPE", m_searchType);
    405             if (!query.exec())
    406                 MythDB::DBError("ProgLister::updateKeywordInDB -- replace",
    407                                 query);
     427    if (newview < 0)
     428    {
     429        QString qphrase = text;
    408430
    409             m_viewList.append(qphrase);
    410             m_viewTextList.append(qphrase);
     431        MSqlQuery query(MSqlQuery::InitCon());
     432        query.prepare("REPLACE INTO keyword (phrase, searchtype)"
     433                      "VALUES(:PHRASE, :TYPE );");
     434        query.bindValue(":PHRASE", qphrase);
     435        query.bindValue(":TYPE", m_searchType);
     436        if (!query.exec())
     437        {
     438            MythDB::DBError(
     439                "ProgLister::updateKeywordInDB -- replace", query);
    411440        }
     441        m_viewList.push_back(qphrase);
     442        m_viewTextList.push_back(qphrase);
    412443    }
    413444}
    414445
    415446void ProgLister::chooseView(void)
    416447{
    417     if (m_type == plChannel || m_type == plCategory || m_type == plMovies ||
    418         m_type == plNewListings || m_type == plStoredSearch)
    419     {
    420         if (m_viewList.count() < 1)
    421             return;
     448    MythScreenStack *popupStack =
     449        GetMythMainWindow()->GetStack("popup stack");
     450    MythScreenType *screen = NULL;
     451    bool connect_string = true;
    422452
    423         QString msg;
    424         switch (m_type)
     453    switch (m_type)
     454    {
     455        case plChannel:
     456        case plCategory:
     457        case plMovies:
     458        case plNewListings:
     459        case plStoredSearch:
    425460        {
    426             case plMovies: msg = tr("Select Rating"); break;
    427             case plChannel: msg = tr("Select Channel"); break;
    428             case plCategory: msg = tr("Select Category"); break;
    429             case plNewListings: msg = tr("Select List"); break;
    430             case plStoredSearch: msg = QString("%1\n%2")
     461            if (m_viewList.empty())
     462                return;
     463
     464            QString msg;
     465            switch (m_type)
     466            {
     467                case plMovies: msg = tr("Select Rating"); break;
     468                case plChannel: msg = tr("Select Channel"); break;
     469                case plCategory: msg = tr("Select Category"); break;
     470                case plNewListings: msg = tr("Select List"); break;
     471                case plStoredSearch: msg = QString("%1\n%2")
    431472                    .arg(tr("Select a search stored from"))
    432473                    .arg(tr("Custom Record")); break;
    433             default: msg = tr("Select"); break;
    434         }
     474            }
    435475
    436         MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    437         MythUISearchDialog *searchDlg =
    438                 new MythUISearchDialog(popupStack, msg, m_viewTextList, true, "");
     476            screen = new MythUISearchDialog(
     477                popupStack, msg, m_viewTextList, true, "");
    439478
    440         if (!searchDlg->Create())
    441         {
    442             delete searchDlg;
    443             return;
     479            break;
    444480        }
     481        case plTitleSearch:
     482        case plKeywordSearch:
     483        case plPeopleSearch:
     484            screen = new PhrasePopup(
     485                popupStack, this, m_searchType, m_viewTextList,
     486                (m_curView >= 0) ? m_viewList[m_curView] : QString());
     487            break;
     488        case plPowerSearch:
     489            screen = new PowerSearchPopup(
     490                popupStack, this, m_searchType, m_viewTextList,
     491                (m_curView >= 0) ? m_viewList[m_curView] : QString());
     492            break;
     493        case plTime:
     494            screen = new TimePopup(popupStack, this);
     495            connect_string = false;
     496            break;
     497    }
    445498
    446         connect(searchDlg, SIGNAL(haveResult(QString)), SLOT(setViewFromList(QString)));
    447 
    448         popupStack->AddScreen(searchDlg);
    449 
     499    if (!screen)
    450500        return;
    451     }
    452     else if (m_type == plTitleSearch || m_type == plKeywordSearch ||
    453              m_type == plPeopleSearch)
    454     {
    455         MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    456         QString currentItem;
    457501
    458         if (m_curView >= 0)
    459             currentItem = m_viewList[m_curView];
    460 
    461         PhrasePopup *popup = new PhrasePopup(popupStack, this, m_searchType,
    462                                              m_viewTextList, currentItem);
    463 
    464         if (!popup->Create())
    465         {
    466             delete popup;
    467             return;
    468         }
    469 
    470         connect(popup, SIGNAL(haveResult(QString)), SLOT(setViewFromList(QString)));
    471 
    472         popupStack->AddScreen(popup);
    473 
     502    if (!screen->Create())
     503    {
     504        delete screen;
    474505        return;
    475506    }
    476     else if (m_type == plPowerSearch)
    477     {
    478         MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    479         QString currentItem;
    480507
    481         if (m_curView >= 0)
    482             currentItem = m_viewList[m_curView];
    483 
    484         PowerSearchPopup *popup = new PowerSearchPopup(popupStack, this, m_searchType,
    485                                                        m_viewTextList, currentItem);
    486 
    487         if (!popup->Create())
    488         {
    489             delete popup;
    490             return;
    491         }
    492 
    493         connect(popup, SIGNAL(haveResult(QString)), SLOT(setViewFromList(QString)));
    494 
    495         popupStack->AddScreen(popup);
     508    if (connect_string)
     509    {
     510        connect(screen, SIGNAL(haveResult(     QString)),
     511                this,   SLOT(  setViewFromList(QString)));
    496512    }
    497     else if (m_type == plTime)
     513    else
    498514    {
    499         MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    500         QString currentItem;
    501 
    502         TimePopup *popup = new TimePopup(popupStack, this);
    503 
    504         if (!popup->Create())
    505         {
    506             delete popup;
    507             return;
    508         }
    509 
    510         connect(popup, SIGNAL(haveResult(QDateTime)), SLOT(setViewFromTime(QDateTime)));
    511 
    512         popupStack->AddScreen(popup);
     515        connect(screen, SIGNAL(haveResult(     QDateTime)),
     516                this,   SLOT(  setViewFromTime(QDateTime)));
    513517    }
     518
     519    popupStack->AddScreen(screen);
    514520}
    515521
    516522void ProgLister::setViewFromTime(QDateTime searchTime)
    517523{
     524    if (m_viewList.empty() || m_viewTextList.empty())
     525        return;
     526
    518527    m_searchTime = searchTime;
    519528    m_curView = 0;
    520529    m_viewList[m_curView] = m_searchTime.toString(m_fullDateFormat);
     
    526535void ProgLister::setViewFromList(QString item)
    527536{
    528537    m_curView = m_viewTextList.indexOf(item);
    529     LoadInBackground();
     538    if (m_curView >= 0)
     539        LoadInBackground();
    530540}
    531541
    532 bool ProgLister::powerStringToSQL(const QString &qphrase, QString &output,
    533                                   MSqlBindings &bindings)
     542bool ProgLister::powerStringToSQL(
     543    const QString &qphrase, QString &output, MSqlBindings &bindings)
    534544{
    535     int ret = 0;
    536545    output.clear();
    537     QString curfield;
    538546
    539547    QStringList field = qphrase.split(':');
    540 
    541     if (field.count() != 6)
     548    if (field.size() != 6)
    542549    {
    543         VERBOSE(VB_IMPORTANT, QString("Error. PowerSearch %1 has %2 fields")
    544                 .arg(qphrase).arg(field.count()));
    545         return ret;
    546     }
     550        VERBOSE(VB_IMPORTANT, LOC_ERR +
     551                "Power search should have 6 fields," +
     552                QString("\n\t\t\tnot %1 (%2)")
     553                .arg(field.size()).arg(qphrase));
     554        return false;
     555    };
    547556
    548     if (!field[0].isEmpty())
     557    static const QString bindinglist[6] =
    549558    {
    550         curfield = '%' + field[0] + '%';
    551         output += "program.title LIKE :POWERTITLE ";
    552         bindings[":POWERTITLE"] = curfield;
    553     }
     559        ":POWERTITLE",
     560        ":POWERSUB",
     561        ":POWERDESC",
     562        ":POWERCATTYPE",
     563        ":POWERGENRE",
     564        ":POWERCALLSIGN",
     565    };
    554566
    555     if (!field[1].isEmpty())
     567    static const QString outputlist[6] =
    556568    {
    557         if (!output.isEmpty())
    558             output += "\nAND ";
     569        "program.title LIKE :POWERTITLE ",
     570        "program.subtitle LIKE :POWERSUB ",
     571        "program.description LIKE :POWERDESC ",
     572        "program.category_type = :POWERCATTYPE ",
     573        "programgenres.genre = :POWERGENRE ",
     574        "channel.callsign = :POWERCALLSIGN ",
     575    };
    559576
    560         curfield = '%' + field[1] + '%';
    561         output += "program.subtitle LIKE :POWERSUB ";
    562         bindings[":POWERSUB"] = curfield;
    563     }
    564 
    565     if (!field[2].isEmpty())
     577    for (uint i = 0; i < (uint) field.size(); i++)
    566578    {
    567         if (!output.isEmpty())
    568             output += "\nAND ";
     579        if (field[i].isEmpty())
     580            continue;
    569581
    570         curfield = '%' + field[2] + '%';
    571         output += "program.description LIKE :POWERDESC ";
    572         bindings[":POWERDESC"] = curfield;
    573     }
    574 
    575     if (!field[3].isEmpty())
    576     {
    577582        if (!output.isEmpty())
    578583            output += "\nAND ";
    579584
    580         output += "program.category_type = :POWERCATTYPE ";
    581         bindings[":POWERCATTYPE"] = field[3];
     585        output += outputlist[i];
     586        bindings[bindinglist[i]] =
     587            (!outputlist[i].contains("=")) ?
     588            QString('%') + field[i] + QString('%') : field[i];
    582589    }
    583590
    584     if (!field[4].isEmpty())
    585     {
    586         if (!output.isEmpty())
    587             output += "\nAND ";
    588 
    589         output += "programgenres.genre = :POWERGENRE ";
    590         bindings[":POWERGENRE"] = field[4];
    591         ret = 1;
    592     }
    593 
    594     if (!field[5].isEmpty())
    595     {
    596         if (!output.isEmpty())
    597             output += "\nAND ";
    598 
    599         output += "channel.callsign = :POWERCALLSIGN ";
    600         bindings[":POWERCALLSIGN"] = field[5];
    601     }
    602     return ret;
     591    return output.contains("programgenres");
    603592}
    604593
    605 void ProgLister::quickRecord()
     594const ProgramInfo *ProgLister::GetCurrent(void) const
    606595{
    607     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    608 
    609     if (!pi)
    610         return;
    611 
    612     RecordingInfo ri(*pi);
    613     ri.ToggleRecord();
    614     *pi = ri;
     596    int pos = m_progList->GetCurrentPos();
     597    if (pos >= 0 && pos < (int) m_itemList.size())
     598        return m_itemList[m_progList->GetCurrentPos()];
     599    return NULL;
    615600}
    616601
    617 void ProgLister::select()
     602ProgramInfo *ProgLister::GetCurrent(void)
    618603{
    619     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    620 
    621     if (!pi)
    622         return;
    623 
    624     if (m_type == plPreviouslyRecorded)
    625         oldRecordedActions();
    626     else
    627         EditRecording(pi);
     604    int pos = m_progList->GetCurrentPos();
     605    if (pos >= 0 && pos < (int) m_itemList.size())
     606        return m_itemList[m_progList->GetCurrentPos()];
     607    return NULL;
    628608}
    629609
    630 void ProgLister::edit()
     610void ProgLister::quickRecord(void)
    631611{
    632     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    633 
    634     EditScheduled(pi);
     612    ProgramInfo *pi = GetCurrent();
     613    if (pi)
     614    {
     615        RecordingInfo ri(*pi);
     616        ri.ToggleRecord();
     617        *pi = ri;
     618    }
    635619}
    636620
    637 void ProgLister::customEdit()
     621void ProgLister::select(void)
    638622{
    639     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    640 
    641     EditCustom(pi);
     623    ProgramInfo *pi = GetCurrent();
     624    if (pi)
     625    {
     626        if (m_type == plPreviouslyRecorded)
     627            oldRecordedActions();
     628        else
     629            EditRecording(pi);
     630    }
    642631}
    643632
    644 void ProgLister::deleteItem()
     633void ProgLister::deleteItem(void)
    645634{
    646635    if (m_type == plPreviouslyRecorded)
    647636        deleteOldEpisode();
     
    649638        deleteRule();
    650639}
    651640
    652 void ProgLister::deleteRule()
     641void ProgLister::deleteRule(void)
    653642{
    654     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     643    ProgramInfo *pi = GetCurrent();
    655644
    656645    if (!pi || !pi->GetRecordingRuleID())
    657646        return;
     
    668657
    669658    MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    670659
    671     MythConfirmationDialog *okPopup = new MythConfirmationDialog(popupStack,
    672                                                                 message, true);
     660    MythConfirmationDialog *okPopup = new MythConfirmationDialog(
     661        popupStack, message, true);
    673662
    674663    okPopup->SetReturnEvent(this, "deleterule");
    675664    okPopup->SetData(qVariantFromValue(record));
     
    680669        delete okPopup;
    681670}
    682671
    683 void ProgLister::deleteOldEpisode()
     672void ProgLister::deleteOldEpisode(void)
    684673{
    685     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     674    ProgramInfo *pi = GetCurrent();
    686675
    687676    if (!pi)
    688677        return;
     
    697686    if (!ok)
    698687        return;
    699688
    700     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     689    ProgramInfo *pi = GetCurrent();
    701690
    702691    if (!pi)
    703692        return;
    704693
    705694    MSqlQuery query(MSqlQuery::InitCon());
    706     query.prepare("DELETE FROM oldrecorded "
    707                   "WHERE chanid = :CHANID AND starttime = :STARTTIME ;");
     695    query.prepare(
     696        "DELETE FROM oldrecorded "
     697        "WHERE chanid    = :CHANID AND "
     698        "      starttime = :STARTTIME");
    708699    query.bindValue(":CHANID", pi->GetChanID());
    709700    query.bindValue(":STARTTIME", pi->GetScheduledStartTime(ISODate));
     701
    710702    if (!query.exec())
    711703        MythDB::DBError("ProgLister::doDeleteOldEpisode", query);
    712704
     
    714706    fillItemList(true);
    715707}
    716708
    717 void ProgLister::deleteOldTitle()
     709void ProgLister::deleteOldTitle(void)
    718710{
    719     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     711    ProgramInfo *pi = GetCurrent();
    720712
    721713    if (!pi)
    722714        return;
     
    731723    if (!ok)
    732724        return;
    733725
    734     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     726    ProgramInfo *pi = GetCurrent();
    735727
    736728    if (!pi)
    737729        return;
    738730
    739731    MSqlQuery query(MSqlQuery::InitCon());
    740     query.prepare("DELETE FROM oldrecorded WHERE title = :TITLE ;");
     732    query.prepare("DELETE FROM oldrecorded WHERE title = :TITLE");
    741733    query.bindValue(":TITLE", pi->GetTitle());
    742734    if (!query.exec())
    743735        MythDB::DBError("ProgLister::doDeleteOldTitle -- delete", query);
     
    746738    fillItemList(true);
    747739}
    748740
    749 void ProgLister::oldRecordedActions()
     741void ProgLister::oldRecordedActions(void)
    750742{
    751     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     743    ProgramInfo *pi = GetCurrent();
    752744
    753745    if (!pi)
    754746        return;
     
    759751        message += "\n\n" + pi->GetDescription();
    760752
    761753    message += "\n\n\n" + tr("NOTE: removing items from this list will not "
    762                "delete any recordings.");
     754                             "delete any recordings.");
    763755
    764756    QString title = tr("Previously Recorded");
    765757    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
     
    785777    }
    786778}
    787779
    788 void ProgLister::upcoming()
     780void ProgLister::upcoming(void)
    789781{
    790     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
     782    ProgramInfo *pi = GetCurrent();
    791783
    792784    if (!pi || m_type == plTitle)
    793785        return;
     
    795787    ShowUpcoming(pi);
    796788}
    797789
    798 void ProgLister::details()
    799 {
    800     ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    801 
    802     ShowDetails(pi);
    803 }
    804 
    805790void ProgLister::fillViewList(const QString &view)
    806791{
    807792    m_viewList.clear();
     
    809794
    810795    if (m_type == plChannel) // list by channel
    811796    {
    812         DBChanList channels = ChannelUtil::GetChannels(0, true,
    813                                                       "channum, chanid");
     797        DBChanList channels = ChannelUtil::GetChannels(
     798            0, true, "channum, chanid");
    814799        ChannelUtil::SortChannels(channels, m_channelOrdering, true);
    815800
    816801        for (uint i = 0; i < channels.size(); ++i)
     
    821806                .replace("<sign>", channels[i].callsign)
    822807                .replace("<name>", channels[i].name);
    823808
    824             m_viewList << QString::number(channels[i].chanid);
    825             m_viewTextList << chantext;
     809            m_viewList.push_back(QString::number(channels[i].chanid));
     810            m_viewTextList.push_back(chantext);
    826811        }
    827812
    828813        if (!view.isEmpty())
     
    844829                      "GROUP BY g1.genre, g2.genre;");
    845830        query.bindValue(":PGILSTART", startstr);
    846831
    847         if (query.exec() && query.size())
     832        m_useGenres = false;
     833
     834        if (query.exec())
    848835        {
    849             QString lastGenre1, genre1;
     836            QString lastGenre1;
    850837
    851838            while (query.next())
    852839            {
    853                 genre1 = query.value(0).toString();
     840                m_useGenres = true;
     841
     842                QString genre1 = query.value(0).toString();
    854843                if (genre1.isEmpty())
    855844                    continue;
    856845
    857846                if (genre1 != lastGenre1)
    858847                {
    859                     m_viewList << genre1;
    860                     m_viewTextList << genre1;
     848                    m_viewList.push_back(genre1);
     849                    m_viewTextList.push_back(genre1);
    861850                    lastGenre1 = genre1;
    862851                }
    863852
     
    865854                if (genre2.isEmpty() || genre2 == genre1)
    866855                    continue;
    867856
    868                 m_viewList << genre1 + ":/:" + genre2;
    869                 m_viewTextList << "    " + genre1 + " / " + genre2;
     857                m_viewList.push_back(genre1 + ":/:" + genre2);
     858                m_viewTextList.push_back("    " + genre1 + " / " + genre2);
    870859            }
    871 
    872             m_useGenres = true;
    873860        }
    874         else
     861
     862        if (!m_useGenres)
    875863        {
    876864            query.prepare("SELECT category "
    877865                          "FROM program "
    878866                          "WHERE program.endtime > :PGILSTART "
    879                           "GROUP BY category;");
     867                          "GROUP BY category");
    880868            query.bindValue(":PGILSTART", startstr);
    881869
    882870            if (query.exec())
     
    887875                    if (category.isEmpty())
    888876                        continue;
    889877                    category = query.value(0).toString();
    890                     m_viewList << category;
    891                     m_viewTextList << category;
     878                    m_viewList.push_back(category);
     879                    m_viewTextList.push_back(category);
    892880                }
    893881            }
    894 
    895             m_useGenres = false;
    896882        }
    897883
    898884        if (!view.isEmpty())
     
    914900                if (phrase.isEmpty())
    915901                    continue;
    916902                phrase = query.value(0).toString();
    917                 m_viewList << phrase;
    918                 m_viewTextList << phrase;
     903                m_viewList.push_back(phrase);
     904                m_viewTextList.push_back(phrase);
    919905            }
    920906        }
     907
    921908        if (!view.isEmpty())
    922909        {
    923910            m_curView = m_viewList.indexOf(view);
     
    935922                    MythDB::DBError("ProgLister::fillViewList -- "
    936923                                    "replace keyword", query);
    937924
    938                 m_viewList << qphrase;
    939                 m_viewTextList << qphrase;
     925                m_viewList.push_back(qphrase);
     926                m_viewTextList.push_back(qphrase);
    940927
    941                 m_curView = m_viewList.count() - 1;
     928                m_curView = m_viewList.size() - 1;
    942929            }
    943930        }
    944931        else
     932        {
    945933            m_curView = -1;
     934        }
    946935    }
    947936    else if (m_type == plTitle)
    948937    {
    949938        if (!view.isEmpty())
    950939        {
    951             m_viewList << view;
    952             m_viewTextList << view;
     940            m_viewList.push_back(view);
     941            m_viewTextList.push_back(view);
    953942            m_curView = 0;
    954943        }
    955944        else
     945        {
    956946            m_curView = -1;
     947        }
    957948    }
    958949    else if (m_type == plNewListings)
    959950    {
    960         m_viewList << "all";
    961         m_viewTextList << tr("All");
     951        m_viewList.push_back("all");
     952        m_viewTextList.push_back(tr("All"));
    962953
    963         m_viewList << "premieres";
    964         m_viewTextList << tr("Premieres");
     954        m_viewList.push_back("premieres");
     955        m_viewTextList.push_back(tr("Premieres"));
    965956
    966         m_viewList << "movies";
    967         m_viewTextList << tr("Movies");
     957        m_viewList.push_back("movies");
     958        m_viewTextList.push_back(tr("Movies"));
    968959
    969         m_viewList << "series";
    970         m_viewTextList << tr("Series");
     960        m_viewList.push_back("series");
     961        m_viewTextList.push_back(tr("Series"));
    971962
    972         m_viewList << "specials";
    973         m_viewTextList << tr("Specials");
     963        m_viewList.push_back("specials");
     964        m_viewTextList.push_back(tr("Specials"));
    974965
    975966        if (!view.isEmpty())
    976967            m_curView = m_viewList.indexOf(view);
    977968    }
    978969    else if (m_type == plMovies)
    979970    {
    980         m_viewList << ">= 0.0";
    981         m_viewTextList << tr("All");
    982         m_viewList << "= 0.0";
    983         m_viewTextList << tr("Unrated");
    984         m_viewList << ">= 1.0";
    985         m_viewTextList << "****";
    986         m_viewList << ">= 0.875 AND program.stars < 1.0";
    987         m_viewTextList << "***/";
    988         m_viewList << ">= 0.75 AND program.stars < 0.875";
    989         m_viewTextList << "***";
    990         m_viewList << ">= 0.625 AND program.stars < 0.75";
    991         m_viewTextList << "**/";
    992         m_viewList << ">= 0.5 AND program.stars < 0.625";
    993         m_viewTextList << "**";
    994         m_viewList << ">= 0.375 AND program.stars < 0.5";
    995         m_viewTextList << "*/";
    996         m_viewList << ">= 0.25 AND program.stars < 0.375";
    997         m_viewTextList << "*";
    998         m_viewList << ">= 0.125 AND program.stars < 0.25";
    999         m_viewTextList << "/";
    1000         m_viewList << ">= 0.875";
    1001         m_viewTextList << tr("At least ***/");
    1002         m_viewList << ">= 0.75";
    1003         m_viewTextList << tr("At least ***");
    1004         m_viewList << ">= 0.625";
    1005         m_viewTextList << tr("At least **/");
    1006         m_viewList << ">= 0.5";
    1007         m_viewTextList << tr("At least **");
    1008         m_viewList << ">= 0.375";
    1009         m_viewTextList << tr("At least */");
    1010         m_viewList << ">= 0.25";
    1011         m_viewTextList << tr("At least *");
    1012         m_viewList << ">= 0.125";
    1013         m_viewTextList << tr("At least /");
     971        m_viewList.push_back(">= 0.0");
     972        m_viewTextList.push_back(tr("All"));
     973        m_viewList.push_back("= 0.0");
     974        m_viewTextList.push_back(tr("Unrated"));
     975        m_viewList.push_back(">= 1.0");
     976        m_viewTextList.push_back("****");
     977        m_viewList.push_back(">= 0.875");
     978        m_viewTextList.push_back("***/");
     979        m_viewList.push_back(">= 0.75 AND program.stars < 0.875");
     980        m_viewTextList.push_back("***");
     981        m_viewList.push_back(">= 0.625 AND program.stars < 0.75");
     982        m_viewTextList.push_back("**/");
     983        m_viewList.push_back(">= 0.5 AND program.stars < 0.625");
     984        m_viewTextList.push_back("**");
     985        m_viewList.push_back(">= 0.375 AND program.stars < 0.5");
     986        m_viewTextList.push_back("*/");
     987        m_viewList.push_back(">= 0.25 AND program.stars < 0.375");
     988        m_viewTextList.push_back("*");
     989        m_viewList.push_back(">= 0.125 AND program.stars < 0.25");
     990        m_viewTextList.push_back("/");
     991        m_viewList.push_back(">= 0.875");
     992        m_viewTextList.push_back(tr("At least ***/"));
     993        m_viewList.push_back(">= 0.75");
     994        m_viewTextList.push_back(tr("At least ***"));
     995        m_viewList.push_back(">= 0.625");
     996        m_viewTextList.push_back(tr("At least **/"));
     997        m_viewList.push_back(">= 0.5");
     998        m_viewTextList.push_back(tr("At least **"));
     999        m_viewList.push_back(">= 0.375");
     1000        m_viewTextList.push_back(tr("At least */"));
     1001        m_viewList.push_back(">= 0.25");
     1002        m_viewTextList.push_back(tr("At least *"));
     1003        m_viewList.push_back(">= 0.125");
     1004        m_viewTextList.push_back(tr("At least /"));
    10141005
    10151006        if (!view.isEmpty())
    10161007            m_curView = m_viewList.indexOf(view);
     
    10181009    else if (m_type == plTime)
    10191010    {
    10201011        m_curView = 0;
    1021         m_viewList << m_searchTime.toString(m_fullDateFormat);
    1022         m_viewTextList << m_viewList[m_curView];
     1012        m_viewList.push_back(m_searchTime.toString(m_fullDateFormat));
     1013        m_viewTextList.push_back(m_viewList[m_curView]);
    10231014    }
    10241015    else if (m_type == plSQLSearch)
    10251016    {
    10261017        m_curView = 0;
    1027         m_viewList << view;
    1028         m_viewTextList << tr("Power Recording Rule");
     1018        m_viewList.push_back(view);
     1019        m_viewTextList.push_back(tr("Power Recording Rule"));
    10291020    }
    10301021    else if (m_type == plRecordid)
    10311022    {
     
    10381029
    10391030        if (query.exec() && query.next())
    10401031        {
    1041                 QString title = query.value(0).toString();
    1042                 title = query.value(0).toString();
    1043                 m_viewList << view;
    1044                 m_viewTextList << title;
     1032            QString title = query.value(0).toString();
     1033            title = query.value(0).toString();
     1034            m_viewList.push_back(view);
     1035            m_viewTextList.push_back(title);
    10451036        }
    10461037    }
    10471038    else if (m_type == plStoredSearch) // stored searches
     
    10581049                if (rulename.isEmpty() || rulename.trimmed().isEmpty())
    10591050                    continue;
    10601051                rulename = query.value(0).toString();
    1061                 m_viewList << rulename;
    1062                 m_viewTextList << rulename;
     1052                m_viewList.push_back(rulename);
     1053                m_viewTextList.push_back(rulename);
    10631054            }
    10641055        }
    10651056        if (!view.isEmpty())
     
    10671058    }
    10681059    else if (m_type == plPreviouslyRecorded) // previously recorded
    10691060    {
    1070         m_viewList << "sort by time";
    1071         m_viewTextList << tr("Time");
     1061        m_viewList.push_back("sort by time");
     1062        m_viewTextList.push_back(tr("Time"));
    10721063
    1073         m_viewList << "reverse time";
    1074         m_viewTextList << tr("Reverse Time");
     1064        m_viewList.push_back("reverse time");
     1065        m_viewTextList.push_back(tr("Reverse Time"));
    10751066
    1076         m_viewList << "sort by title";
    1077         m_viewTextList << tr("Title");
     1067        m_viewList.push_back("sort by title");
     1068        m_viewTextList.push_back(tr("Title"));
    10781069
    1079         m_viewList << "reverse title";
    1080         m_viewTextList << tr("Reverse Title");
     1070        m_viewList.push_back("reverse title");
     1071        m_viewTextList.push_back(tr("Reverse Title"));
    10811072
    10821073        if (!view.isEmpty())
    10831074            m_curView = m_viewList.indexOf(view);
    10841075    }
    10851076
    1086     if (m_curView >= (int)m_viewList.count())
    1087         m_curView = m_viewList.count() - 1;
     1077    if (m_curView >= (int)m_viewList.size())
     1078        m_curView = m_viewList.size() - 1;
    10881079}
    10891080
    1090 class plCompare
    1091 {
    1092     public:
    1093         plCompare(void) {};
    1094         virtual bool operator()(const ProgramInfo *a, const ProgramInfo *b)
    1095             = 0;
    1096 };
     1081typedef binary_function<const ProgramInfo*, const ProgramInfo*, bool> plCompare;
    10971082
    1098 class plTitleSort
    1099     : public plCompare
     1083class plTitleSort : public plCompare
    11001084{
    1101     public:
    1102         plTitleSort(void) : plCompare() {;}
     1085  public:
     1086    bool operator()(const ProgramInfo *a, const ProgramInfo *b)
     1087    {
     1088        if (a->sortTitle != b->sortTitle)
     1089            return (a->sortTitle < b->sortTitle);
    11031090
    1104         bool operator()(const ProgramInfo *a, const ProgramInfo *b)
    1105         {
    1106             if (a->sortTitle != b->sortTitle)
    1107                     return (a->sortTitle < b->sortTitle);
     1091        if (a->GetRecordingStatus() == b->GetRecordingStatus())
     1092            return a->GetScheduledStartTime() < b->GetScheduledStartTime();
    11081093
    1109             if (a->GetRecordingStatus() == b->GetRecordingStatus())
    1110                 return a->GetScheduledStartTime() < b->GetScheduledStartTime();
     1094        if (a->GetRecordingStatus() == rsRecording)
     1095            return true;
     1096        if (b->GetRecordingStatus() == rsRecording)
     1097            return false;
    11111098
    1112             if (a->GetRecordingStatus() == rsRecording) return true;
    1113             if (b->GetRecordingStatus() == rsRecording) return false;
     1099        if (a->GetRecordingStatus() == rsWillRecord)
     1100            return true;
     1101        if (b->GetRecordingStatus() == rsWillRecord)
     1102            return false;
    11141103
    1115             if (a->GetRecordingStatus() == rsWillRecord) return true;
    1116             if (b->GetRecordingStatus() == rsWillRecord) return false;
    1117 
    1118             return a->GetScheduledStartTime() < b->GetScheduledStartTime();
    1119         }
     1104        return a->GetScheduledStartTime() < b->GetScheduledStartTime();
     1105    }
    11201106};
    11211107
    1122 class plPrevTitleSort
    1123     : public plCompare
     1108class plPrevTitleSort : public plCompare
    11241109{
    1125     public:
    1126         plPrevTitleSort(void) : plCompare() {;}
     1110  public:
     1111    plPrevTitleSort(void) : plCompare() {;}
    11271112
    1128         bool operator()(const ProgramInfo *a, const ProgramInfo *b)
    1129         {
    1130             if (a->sortTitle != b->sortTitle)
    1131                     return (a->sortTitle < b->sortTitle);
     1113    bool operator()(const ProgramInfo *a, const ProgramInfo *b)
     1114    {
     1115        if (a->sortTitle != b->sortTitle)
     1116            return (a->sortTitle < b->sortTitle);
    11321117
    1133             if (a->GetProgramID() != b->GetProgramID())
    1134                 return a->GetProgramID() < b->GetProgramID();
     1118        if (a->GetProgramID() != b->GetProgramID())
     1119            return a->GetProgramID() < b->GetProgramID();
    11351120
    1136             return a->GetScheduledStartTime() < b->GetScheduledStartTime();
    1137         }
     1121        return a->GetScheduledStartTime() < b->GetScheduledStartTime();
     1122    }
    11381123};
    11391124
    1140 class plTimeSort
    1141     : public plCompare
     1125class plTimeSort : public plCompare
    11421126{
    1143     public:
    1144         plTimeSort(void) : plCompare() {;}
     1127  public:
     1128    plTimeSort(void) : plCompare() {;}
    11451129
    1146         bool operator()(const ProgramInfo *a, const ProgramInfo *b)
    1147         {
    1148             if (a->GetScheduledStartTime() == b->GetScheduledStartTime())
    1149                 return (a->GetChanID() < b->GetChanID());
     1130    bool operator()(const ProgramInfo *a, const ProgramInfo *b)
     1131    {
     1132        if (a->GetScheduledStartTime() == b->GetScheduledStartTime())
     1133            return (a->GetChanID() < b->GetChanID());
    11501134
    1151             return (a->GetScheduledStartTime() < b->GetScheduledStartTime());
    1152         }
     1135        return (a->GetScheduledStartTime() < b->GetScheduledStartTime());
     1136    }
    11531137};
    11541138
    11551139void ProgLister::fillItemList(bool restorePosition, bool updateDisp)
     
    11731157    }
    11741158
    11751159    if (m_curView < 0)
    1176          return;
     1160        return;
    11771161
    11781162    bool oneChanid = false;
    11791163    QString where;
     
    11881172    if (m_type == plTitle) // per title listings
    11891173    {
    11901174        where = "WHERE channel.visible = 1 "
    1191                 "  AND program.endtime > :PGILSTART "
    1192                 "  AND program.title = :PGILPHRASE0 ";
     1175            "  AND program.endtime > :PGILSTART "
     1176            "  AND program.title = :PGILPHRASE0 ";
    11931177        bindings[":PGILPHRASE0"] = qphrase;
    11941178    }
    11951179    else if (m_type == plNewListings) // what's new list
    11961180    {
    11971181        where = "LEFT JOIN oldprogram ON "
    1198                 "  oldprogram.oldtitle = program.title "
    1199                 "WHERE channel.visible = 1 "
    1200                 "  AND program.endtime > :PGILSTART "
    1201                 "  AND oldprogram.oldtitle IS NULL "
    1202                 "  AND program.manualid = 0 ";
     1182            "  oldprogram.oldtitle = program.title "
     1183            "WHERE channel.visible = 1 "
     1184            "  AND program.endtime > :PGILSTART "
     1185            "  AND oldprogram.oldtitle IS NULL "
     1186            "  AND program.manualid = 0 ";
    12031187
    12041188        if (qphrase == "premieres")
    12051189        {
     
    12331217    else if (m_type == plTitleSearch) // keyword search
    12341218    {
    12351219        where = "WHERE channel.visible = 1 "
    1236                 "  AND program.endtime > :PGILSTART "
    1237                 "  AND program.title LIKE :PGILLIKEPHRASE0 ";
     1220            "  AND program.endtime > :PGILSTART "
     1221            "  AND program.title LIKE :PGILLIKEPHRASE0 ";
    12381222        bindings[":PGILLIKEPHRASE0"] = QString("%") + qphrase + '%';
    12391223    }
    12401224    else if (m_type == plKeywordSearch) // keyword search
    12411225    {
    12421226        where = "WHERE channel.visible = 1 "
    1243                 "  AND program.endtime > :PGILSTART "
    1244                 "  AND (program.title LIKE :PGILLIKEPHRASE1 "
    1245                 "    OR program.subtitle LIKE :PGILLIKEPHRASE2 "
    1246                 "    OR program.description LIKE :PGILLIKEPHRASE3 ) ";
     1227            "  AND program.endtime > :PGILSTART "
     1228            "  AND (program.title LIKE :PGILLIKEPHRASE1 "
     1229            "    OR program.subtitle LIKE :PGILLIKEPHRASE2 "
     1230            "    OR program.description LIKE :PGILLIKEPHRASE3 ) ";
    12471231        bindings[":PGILLIKEPHRASE1"] = QString("%") + qphrase + '%';
    12481232        bindings[":PGILLIKEPHRASE2"] = QString("%") + qphrase + '%';
    12491233        bindings[":PGILLIKEPHRASE3"] = QString("%") + qphrase + '%';
     
    12511235    else if (m_type == plPeopleSearch) // people search
    12521236    {
    12531237        where = ", people, credits WHERE channel.visible = 1 "
    1254                 "  AND program.endtime > :PGILSTART "
    1255                 "  AND people.name LIKE :PGILPHRASE1 "
    1256                 "  AND credits.person = people.person "
    1257                 "  AND program.chanid = credits.chanid "
    1258                 "  AND program.starttime = credits.starttime";
     1238            "  AND program.endtime > :PGILSTART "
     1239            "  AND people.name LIKE :PGILPHRASE1 "
     1240            "  AND credits.person = people.person "
     1241            "  AND program.chanid = credits.chanid "
     1242            "  AND program.starttime = credits.starttime";
    12591243        bindings[":PGILPHRASE1"] = qphrase;
    12601244    }
    12611245    else if (m_type == plPowerSearch) // complex search
     
    12691253        {
    12701254            if (genreflag)
    12711255                where = QString("LEFT JOIN programgenres ON "
    1272                         "program.chanid = programgenres.chanid AND "
    1273                         "program.starttime = programgenres.starttime ");
     1256                                "program.chanid = programgenres.chanid AND "
     1257                                "program.starttime = programgenres.starttime ");
    12741258
    12751259            where += QString("WHERE channel.visible = 1 "
    1276                     "  AND program.endtime > :PGILSTART "
    1277                     "  AND ( ") + powerWhere + " ) ";
     1260                             "  AND program.endtime > :PGILSTART "
     1261                             "  AND ( ") + powerWhere + " ) ";
    12781262            MSqlAddMoreBindings(bindings, powerBindings);
    12791263        }
    12801264    }
     
    12911275    {
    12921276        oneChanid = true;
    12931277        where = "WHERE channel.visible = 1 "
    1294                 "  AND program.endtime > :PGILSTART "
    1295                 "  AND channel.chanid = :PGILPHRASE2 ";
     1278            "  AND program.endtime > :PGILSTART "
     1279            "  AND channel.chanid = :PGILPHRASE2 ";
    12961280        bindings[":PGILPHRASE2"] = qphrase;
    12971281    }
    12981282    else if (m_type == plCategory) // list by category
     
    13001284        if (!m_useGenres)
    13011285        {
    13021286            where = "WHERE channel.visible = 1 "
    1303                     "  AND program.endtime > :PGILSTART "
    1304                     "  AND program.category = :PGILPHRASE3 ";
     1287                "  AND program.endtime > :PGILSTART "
     1288                "  AND program.category = :PGILPHRASE3 ";
    13051289            bindings[":PGILPHRASE3"] = qphrase;
    13061290        }
    13071291        else if (m_viewList[m_curView].indexOf(":/:") < 0)
    13081292        {
    13091293            where = "JOIN programgenres g ON "
    1310                     "  program.chanid = g.chanid AND "
    1311                     "  program.starttime = g.starttime AND "
    1312                     "  genre = :PGILPHRASE4 "
    1313                     "WHERE channel.visible = 1 "
    1314                     "  AND program.endtime > :PGILSTART ";
     1294                "  program.chanid = g.chanid AND "
     1295                "  program.starttime = g.starttime AND "
     1296                "  genre = :PGILPHRASE4 "
     1297                "WHERE channel.visible = 1 "
     1298                "  AND program.endtime > :PGILSTART ";
    13151299            bindings[":PGILPHRASE4"] = qphrase;
    13161300        }
    13171301        else
    13181302        {
    13191303            where = "JOIN programgenres g1 ON "
    1320                     "  program.chanid = g1.chanid AND "
    1321                     "  program.starttime = g1.starttime AND "
    1322                     "  g1.genre = :GENRE1 "
    1323                     "JOIN programgenres g2 ON "
    1324                     "  program.chanid = g2.chanid AND "
    1325                     "  program.starttime = g2.starttime AND "
    1326                     "  g2.genre = :GENRE2 "
    1327                     "WHERE channel.visible = 1 "
    1328                     "  AND program.endtime > :PGILSTART ";
     1304                "  program.chanid = g1.chanid AND "
     1305                "  program.starttime = g1.starttime AND "
     1306                "  g1.genre = :GENRE1 "
     1307                "JOIN programgenres g2 ON "
     1308                "  program.chanid = g2.chanid AND "
     1309                "  program.starttime = g2.starttime AND "
     1310                "  g2.genre = :GENRE2 "
     1311                "WHERE channel.visible = 1 "
     1312                "  AND program.endtime > :PGILSTART ";
    13291313            bindings[":GENRE1"] = m_viewList[m_curView].section(":/:", 0, 0);
    13301314            bindings[":GENRE2"] = m_viewList[m_curView].section(":/:", 1, 1);
    13311315        }
     
    13331317    else if (m_type == plMovies) // list movies
    13341318    {
    13351319        where = "WHERE channel.visible = 1 "
    1336                 "  AND program.endtime > :PGILSTART "
    1337                 "  AND program.category_type = 'movie' "
    1338                 "  AND program.stars " + qphrase + ' ';
     1320            "  AND program.endtime > :PGILSTART "
     1321            "  AND program.category_type = 'movie' "
     1322            "  AND program.stars " + qphrase + ' ';
    13391323    }
    13401324    else if (m_type == plTime) // list by time
    13411325    {
    1342         bindings[":PGILSEARCHTIME1"] = m_searchTime.toString("yyyy-MM-dd hh:00:00");
     1326        bindings[":PGILSEARCHTIME1"] =
     1327            m_searchTime.toString("yyyy-MM-dd hh:00:00");
    13431328        where = "WHERE channel.visible = 1 "
    1344                 "  AND program.starttime >= :PGILSEARCHTIME1 ";
     1329            "  AND program.starttime >= :PGILSEARCHTIME1 ";
    13451330        if (m_titleSort)
    13461331        {
    13471332            where += "  AND program.starttime < DATE_ADD(:PGILSEARCHTIME2, "
    1348                      "INTERVAL '1' HOUR) ";
     1333                "INTERVAL '1' HOUR) ";
    13491334            bindings[":PGILSEARCHTIME2"] = bindings[":PGILSEARCHTIME1"];
    13501335        }
    13511336    }
    13521337    else if (m_type == plRecordid) // list by recordid
    13531338    {
    13541339        where = "JOIN recordmatch ON "
    1355                 " (program.starttime = recordmatch.starttime "
    1356                 "  AND program.chanid = recordmatch.chanid) "
    1357                 "WHERE channel.visible = 1 "
    1358                 "  AND program.endtime > :PGILSTART "
    1359                 "  AND recordmatch.recordid = :PGILPHRASE5 ";
     1340            " (program.starttime = recordmatch.starttime "
     1341            "  AND program.chanid = recordmatch.chanid) "
     1342            "WHERE channel.visible = 1 "
     1343            "  AND program.endtime > :PGILSTART "
     1344            "  AND recordmatch.recordid = :PGILPHRASE5 ";
    13601345        bindings[":PGILPHRASE5"] = qphrase;
    13611346    }
    13621347    else if (m_type == plStoredSearch) // stored search
     
    13801365    }
    13811366    else if (m_type == plPreviouslyRecorded)
    13821367    {
    1383         if (m_recid > 0 && !m_title.isEmpty())
     1368        if (m_recid && !m_title.isEmpty())
    13841369        {
    1385             where = QString("WHERE recordid = %1 OR title = :MTITLE ").arg(m_recid);
     1370            where = QString("WHERE recordid = %1 OR title = :MTITLE ")
     1371                .arg(m_recid);
    13861372            bindings[":MTITLE"] = m_title;
    13871373        }
    13881374        else if (!m_title.isEmpty())
     
    13901376            where = QString("WHERE title = :MTITLE ");
    13911377            bindings[":MTITLE"] = m_title;
    13921378        }
    1393         else if (m_recid > 0)
     1379        else if (m_recid)
    13941380        {
    13951381            where = QString("WHERE recordid = %1 ").arg(m_recid);
    13961382        }
    13971383    }
    13981384
     1385    m_progList->Reset();
     1386    m_itemList.clear();
     1387
    13991388    if (m_type == plPreviouslyRecorded)
    14001389    {
    14011390        LoadFromOldRecorded(m_itemList, where, bindings);
     
    14061395        LoadFromProgram(m_itemList, where, bindings, m_schedList, oneChanid);
    14071396    }
    14081397
    1409     ProgramInfo *s;
    1410     vector<ProgramInfo *> sortedList;
    1411     const QRegExp prefixes("^(The |A |An )");
    1412 
    1413     while (!m_itemList.empty())
     1398    const QRegExp prefixes(
     1399        tr("^(The |A |An )",
     1400           "Regular Expression for what to ignore when sorting"));
     1401    for (uint i = 0; i < m_itemList.size(); i++)
    14141402    {
    1415         s = m_itemList.take(0);
    1416         if (m_type == plTitle)
    1417             s->sortTitle = s->GetSubtitle();
    1418         else
    1419             s->sortTitle = s->GetTitle();
    1420 
     1403        ProgramInfo *s = m_itemList[i];
     1404        s->sortTitle = (m_type == plTitle) ? s->GetSubtitle() : s->GetTitle();
    14211405        s->sortTitle.remove(prefixes);
    1422         sortedList.push_back(s);
    14231406    }
    14241407
    14251408    if (m_type == plNewListings || m_titleSort)
    14261409    {
    1427         if (m_type == plPreviouslyRecorded)
    1428             sort(sortedList.begin(), sortedList.end(), plPrevTitleSort());
    1429         else
     1410        SortList(kTitleSort, m_reverseSort);
     1411        if (m_type != plPreviouslyRecorded)
    14301412        {
    14311413            // Prune to one per title
    1432             sort(sortedList.begin(), sortedList.end(), plTitleSort());
    1433 
    14341414            QString curtitle;
    1435             vector<ProgramInfo *>::iterator i = sortedList.begin();
    1436             while (i != sortedList.end())
     1415            ProgramList::iterator it = m_itemList.begin();
     1416            while (it != m_itemList.end())
    14371417            {
    1438                 ProgramInfo *p = *i;
    1439                 if (p->sortTitle != curtitle)
     1418                if ((*it)->sortTitle != curtitle)
    14401419                {
    1441                     curtitle = p->sortTitle;
    1442                     i++;
     1420                    curtitle = (*it)->sortTitle;
     1421                    it++;
    14431422                }
    14441423                else
    14451424                {
    1446                     delete p;
    1447                     i = sortedList.erase(i);
     1425                    it = m_itemList.erase(it);
    14481426                }
    14491427            }
    14501428        }
    14511429    }
    14521430
    14531431    if (!m_titleSort)
    1454         sort(sortedList.begin(), sortedList.end(), plTimeSort());
     1432        SortList(GetSortBy(), m_reverseSort);
    14551433
    1456     if (m_reverseSort)
     1434    if (updateDisp)
     1435        updateDisplay(restorePosition);
     1436}
     1437
     1438ProgLister::SortBy ProgLister::GetSortBy(void) const
     1439{
     1440    if (!m_titleSort)
     1441        return kTimeSort;
     1442    if (m_type == plPreviouslyRecorded)
     1443        return kPrevTitleSort;
     1444    return kTitleSort;
     1445}
     1446
     1447void ProgLister::SortList(SortBy sortby, bool reverseSort)
     1448{
     1449    if (reverseSort)
    14571450    {
    1458         vector<ProgramInfo *>::reverse_iterator r = sortedList.rbegin();
    1459         for (; r != sortedList.rend(); r++)
    1460             m_itemList.push_back(*r);
     1451        if (kTimeSort == sortby)
     1452            stable_sort(m_itemList.rbegin(), m_itemList.rend(), plTimeSort());
     1453        else if (kPrevTitleSort == sortby)
     1454            stable_sort(m_itemList.rbegin(), m_itemList.rend(),
     1455                        plPrevTitleSort());
     1456        else
     1457            stable_sort(m_itemList.rbegin(), m_itemList.rend(), plTitleSort());
    14611458    }
    14621459    else
    14631460    {
    1464         vector<ProgramInfo *>::iterator i = sortedList.begin();
    1465         for (; i != sortedList.end(); ++i)
    1466             m_itemList.push_back(*i);
     1461        if (kTimeSort == sortby)
     1462            stable_sort(m_itemList.begin(), m_itemList.end(), plTimeSort());
     1463        else if (kPrevTitleSort == sortby)
     1464            stable_sort(m_itemList.begin(), m_itemList.end(),
     1465                        plPrevTitleSort());
     1466        else
     1467            stable_sort(m_itemList.begin(), m_itemList.end(), plTitleSort());
    14671468    }
    1468 
    1469     if (updateDisp)
    1470         updateDisplay(restorePosition);
    14711469}
    14721470
    14731471void ProgLister::updateDisplay(bool restorePosition)
    14741472{
     1473    m_progList->Reset();
     1474
    14751475    if (m_messageText)
    14761476        m_messageText->SetVisible(m_itemList.empty());
    14771477
     
    14841484    ProgramInfo *selected = NULL;
    14851485    if (currentItem)
    14861486    {
    1487         ProgramInfo* variantProgramInfo = qVariantValue<ProgramInfo*>(currentItem->GetData());
     1487        ProgramInfo *variantProgramInfo =
     1488            qVariantValue<ProgramInfo*>(currentItem->GetData());
    14881489        if (variantProgramInfo)
    14891490            selected = new ProgramInfo(*variantProgramInfo);
    14901491    }
     
    15021503    // Restore position after a list update
    15031504    if (restorePosition && selected)
    15041505    {
    1505         plCompare *comp;
    1506         if (!m_titleSort)
    1507             comp = new plTimeSort();
    1508         else if (m_type == plPreviouslyRecorded)
    1509             comp = new plPrevTitleSort();
    1510         else
    1511             comp = new plTitleSort();
    1512 
    1513         int i;
    1514         for (i = m_itemList.size() - 2; i >= 0; i--)
    1515         {
    1516             bool dobreak;
    1517             if (m_reverseSort)
    1518                 dobreak = comp->operator()(selected, m_itemList[i]);
    1519             else
    1520                 dobreak = comp->operator()(m_itemList[i], selected);
    1521             if (dobreak)
    1522                 break;
    1523         }
    1524 
    1525         delete comp;
    1526 
    1527         m_progList->SetItemCurrent(i + 1, i + 1 - selectedOffset);
     1506        SortList(GetSortBy(), m_reverseSort);
     1507        // TODO FIXME
     1508        //m_progList->SetItemCurrent(i + 1, i + 1 - selectedOffset);
    15281509    }
    15291510
    15301511    delete selected;
     
    15321513
    15331514void ProgLister::updateButtonList(void)
    15341515{
    1535     m_progList->Reset();
    1536 
    15371516    ProgramList::const_iterator it = m_itemList.begin();
    15381517    for (; it != m_itemList.end(); ++it)
    15391518    {
     
    15661545
    15671546    if (m_positionText)
    15681547    {
    1569         m_positionText->SetText(tr("%1 of %2")
     1548        m_positionText->SetText(
     1549            tr("%1 of %2", "Current position in list where %1 is the "
     1550               "position, %2 is the total count")
    15701551            .arg(m_progList->GetCurrentPos())
    15711552            .arg(m_progList->GetCount()));
    15721553    }
     
    15831564        InfoMap infoMap;
    15841565        pginfo->ToMap(infoMap);
    15851566        SetTextFromMap(infoMap);
     1567
    15861568        if (m_positionText)
    15871569        {
    1588             m_positionText->SetText(tr("%1 of %2")
    1589                    .arg(m_progList->GetCurrentPos())
    1590                    .arg(m_progList->GetCount()));
     1570            m_positionText->SetText(
     1571                tr("%1 of %2", "Current position in list where %1 is the "
     1572                   "position, %2 is the total count")
     1573                .arg(m_progList->GetCurrentPos())
     1574                .arg(m_progList->GetCount()));
    15911575        }
     1576
    15921577        MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
    1593                                                     (GetChild("ratingstate"));
     1578            (GetChild("ratingstate"));
     1579
    15941580        if (ratingState)
    15951581        {
    15961582            QString rating = QString::number(pginfo->GetStars(10));
     
    16111597        QString resulttext = dce->GetResultText();
    16121598        int     buttonnum  = dce->GetResult();
    16131599
    1614         if (resultid == "menu")
     1600        if (resultid == "sortmenu")
    16151601        {
    1616             if (resulttext == tr("Choose Search Phrase..."))
     1602            switch (buttonnum)
    16171603            {
    1618                 chooseView();
     1604                case 0:
     1605                    m_reverseSort = !m_reverseSort;
     1606                    needUpdate    = true;
     1607                    break;
     1608                case 1:
     1609                    m_titleSort   = true;
     1610                    m_reverseSort = false;
     1611                    needUpdate    = true;
     1612                    break;
     1613                case 2:
     1614                    m_titleSort   = false;
     1615                    m_reverseSort = (m_type == plPreviouslyRecorded);
     1616                    needUpdate    = true;
     1617                    break;
    16191618            }
    1620             else if (resulttext == tr("Sort"))
    1621             {
    1622                 showSortMenu();
    1623             }
    1624             else if (resulttext == tr("Record"))
    1625             {
    1626                 quickRecord();
    1627             }
    1628             else if (resulttext == tr("Edit Schedule"))
    1629             {
    1630                 edit();
    1631             }
    1632             else if (resulttext == tr("Program Details"))
    1633             {
    1634                 details();
    1635             }
    1636             else if (resulttext == tr("Upcoming"))
    1637             {
    1638                 upcoming();
    1639             }
    1640             else if (resulttext == tr("Custom Edit"))
    1641             {
    1642                 customEdit();
    1643             }
    1644             else if (resulttext == tr("Delete Rule"))
    1645             {
    1646                 deleteRule();
    1647             }
    1648             else if (resulttext == tr("Delete Episode"))
    1649             {
    1650                 deleteOldEpisode();
    1651             }
    16521619        }
    1653         else if (resultid == "sortmenu")
    1654         {
    1655             if (resulttext == tr("Reverse Sort Order"))
    1656             {
    1657                 m_reverseSort = !m_reverseSort;
    1658                 needUpdate = true;
    1659             }
    1660             else if (resulttext == tr("Sort By Title"))
    1661             {
    1662                 m_titleSort = true;
    1663                 m_reverseSort = false;
    1664                 needUpdate = true;
    1665             }
    1666             else if (resulttext == tr("Sort By Time"))
    1667             {
    1668                 m_titleSort = false;
    1669                 m_reverseSort = (m_type == plPreviouslyRecorded);
    1670                 needUpdate = true;
    1671             }
    1672         }
    16731620        else if (resultid == "deletemenu")
    16741621        {
    1675             if (resulttext == tr("Allow this episode to re-record"))
     1622            switch (buttonnum)
    16761623            {
    1677                 ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    1678                 if (pi)
     1624                case 0:
    16791625                {
    1680                     RecordingInfo ri(*pi);
    1681                     ri.ForgetHistory();
    1682                     *pi = ri;
     1626                    ProgramInfo *pi = GetCurrent();
     1627                    if (pi)
     1628                    {
     1629                        RecordingInfo ri(*pi);
     1630                        if (ri.IsDuplicate())
     1631                            ri.ForgetHistory();
     1632                        else
     1633                            ri.SetDupHistory();
     1634                        *pi = ri;
     1635                    }
     1636                    break;
    16831637                }
     1638                case 1:
     1639                    deleteOldEpisode();
     1640                    break;
     1641                case 2:
     1642                    deleteOldTitle();
     1643                    break;
    16841644            }
    1685             else if (resulttext == tr("Never record this episode"))
    1686             {
    1687                 ProgramInfo *pi = m_itemList[m_progList->GetCurrentPos()];
    1688                 if (pi)
    1689                 {
    1690                     RecordingInfo ri(*pi);
    1691                     ri.SetDupHistory();
    1692                     *pi = ri;
    1693                 }
    1694             }
    1695             else if (resulttext == tr("Remove this episode from the list"))
    1696             {
    1697                 deleteOldEpisode();
    1698             }
    1699             else if (resulttext == tr("Remove all episodes for this title"))
    1700             {
    1701                 deleteOldTitle();
    1702             }
    17031645        }
    17041646        else if (resultid == "deleterule")
    17051647        {
    1706             RecordingRule *record = qVariantValue<RecordingRule *>(dce->GetData());
    1707             if (record)
     1648            RecordingRule *record =
     1649                qVariantValue<RecordingRule *>(dce->GetData());
     1650            if (record && buttonnum > 0 && !record->Delete())
    17081651            {
    1709                 if (buttonnum > 0)
    1710                 {
    1711                     if (!record->Delete())
    1712                         VERBOSE(VB_IMPORTANT, "Failed to delete recording rule");
    1713                 }
    1714                 delete record;
     1652                VERBOSE(VB_IMPORTANT,
     1653                        LOC_ERR + "Failed to delete recording rule");
    17151654            }
     1655            if (record)
     1656                delete record;
    17161657        }
    17171658        else
     1659        {
    17181660            ScheduleCommon::customEvent(event);
     1661        }
    17191662    }
    17201663    else if (event->type() == ScreenLoadCompletionEvent::kEventType)
    17211664    {
     
    17291672
    17301673            if (m_curView < 0 && m_type != plPreviouslyRecorded)
    17311674                chooseView();
    1732             return;
    17331675        }
    17341676    }
    17351677    else if ((MythEvent::Type)(event->type()) == MythEvent::MythEventMessage)
     
    17381680        QString message = me->Message();
    17391681
    17401682        if (message == "CHOOSE_VIEW")
    1741         {
    17421683            chooseView();
    1743             return;
    1744         }
    17451684        else if (message == "SCHEDULE_CHANGE")
    1746         {
    17471685            needUpdate = true;
    1748         }
    17491686    }
    17501687
    17511688    if (needUpdate)
    17521689        fillItemList(true);
    17531690}
    1754 
    1755 ///////////////////////////////////////////////////////////////////////////////
    1756 
    1757 PhrasePopup::PhrasePopup(MythScreenStack *parentStack,
    1758                          ProgLister *parent,
    1759                          RecSearchType searchType,
    1760                          const QStringList &list,
    1761                          const QString &currentValue)
    1762             : MythScreenType(parentStack, "phrasepopup"),
    1763               m_parent(parent), m_searchType(searchType),  m_list(list),
    1764               m_titleText(NULL), m_phraseList(NULL), m_phraseEdit(NULL),
    1765               m_okButton(NULL), m_deleteButton(NULL), m_recordButton(NULL)
    1766 {
    1767     m_currentValue = currentValue;
    1768 }
    1769 
    1770 bool PhrasePopup::Create()
    1771 {
    1772     if (!LoadWindowFromXML("schedule-ui.xml", "phrasepopup", this))
    1773         return false;
    1774 
    1775     bool err = false;
    1776     UIUtilE::Assign(this, m_titleText, "title_text", &err);
    1777     UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
    1778     UIUtilE::Assign(this, m_phraseEdit, "phrase_edit", &err);
    1779     UIUtilE::Assign(this, m_okButton, "ok_button", &err);
    1780     UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
    1781     UIUtilE::Assign(this, m_recordButton, "record_button", &err);
    1782 
    1783     if (err)
    1784     {
    1785         VERBOSE(VB_IMPORTANT, "Cannot load screen 'phrasepopup'");
    1786         return false;
    1787     }
    1788 
    1789     if (m_searchType == kPowerSearch)
    1790     {
    1791         m_titleText->SetText(tr("Select Search"));
    1792         new MythUIButtonListItem(m_phraseList, tr("<New Search>"), NULL, false);
    1793         m_okButton->SetText(tr("Edit"));
    1794     }
    1795     else
    1796     {
    1797         m_titleText->SetText(tr("Phrase"));
    1798         new MythUIButtonListItem(m_phraseList, tr("<New Phrase>"), NULL, false);
    1799     }
    1800 
    1801     for (int x = 0; x < m_list.size(); x++)
    1802     {
    1803         new MythUIButtonListItem(m_phraseList, m_list.at(x), NULL, false);
    1804     }
    1805 
    1806     connect(m_phraseList, SIGNAL(itemClicked(MythUIButtonListItem*)),
    1807             this, SLOT(phraseClicked(MythUIButtonListItem*)));
    1808     connect(m_phraseList, SIGNAL(itemSelected(MythUIButtonListItem*)),
    1809             this, SLOT(phraseSelected(MythUIButtonListItem*)));
    1810 
    1811 
    1812     m_phraseList->MoveToNamedPosition(m_currentValue);
    1813 
    1814     m_deleteButton->SetText(tr("Delete"));
    1815     m_recordButton->SetText(tr("Record"));
    1816 
    1817     connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
    1818     connect(m_deleteButton, SIGNAL(Clicked()), this, SLOT(deleteClicked()));
    1819     connect(m_recordButton, SIGNAL(Clicked()), this, SLOT(recordClicked()));
    1820 
    1821     connect(m_phraseEdit, SIGNAL(valueChanged()), this, SLOT(editChanged()));
    1822 
    1823     BuildFocusList();
    1824 
    1825     SetFocusWidget(m_phraseList);
    1826 
    1827     return true;
    1828 }
    1829 
    1830 void PhrasePopup::editChanged(void)
    1831 {
    1832     m_okButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
    1833     m_deleteButton->SetEnabled((m_list.indexOf(m_phraseEdit->GetText().trimmed()) != -1));
    1834     m_recordButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
    1835 }
    1836 
    1837 void PhrasePopup::phraseClicked(MythUIButtonListItem *item)
    1838 {
    1839     if (!item)
    1840         return;
    1841 
    1842     int pos = m_phraseList->GetCurrentPos();
    1843 
    1844     if (pos == 0)
    1845        SetFocusWidget(m_phraseEdit);
    1846     else
    1847        okClicked();
    1848 }
    1849 
    1850 void PhrasePopup::phraseSelected(MythUIButtonListItem *item)
    1851 {
    1852     if (!item)
    1853         return;
    1854 
    1855     if (m_phraseList->GetCurrentPos() == 0)
    1856         m_phraseEdit->SetText("");
    1857     else
    1858         m_phraseEdit->SetText(item->GetText());
    1859 
    1860     m_okButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    1861     m_deleteButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    1862     m_recordButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    1863 }
    1864 
    1865 void PhrasePopup::okClicked(void)
    1866 {
    1867     if (m_phraseEdit->GetText().trimmed().isEmpty())
    1868         return;
    1869 
    1870     // check to see if we need to save the phrase
    1871     m_parent->updateKeywordInDB(m_phraseEdit->GetText(), m_phraseList->GetValue());
    1872 
    1873 //    emit haveResult(m_phraseList->GetCurrentPos());
    1874     emit haveResult(m_phraseEdit->GetText());
    1875 
    1876     Close();
    1877 }
    1878 
    1879 void PhrasePopup::deleteClicked(void)
    1880 {
    1881     int view = m_phraseList->GetCurrentPos() - 1;
    1882 
    1883     if (view < 0)
    1884         return;
    1885 
    1886     QString text = m_list[view];
    1887     QString qphrase = text;
    1888 
    1889     MSqlQuery query(MSqlQuery::InitCon());
    1890     query.prepare("DELETE FROM keyword "
    1891                   "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
    1892     query.bindValue(":PHRASE", qphrase);
    1893     query.bindValue(":TYPE", m_searchType);
    1894     if (!query.exec())
    1895         MythDB::DBError("PhrasePopup::deleteClicked", query);
    1896 
    1897     m_phraseList->RemoveItem(m_phraseList->GetItemCurrent());
    1898 
    1899     m_parent->m_viewList.removeAll(text);
    1900     m_parent->m_viewTextList.removeAll(text);
    1901 
    1902     if (view < m_parent->m_curView)
    1903         m_parent->m_curView--;
    1904     else if (view == m_parent->m_curView)
    1905         m_parent->m_curView = -1;
    1906 
    1907     if (m_parent->m_viewList.count() < 1)
    1908         SetFocusWidget(m_phraseEdit);
    1909     else
    1910         SetFocusWidget(m_phraseEdit);
    1911 }
    1912 
    1913 void PhrasePopup::recordClicked(void)
    1914 {
    1915     QString text = m_phraseEdit->GetText();
    1916     bool genreflag = false;
    1917 
    1918     QString what = text;
    1919 
    1920     if (text.trimmed().isEmpty())
    1921         return;
    1922 
    1923     if (m_searchType == kNoSearch)
    1924     {
    1925         VERBOSE(VB_IMPORTANT, "Unknown search in ProgLister");
    1926         return;
    1927     }
    1928 
    1929     if (m_searchType == kPowerSearch)
    1930     {
    1931         if (text == ":::::")
    1932             return;
    1933 
    1934         MSqlBindings bindings;
    1935         genreflag = m_parent->powerStringToSQL(text, what, bindings);
    1936 
    1937         if (what.isEmpty())
    1938             return;
    1939 
    1940         MSqlEscapeAsAQuery(what, bindings);
    1941     }
    1942 
    1943     RecordingRule *record = new RecordingRule();
    1944 
    1945     if (genreflag)
    1946     {
    1947         QString fromgenre = QString("LEFT JOIN programgenres ON "
    1948                 "program.chanid = programgenres.chanid AND "
    1949                 "program.starttime = programgenres.starttime ");
    1950         record->LoadBySearch(m_searchType, text, what, fromgenre);
    1951     }
    1952     else
    1953     {
    1954         record->LoadBySearch(m_searchType, text, what);
    1955     }
    1956 
    1957     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    1958     ScheduleEditor *schededit = new ScheduleEditor(mainStack, record);
    1959     if (schededit->Create())
    1960     {
    1961         mainStack->AddScreen(schededit);
    1962         okClicked();
    1963     }
    1964     else
    1965         delete schededit;
    1966 }
    1967 
    1968 ///////////////////////////////////////////////////////////////////////////////
    1969 
    1970 TimePopup::TimePopup(MythScreenStack *parentStack, ProgLister *parent)
    1971          : MythScreenType(parentStack, "timepopup"),
    1972            m_parent(parent), m_dateList(NULL), m_timeList(NULL),
    1973            m_okButton(NULL)
    1974 {
    1975 }
    1976 
    1977 bool TimePopup::Create()
    1978 {
    1979     if (!LoadWindowFromXML("schedule-ui.xml", "timepopup", this))
    1980         return false;
    1981 
    1982     bool err = false;
    1983     UIUtilE::Assign(this, m_dateList, "date_list", &err);
    1984     UIUtilE::Assign(this, m_timeList, "time_list", &err);
    1985     UIUtilE::Assign(this, m_okButton, "ok_button", &err);
    1986 
    1987     if (err)
    1988     {
    1989         VERBOSE(VB_IMPORTANT, "Cannot load screen 'timepopup'");
    1990         return false;
    1991     }
    1992 
    1993     // date
    1994     for (int x = -1; x <= 14; x++)
    1995     {
    1996         new MythUIButtonListItem(m_dateList,
    1997                                  m_parent->m_startTime.addDays(x).toString(m_parent->m_dayFormat),
    1998                                  NULL, false);
    1999 
    2000         if (m_parent->m_startTime.addDays(x).toString("MMdd") ==
    2001                 m_parent->m_searchTime.toString("MMdd"))
    2002             m_dateList->SetItemCurrent(m_dateList->GetCount() - 1);
    2003     }
    2004 
    2005     // time
    2006     QTime hr;
    2007     for (int x = 0; x < 24; x++)
    2008     {
    2009         hr.setHMS(x, 0, 0);
    2010         new MythUIButtonListItem(m_timeList,
    2011                                  hr.toString(m_parent->m_hourFormat),
    2012                                  NULL, false);
    2013 
    2014         if (hr.toString("hh") == m_parent->m_searchTime.toString("hh"))
    2015             m_timeList->SetItemCurrent(x);
    2016     }
    2017 
    2018     connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
    2019 
    2020     BuildFocusList();
    2021 
    2022     SetFocusWidget(m_dateList);
    2023 
    2024     return true;
    2025 }
    2026 
    2027 void TimePopup::okClicked(void)
    2028 {
    2029     QDateTime startTime = m_parent->m_startTime;
    2030     int dayOffset = m_dateList->GetCurrentPos() -1;
    2031 
    2032     startTime.setDate(startTime.addDays(dayOffset).date());
    2033 
    2034     QTime hr;
    2035     hr.setHMS(m_timeList->GetCurrentPos(), 0, 0);
    2036     startTime.setTime(hr);
    2037 
    2038     emit haveResult(startTime);
    2039 
    2040     Close();
    2041 }
    2042 
    2043 //////////////////////////////////////////////////////////////////////////////
    2044 
    2045 PowerSearchPopup::PowerSearchPopup(MythScreenStack *parentStack,
    2046                                    ProgLister *parent,
    2047                                    RecSearchType searchType,
    2048                                    const QStringList &list,
    2049                                    const QString &currentValue)
    2050             : MythScreenType(parentStack, "phrasepopup"),
    2051               m_parent(parent), m_searchType(searchType), m_list(list),
    2052               m_currentValue(currentValue),
    2053               m_titleText(NULL), m_phraseList(NULL), m_phraseEdit(NULL),
    2054               m_editButton(NULL), m_deleteButton(NULL), m_recordButton(NULL)
    2055 {
    2056 }
    2057 
    2058 bool PowerSearchPopup::Create()
    2059 {
    2060     if (!LoadWindowFromXML("schedule-ui.xml", "powersearchpopup", this))
    2061         return false;
    2062 
    2063     bool err = false;
    2064     UIUtilE::Assign(this, m_titleText, "title_text", &err);
    2065     UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
    2066     UIUtilE::Assign(this, m_editButton, "edit_button", &err);
    2067     UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
    2068     UIUtilE::Assign(this, m_recordButton, "record_button", &err);
    2069 
    2070     if (err)
    2071     {
    2072         VERBOSE(VB_IMPORTANT, "Cannot load screen 'powersearchpopup'");
    2073         return false;
    2074     }
    2075 
    2076     m_titleText->SetText(tr("Select Search"));
    2077     new MythUIButtonListItem(m_phraseList, tr("<New Search>"), NULL, false);
    2078 
    2079     for (int x = 0; x < m_list.size(); x++)
    2080     {
    2081         new MythUIButtonListItem(m_phraseList, m_list.at(x), NULL, false);
    2082     }
    2083 
    2084     connect(m_phraseList, SIGNAL(itemClicked(MythUIButtonListItem*)),
    2085             this, SLOT(phraseClicked(MythUIButtonListItem*)));
    2086     connect(m_phraseList, SIGNAL(itemSelected(MythUIButtonListItem*)),
    2087             this, SLOT(phraseSelected(MythUIButtonListItem*)));
    2088 
    2089 
    2090     m_phraseList->MoveToNamedPosition(m_currentValue);
    2091 
    2092     m_editButton->SetText(tr("Edit"));
    2093     m_deleteButton->SetText(tr("Delete"));
    2094     m_recordButton->SetText(tr("Record"));
    2095 
    2096     connect(m_editButton, SIGNAL(Clicked()), this, SLOT(editClicked()));
    2097     connect(m_deleteButton, SIGNAL(Clicked()), this, SLOT(deleteClicked()));
    2098     connect(m_recordButton, SIGNAL(Clicked()), this, SLOT(recordClicked()));
    2099 
    2100     BuildFocusList();
    2101 
    2102     SetFocusWidget(m_phraseList);
    2103 
    2104     return true;
    2105 }
    2106 
    2107 void PowerSearchPopup::phraseClicked(MythUIButtonListItem *item)
    2108 {
    2109     if (!item)
    2110         return;
    2111 
    2112     int pos = m_phraseList->GetCurrentPos();
    2113 
    2114     if (pos == 0)
    2115        editClicked();
    2116     else
    2117     {
    2118         emit haveResult(m_phraseList->GetValue());
    2119         Close();
    2120     }
    2121 }
    2122 
    2123 void PowerSearchPopup::phraseSelected(MythUIButtonListItem *item)
    2124 {
    2125     if (!item)
    2126         return;
    2127 
    2128     m_editButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    2129     m_deleteButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    2130     m_recordButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
    2131 }
    2132 
    2133 void PowerSearchPopup::editClicked(void)
    2134 {
    2135     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    2136 
    2137     QString currentItem = ":::::";
    2138 
    2139     if (m_phraseList->GetCurrentPos() != 0)
    2140           currentItem = m_phraseList->GetValue();
    2141 
    2142     EditPowerSearchPopup *popup = new EditPowerSearchPopup(popupStack, m_parent, currentItem);
    2143 
    2144     if (!popup->Create())
    2145     {
    2146         delete popup;
    2147         return;
    2148     }
    2149 
    2150     popupStack->AddScreen(popup);
    2151 
    2152     Close();
    2153 }
    2154 
    2155 void PowerSearchPopup::deleteClicked(void)
    2156 {
    2157     int view = m_phraseList->GetCurrentPos() - 1;
    2158 
    2159     if (view < 0)
    2160         return;
    2161 
    2162     QString text = m_list[view];
    2163     QString qphrase = text;
    2164 
    2165     MSqlQuery query(MSqlQuery::InitCon());
    2166     query.prepare("DELETE FROM keyword "
    2167                   "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
    2168     query.bindValue(":PHRASE", qphrase);
    2169     query.bindValue(":TYPE", m_searchType);
    2170     if (!query.exec())
    2171         MythDB::DBError("PowerSearchPopup::deleteClicked", query);
    2172 
    2173     m_phraseList->RemoveItem(m_phraseList->GetItemCurrent());
    2174 
    2175     m_parent->m_viewList.removeAll(text);
    2176     m_parent->m_viewTextList.removeAll(text);
    2177 
    2178     if (view < m_parent->m_curView)
    2179         m_parent->m_curView--;
    2180     else if (view == m_parent->m_curView)
    2181         m_parent->m_curView = -1;
    2182 
    2183     if (m_parent->m_viewList.count() < 1)
    2184         SetFocusWidget(m_phraseEdit);
    2185     else
    2186         SetFocusWidget(m_phraseEdit);
    2187 }
    2188 
    2189 void PowerSearchPopup::recordClicked(void)
    2190 {
    2191     QString text = m_phraseEdit->GetText();
    2192     bool genreflag = false;
    2193 
    2194     QString what = text;
    2195 
    2196     if (text.trimmed().isEmpty())
    2197         return;
    2198 
    2199     if (m_searchType == kNoSearch)
    2200     {
    2201         VERBOSE(VB_IMPORTANT, "Unknown search in ProgLister");
    2202         return;
    2203     }
    2204 
    2205     if (m_searchType == kPowerSearch)
    2206     {
    2207         if (text == ":::::")
    2208             return;
    2209 
    2210         MSqlBindings bindings;
    2211         genreflag = m_parent->powerStringToSQL(text, what, bindings);
    2212 
    2213         if (what.isEmpty())
    2214             return;
    2215 
    2216         MSqlEscapeAsAQuery(what, bindings);
    2217     }
    2218 
    2219     RecordingRule *record = new RecordingRule();
    2220 
    2221     if (genreflag)
    2222     {
    2223         QString fromgenre = QString("LEFT JOIN programgenres ON "
    2224                 "program.chanid = programgenres.chanid AND "
    2225                 "program.starttime = programgenres.starttime ");
    2226         record->LoadBySearch(m_searchType, text, what, fromgenre);
    2227     }
    2228     else
    2229     {
    2230         record->LoadBySearch(m_searchType, text, what);
    2231     }
    2232    
    2233     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    2234     ScheduleEditor *schededit = new ScheduleEditor(mainStack, record);
    2235     if (schededit->Create())
    2236     {
    2237         mainStack->AddScreen(schededit);
    2238         emit haveResult(m_phraseList->GetValue());
    2239         Close();
    2240     }
    2241     else
    2242         delete schededit;
    2243 }
    2244 
    2245 ///////////////////////////////////////////////////////////////////////////////
    2246 
    2247 EditPowerSearchPopup::EditPowerSearchPopup(MythScreenStack *parentStack,
    2248                                    ProgLister *parent,
    2249                                    const QString &currentValue)
    2250                 : MythScreenType(parentStack, "phrasepopup")
    2251 {
    2252     m_parent = parent;
    2253 
    2254     //sanity check currentvalue
    2255     m_currentValue = currentValue;
    2256     QStringList field = m_currentValue.split(':');
    2257     if (field.count() != 6)
    2258     {
    2259         VERBOSE(VB_IMPORTANT, QString("Error. PowerSearch %1 has %2 fields")
    2260                 .arg(m_currentValue).arg(field.count()));
    2261         m_currentValue = ":::::";
    2262     }
    2263 }
    2264 
    2265 bool EditPowerSearchPopup::Create()
    2266 {
    2267     if (!LoadWindowFromXML("schedule-ui.xml", "editpowersearchpopup", this))
    2268         return false;
    2269 
    2270     bool err = false;
    2271     UIUtilE::Assign(this, m_titleEdit, "title_edit", &err);
    2272     UIUtilE::Assign(this, m_subtitleEdit, "subtitle_edit", &err);
    2273     UIUtilE::Assign(this, m_descEdit, "desc_edit", &err);
    2274     UIUtilE::Assign(this, m_categoryList, "category_list", &err);
    2275     UIUtilE::Assign(this, m_genreList, "genre_list", &err);
    2276     UIUtilE::Assign(this, m_channelList, "channel_list", &err);
    2277     UIUtilE::Assign(this, m_okButton, "ok_button", &err);
    2278 
    2279     if (err)
    2280     {
    2281         VERBOSE(VB_IMPORTANT, "Cannot load screen 'editpowersearchpopup'");
    2282         return false;
    2283     }
    2284 
    2285     QStringList field = m_currentValue.split(':');
    2286 
    2287     m_titleEdit->SetText(field[0]);
    2288     m_subtitleEdit->SetText(field[1]);
    2289     m_descEdit->SetText(field[2]);
    2290 
    2291     initLists();
    2292 
    2293     connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
    2294 
    2295     BuildFocusList();
    2296 
    2297     SetFocusWidget(m_titleEdit);
    2298 
    2299     return true;
    2300 }
    2301 
    2302 void EditPowerSearchPopup::okClicked(void)
    2303 {
    2304     QString text;
    2305     text =  m_titleEdit->GetText().replace(':','%').replace('*','%') + ':';
    2306     text += m_subtitleEdit->GetText().replace(':','%').replace('*','%') + ':';
    2307     text += m_descEdit->GetText().replace(':','%').replace('*','%') + ':';
    2308 
    2309     if (m_categoryList->GetCurrentPos() > 0)
    2310         text += m_categories[m_categoryList->GetCurrentPos()];
    2311     text += ':';
    2312     if (m_genreList->GetCurrentPos() > 0)
    2313         text += m_genres[m_genreList->GetCurrentPos()];
    2314     text += ':';
    2315     if (m_channelList->GetCurrentPos() > 0)
    2316         text += m_channels[m_channelList->GetCurrentPos()];
    2317 
    2318     if (text == ":::::")
    2319         return;
    2320 
    2321     m_parent->updateKeywordInDB(text, m_currentValue);
    2322     m_parent->fillViewList(text);
    2323     m_parent->setViewFromList(text);
    2324 
    2325     Close();
    2326 }
    2327 
    2328 void EditPowerSearchPopup::initLists(void)
    2329 {
    2330     QStringList field = m_currentValue.split(':');
    2331 
    2332     // category type
    2333     m_categories.clear();
    2334     new MythUIButtonListItem(m_categoryList, tr("(Any Program Type)"), NULL, false);
    2335     m_categories << "";
    2336     new MythUIButtonListItem(m_categoryList, tr("Movies"), NULL, false);
    2337     m_categories << "movie";
    2338     new MythUIButtonListItem(m_categoryList, tr("Series"), NULL, false);
    2339     m_categories << "series";
    2340     new MythUIButtonListItem(m_categoryList, tr("Show"), NULL, false);
    2341     m_categories << "tvshow";
    2342     new MythUIButtonListItem(m_categoryList, tr("Sports"), NULL, false);
    2343     m_categories << "sports";
    2344     m_categoryList->SetItemCurrent(m_categories.indexOf(field[3]));
    2345 
    2346     // genre
    2347     m_genres.clear();
    2348     new MythUIButtonListItem(m_genreList, tr("(Any Genre)"), NULL, false);
    2349     m_genres << "";
    2350 
    2351     MSqlQuery query(MSqlQuery::InitCon());
    2352 
    2353     query.prepare("SELECT genre FROM programgenres GROUP BY genre;");
    2354 
    2355     if (query.exec())
    2356     {
    2357         while (query.next())
    2358         {
    2359             QString category = query.value(0).toString();
    2360             if (category.isEmpty() || category.trimmed().isEmpty())
    2361                 continue;
    2362             category = query.value(0).toString();
    2363             new MythUIButtonListItem(m_genreList, category, NULL, false);
    2364             m_genres << category;
    2365             if (category == field[4])
    2366                 m_genreList->SetItemCurrent(m_genreList->GetCount() - 1);
    2367         }
    2368     }
    2369 
    2370     // channel
    2371     QString channelOrdering = gCoreContext->GetSetting("ChannelOrdering", "channum");
    2372     QString channelFormat = gCoreContext->GetSetting("ChannelFormat", "<num> <sign>");
    2373 
    2374     m_channels.clear();
    2375     new MythUIButtonListItem(m_channelList, tr("(Any Channel)"), NULL, false);
    2376     m_channels << "";
    2377 
    2378     DBChanList channels = ChannelUtil::GetChannels(0, true, "callsign");
    2379     ChannelUtil::SortChannels(channels, channelOrdering, true);
    2380 
    2381     for (uint i = 0; i < channels.size(); ++i)
    2382     {
    2383         QString chantext = channelFormat;
    2384         chantext
    2385             .replace("<num>",  channels[i].channum)
    2386             .replace("<sign>", channels[i].callsign)
    2387             .replace("<name>", channels[i].name);
    2388 
    2389         m_parent->m_viewList << QString::number(channels[i].chanid);
    2390         m_parent->m_viewTextList << chantext;
    2391 
    2392         new MythUIButtonListItem(m_channelList, chantext, NULL, false);
    2393 
    2394         m_channels << channels[i].callsign;
    2395         if (channels[i].callsign == field[5])
    2396             m_channelList->SetItemCurrent(m_channelList->GetCount() - 1);
    2397     }
    2398 }
  • programs/mythfrontend/proglist_helpers.cpp

     
     1// MythTV
     2#include "mythuibuttonlist.h"
     3#include "proglist_helpers.h"
     4#include "mythcorecontext.h"
     5#include "mythuitextedit.h"
     6#include "scheduleeditor.h"
     7#include "recordingrule.h"
     8#include "mythuibutton.h"
     9#include "channelutil.h"
     10#include "proglist.h"
     11
     12PhrasePopup::PhrasePopup(MythScreenStack *parentStack,
     13                         ProgLister *parent,
     14                         RecSearchType searchType,
     15                         const QStringList &list,
     16                         const QString &currentValue) :
     17    MythScreenType(parentStack, "phrasepopup"),
     18    m_parent(parent), m_searchType(searchType),  m_list(list),
     19    m_titleText(NULL), m_phraseList(NULL), m_phraseEdit(NULL),
     20    m_okButton(NULL), m_deleteButton(NULL), m_recordButton(NULL)
     21{
     22    m_currentValue = currentValue;
     23}
     24
     25bool PhrasePopup::Create()
     26{
     27    if (!LoadWindowFromXML("schedule-ui.xml", "phrasepopup", this))
     28        return false;
     29
     30    bool err = false;
     31    UIUtilE::Assign(this, m_titleText, "title_text", &err);
     32    UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
     33    UIUtilE::Assign(this, m_phraseEdit, "phrase_edit", &err);
     34    UIUtilE::Assign(this, m_okButton, "ok_button", &err);
     35    UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
     36    UIUtilE::Assign(this, m_recordButton, "record_button", &err);
     37
     38    if (err)
     39    {
     40        VERBOSE(VB_IMPORTANT, "Cannot load screen 'phrasepopup'");
     41        return false;
     42    }
     43
     44    if (m_searchType == kPowerSearch)
     45    {
     46        m_titleText->SetText(tr("Select Search"));
     47        new MythUIButtonListItem(m_phraseList, tr("<New Search>"), NULL, false);
     48        m_okButton->SetText(tr("Edit"));
     49    }
     50    else
     51    {
     52        m_titleText->SetText(tr("Phrase"));
     53        new MythUIButtonListItem(m_phraseList, tr("<New Phrase>"), NULL, false);
     54    }
     55
     56    for (int x = 0; x < m_list.size(); x++)
     57    {
     58        new MythUIButtonListItem(m_phraseList, m_list.at(x), NULL, false);
     59    }
     60
     61    connect(m_phraseList, SIGNAL(itemClicked(MythUIButtonListItem*)),
     62            this, SLOT(phraseClicked(MythUIButtonListItem*)));
     63    connect(m_phraseList, SIGNAL(itemSelected(MythUIButtonListItem*)),
     64            this, SLOT(phraseSelected(MythUIButtonListItem*)));
     65
     66
     67    m_phraseList->MoveToNamedPosition(m_currentValue);
     68
     69    m_deleteButton->SetText(tr("Delete"));
     70    m_recordButton->SetText(tr("Record"));
     71
     72    connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
     73    connect(m_deleteButton, SIGNAL(Clicked()), this, SLOT(deleteClicked()));
     74    connect(m_recordButton, SIGNAL(Clicked()), this, SLOT(recordClicked()));
     75
     76    connect(m_phraseEdit, SIGNAL(valueChanged()), this, SLOT(editChanged()));
     77
     78    BuildFocusList();
     79
     80    SetFocusWidget(m_phraseList);
     81
     82    return true;
     83}
     84
     85void PhrasePopup::editChanged(void)
     86{
     87    m_okButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
     88    m_deleteButton->SetEnabled(
     89        (m_list.indexOf(m_phraseEdit->GetText().trimmed()) != -1));
     90    m_recordButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
     91}
     92
     93void PhrasePopup::phraseClicked(MythUIButtonListItem *item)
     94{
     95    if (!item)
     96        return;
     97
     98    int pos = m_phraseList->GetCurrentPos();
     99
     100    if (pos == 0)
     101        SetFocusWidget(m_phraseEdit);
     102    else
     103        okClicked();
     104}
     105
     106void PhrasePopup::phraseSelected(MythUIButtonListItem *item)
     107{
     108    if (!item)
     109        return;
     110
     111    if (m_phraseList->GetCurrentPos() == 0)
     112        m_phraseEdit->SetText("");
     113    else
     114        m_phraseEdit->SetText(item->GetText());
     115
     116    m_okButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     117    m_deleteButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     118    m_recordButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     119}
     120
     121void PhrasePopup::okClicked(void)
     122{
     123    if (m_phraseEdit->GetText().trimmed().isEmpty())
     124        return;
     125
     126    // check to see if we need to save the phrase
     127    m_parent->updateKeywordInDB(
     128        m_phraseEdit->GetText(), m_phraseList->GetValue());
     129
     130//    emit haveResult(m_phraseList->GetCurrentPos());
     131    emit haveResult(m_phraseEdit->GetText());
     132
     133    Close();
     134}
     135
     136void PhrasePopup::deleteClicked(void)
     137{
     138    int view = m_phraseList->GetCurrentPos() - 1;
     139
     140    if (view < 0)
     141        return;
     142
     143    QString text = m_list[view];
     144    QString qphrase = text;
     145
     146    MSqlQuery query(MSqlQuery::InitCon());
     147    query.prepare("DELETE FROM keyword "
     148                  "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
     149    query.bindValue(":PHRASE", qphrase);
     150    query.bindValue(":TYPE", m_searchType);
     151    if (!query.exec())
     152        MythDB::DBError("PhrasePopup::deleteClicked", query);
     153
     154    m_phraseList->RemoveItem(m_phraseList->GetItemCurrent());
     155
     156    m_parent->m_viewList.removeAll(text);
     157    m_parent->m_viewTextList.removeAll(text);
     158
     159    if (view < m_parent->m_curView)
     160        m_parent->m_curView--;
     161    else if (view == m_parent->m_curView)
     162        m_parent->m_curView = -1;
     163
     164    if (m_parent->m_viewList.count() < 1)
     165        SetFocusWidget(m_phraseEdit);
     166    else
     167        SetFocusWidget(m_phraseEdit);
     168}
     169
     170void PhrasePopup::recordClicked(void)
     171{
     172    QString text = m_phraseEdit->GetText();
     173    bool genreflag = false;
     174
     175    QString what = text;
     176
     177    if (text.trimmed().isEmpty())
     178        return;
     179
     180    if (m_searchType == kNoSearch)
     181    {
     182        VERBOSE(VB_IMPORTANT, "Unknown search in ProgLister");
     183        return;
     184    }
     185
     186    if (m_searchType == kPowerSearch)
     187    {
     188        if (text == ":::::")
     189            return;
     190
     191        MSqlBindings bindings;
     192        genreflag = m_parent->powerStringToSQL(text, what, bindings);
     193
     194        if (what.isEmpty())
     195            return;
     196
     197        MSqlEscapeAsAQuery(what, bindings);
     198    }
     199
     200    RecordingRule *record = new RecordingRule();
     201
     202    if (genreflag)
     203    {
     204        QString fromgenre = QString("LEFT JOIN programgenres ON "
     205                                    "program.chanid = programgenres.chanid AND "
     206                                    "program.starttime = programgenres.starttime ");
     207        record->LoadBySearch(m_searchType, text, what, fromgenre);
     208    }
     209    else
     210    {
     211        record->LoadBySearch(m_searchType, text, what);
     212    }
     213
     214    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
     215    ScheduleEditor *schededit = new ScheduleEditor(mainStack, record);
     216    if (schededit->Create())
     217    {
     218        mainStack->AddScreen(schededit);
     219        okClicked();
     220    }
     221    else
     222        delete schededit;
     223}
     224
     225///////////////////////////////////////////////////////////////////////////////
     226
     227TimePopup::TimePopup(MythScreenStack *parentStack, ProgLister *parent)
     228    : MythScreenType(parentStack, "timepopup"),
     229      m_parent(parent), m_dateList(NULL), m_timeList(NULL),
     230      m_okButton(NULL)
     231{
     232}
     233
     234bool TimePopup::Create()
     235{
     236    if (!LoadWindowFromXML("schedule-ui.xml", "timepopup", this))
     237        return false;
     238
     239    bool err = false;
     240    UIUtilE::Assign(this, m_dateList, "date_list", &err);
     241    UIUtilE::Assign(this, m_timeList, "time_list", &err);
     242    UIUtilE::Assign(this, m_okButton, "ok_button", &err);
     243
     244    if (err)
     245    {
     246        VERBOSE(VB_IMPORTANT, "Cannot load screen 'timepopup'");
     247        return false;
     248    }
     249
     250    // date
     251    for (int x = -1; x <= 14; x++)
     252    {
     253        new MythUIButtonListItem(
     254            m_dateList,
     255            m_parent->m_startTime.addDays(x).toString(m_parent->m_dayFormat),
     256            NULL, false);
     257
     258        if (m_parent->m_startTime.addDays(x).toString("MMdd") ==
     259            m_parent->m_searchTime.toString("MMdd"))
     260            m_dateList->SetItemCurrent(m_dateList->GetCount() - 1);
     261    }
     262
     263    // time
     264    QTime hr;
     265    for (int x = 0; x < 24; x++)
     266    {
     267        hr.setHMS(x, 0, 0);
     268        new MythUIButtonListItem(m_timeList,
     269                                 hr.toString(m_parent->m_hourFormat),
     270                                 NULL, false);
     271
     272        if (hr.toString("hh") == m_parent->m_searchTime.toString("hh"))
     273            m_timeList->SetItemCurrent(x);
     274    }
     275
     276    connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
     277
     278    BuildFocusList();
     279
     280    SetFocusWidget(m_dateList);
     281
     282    return true;
     283}
     284
     285void TimePopup::okClicked(void)
     286{
     287    QDateTime startTime = m_parent->m_startTime;
     288    int dayOffset = m_dateList->GetCurrentPos() -1;
     289
     290    startTime.setDate(startTime.addDays(dayOffset).date());
     291
     292    QTime hr;
     293    hr.setHMS(m_timeList->GetCurrentPos(), 0, 0);
     294    startTime.setTime(hr);
     295
     296    emit haveResult(startTime);
     297
     298    Close();
     299}
     300
     301//////////////////////////////////////////////////////////////////////////////
     302
     303PowerSearchPopup::PowerSearchPopup(MythScreenStack *parentStack,
     304                                   ProgLister *parent,
     305                                   RecSearchType searchType,
     306                                   const QStringList &list,
     307                                   const QString &currentValue)
     308    : MythScreenType(parentStack, "phrasepopup"),
     309      m_parent(parent), m_searchType(searchType), m_list(list),
     310      m_currentValue(currentValue),
     311      m_titleText(NULL), m_phraseList(NULL), m_phraseEdit(NULL),
     312      m_editButton(NULL), m_deleteButton(NULL), m_recordButton(NULL)
     313{
     314}
     315
     316bool PowerSearchPopup::Create()
     317{
     318    if (!LoadWindowFromXML("schedule-ui.xml", "powersearchpopup", this))
     319        return false;
     320
     321    bool err = false;
     322    UIUtilE::Assign(this, m_titleText, "title_text", &err);
     323    UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
     324    UIUtilE::Assign(this, m_editButton, "edit_button", &err);
     325    UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
     326    UIUtilE::Assign(this, m_recordButton, "record_button", &err);
     327
     328    if (err)
     329    {
     330        VERBOSE(VB_IMPORTANT, "Cannot load screen 'powersearchpopup'");
     331        return false;
     332    }
     333
     334    m_titleText->SetText(tr("Select Search"));
     335    new MythUIButtonListItem(m_phraseList, tr("<New Search>"), NULL, false);
     336
     337    for (int x = 0; x < m_list.size(); x++)
     338    {
     339        new MythUIButtonListItem(m_phraseList, m_list.at(x), NULL, false);
     340    }
     341
     342    connect(m_phraseList, SIGNAL(itemClicked(MythUIButtonListItem*)),
     343            this, SLOT(phraseClicked(MythUIButtonListItem*)));
     344    connect(m_phraseList, SIGNAL(itemSelected(MythUIButtonListItem*)),
     345            this, SLOT(phraseSelected(MythUIButtonListItem*)));
     346
     347
     348    m_phraseList->MoveToNamedPosition(m_currentValue);
     349
     350    m_editButton->SetText(tr("Edit"));
     351    m_deleteButton->SetText(tr("Delete"));
     352    m_recordButton->SetText(tr("Record"));
     353
     354    connect(m_editButton, SIGNAL(Clicked()), this, SLOT(editClicked()));
     355    connect(m_deleteButton, SIGNAL(Clicked()), this, SLOT(deleteClicked()));
     356    connect(m_recordButton, SIGNAL(Clicked()), this, SLOT(recordClicked()));
     357
     358    BuildFocusList();
     359
     360    SetFocusWidget(m_phraseList);
     361
     362    return true;
     363}
     364
     365void PowerSearchPopup::phraseClicked(MythUIButtonListItem *item)
     366{
     367    if (!item)
     368        return;
     369
     370    int pos = m_phraseList->GetCurrentPos();
     371
     372    if (pos == 0)
     373        editClicked();
     374    else
     375    {
     376        emit haveResult(m_phraseList->GetValue());
     377        Close();
     378    }
     379}
     380
     381void PowerSearchPopup::phraseSelected(MythUIButtonListItem *item)
     382{
     383    if (!item)
     384        return;
     385
     386    m_editButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     387    m_deleteButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     388    m_recordButton->SetEnabled((m_phraseList->GetCurrentPos() != 0));
     389}
     390
     391void PowerSearchPopup::editClicked(void)
     392{
     393    MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
     394
     395    QString currentItem = ":::::";
     396
     397    if (m_phraseList->GetCurrentPos() != 0)
     398        currentItem = m_phraseList->GetValue();
     399
     400    EditPowerSearchPopup *popup = new EditPowerSearchPopup(
     401        popupStack, m_parent, currentItem);
     402
     403    if (!popup->Create())
     404    {
     405        delete popup;
     406        return;
     407    }
     408
     409    popupStack->AddScreen(popup);
     410
     411    Close();
     412}
     413
     414void PowerSearchPopup::deleteClicked(void)
     415{
     416    int view = m_phraseList->GetCurrentPos() - 1;
     417
     418    if (view < 0)
     419        return;
     420
     421    QString text = m_list[view];
     422    QString qphrase = text;
     423
     424    MSqlQuery query(MSqlQuery::InitCon());
     425    query.prepare("DELETE FROM keyword "
     426                  "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
     427    query.bindValue(":PHRASE", qphrase);
     428    query.bindValue(":TYPE", m_searchType);
     429    if (!query.exec())
     430        MythDB::DBError("PowerSearchPopup::deleteClicked", query);
     431
     432    m_phraseList->RemoveItem(m_phraseList->GetItemCurrent());
     433
     434    m_parent->m_viewList.removeAll(text);
     435    m_parent->m_viewTextList.removeAll(text);
     436
     437    if (view < m_parent->m_curView)
     438        m_parent->m_curView--;
     439    else if (view == m_parent->m_curView)
     440        m_parent->m_curView = -1;
     441
     442    if (m_parent->m_viewList.count() < 1)
     443        SetFocusWidget(m_phraseEdit);
     444    else
     445        SetFocusWidget(m_phraseEdit);
     446}
     447
     448void PowerSearchPopup::recordClicked(void)
     449{
     450    QString text = m_phraseEdit->GetText();
     451    bool genreflag = false;
     452
     453    QString what = text;
     454
     455    if (text.trimmed().isEmpty())
     456        return;
     457
     458    if (m_searchType == kNoSearch)
     459    {
     460        VERBOSE(VB_IMPORTANT, "Unknown search in ProgLister");
     461        return;
     462    }
     463
     464    if (m_searchType == kPowerSearch)
     465    {
     466        if (text == ":::::")
     467            return;
     468
     469        MSqlBindings bindings;
     470        genreflag = m_parent->powerStringToSQL(text, what, bindings);
     471
     472        if (what.isEmpty())
     473            return;
     474
     475        MSqlEscapeAsAQuery(what, bindings);
     476    }
     477
     478    RecordingRule *record = new RecordingRule();
     479
     480    if (genreflag)
     481    {
     482        QString fromgenre = QString(
     483            "LEFT JOIN programgenres ON "
     484            "program.chanid = programgenres.chanid AND "
     485            "program.starttime = programgenres.starttime ");
     486        record->LoadBySearch(m_searchType, text, what, fromgenre);
     487    }
     488    else
     489    {
     490        record->LoadBySearch(m_searchType, text, what);
     491    }
     492   
     493    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
     494    ScheduleEditor *schededit = new ScheduleEditor(mainStack, record);
     495    if (schededit->Create())
     496    {
     497        mainStack->AddScreen(schededit);
     498        emit haveResult(m_phraseList->GetValue());
     499        Close();
     500    }
     501    else
     502        delete schededit;
     503}
     504
     505///////////////////////////////////////////////////////////////////////////////
     506
     507EditPowerSearchPopup::EditPowerSearchPopup(MythScreenStack *parentStack,
     508                                           ProgLister *parent,
     509                                           const QString &currentValue)
     510    : MythScreenType(parentStack, "phrasepopup")
     511{
     512    m_parent = parent;
     513
     514    //sanity check currentvalue
     515    m_currentValue = currentValue;
     516    QStringList field = m_currentValue.split(':');
     517    if (field.count() != 6)
     518    {
     519        VERBOSE(VB_IMPORTANT, QString("Error. PowerSearch %1 has %2 fields")
     520                .arg(m_currentValue).arg(field.count()));
     521        m_currentValue = ":::::";
     522    }
     523}
     524
     525bool EditPowerSearchPopup::Create()
     526{
     527    if (!LoadWindowFromXML("schedule-ui.xml", "editpowersearchpopup", this))
     528        return false;
     529
     530    bool err = false;
     531    UIUtilE::Assign(this, m_titleEdit, "title_edit", &err);
     532    UIUtilE::Assign(this, m_subtitleEdit, "subtitle_edit", &err);
     533    UIUtilE::Assign(this, m_descEdit, "desc_edit", &err);
     534    UIUtilE::Assign(this, m_categoryList, "category_list", &err);
     535    UIUtilE::Assign(this, m_genreList, "genre_list", &err);
     536    UIUtilE::Assign(this, m_channelList, "channel_list", &err);
     537    UIUtilE::Assign(this, m_okButton, "ok_button", &err);
     538
     539    if (err)
     540    {
     541        VERBOSE(VB_IMPORTANT, "Cannot load screen 'editpowersearchpopup'");
     542        return false;
     543    }
     544
     545    QStringList field = m_currentValue.split(':');
     546
     547    m_titleEdit->SetText(field[0]);
     548    m_subtitleEdit->SetText(field[1]);
     549    m_descEdit->SetText(field[2]);
     550
     551    initLists();
     552
     553    connect(m_okButton, SIGNAL(Clicked()), this, SLOT(okClicked()));
     554
     555    BuildFocusList();
     556
     557    SetFocusWidget(m_titleEdit);
     558
     559    return true;
     560}
     561
     562void EditPowerSearchPopup::okClicked(void)
     563{
     564    QString text;
     565    text =  m_titleEdit->GetText().replace(':','%').replace('*','%') + ':';
     566    text += m_subtitleEdit->GetText().replace(':','%').replace('*','%') + ':';
     567    text += m_descEdit->GetText().replace(':','%').replace('*','%') + ':';
     568
     569    if (m_categoryList->GetCurrentPos() > 0)
     570        text += m_categories[m_categoryList->GetCurrentPos()];
     571    text += ':';
     572    if (m_genreList->GetCurrentPos() > 0)
     573        text += m_genres[m_genreList->GetCurrentPos()];
     574    text += ':';
     575    if (m_channelList->GetCurrentPos() > 0)
     576        text += m_channels[m_channelList->GetCurrentPos()];
     577
     578    if (text == ":::::")
     579        return;
     580
     581    m_parent->updateKeywordInDB(text, m_currentValue);
     582    m_parent->fillViewList(text);
     583    m_parent->setViewFromList(text);
     584
     585    Close();
     586}
     587
     588void EditPowerSearchPopup::initLists(void)
     589{
     590    QStringList field = m_currentValue.split(':');
     591
     592    // category type
     593    m_categories.clear();
     594    new MythUIButtonListItem(
     595        m_categoryList, tr("(Any Program Type)"), NULL, false);
     596    m_categories << "";
     597    new MythUIButtonListItem(m_categoryList, tr("Movies"), NULL, false);
     598    m_categories << "movie";
     599    new MythUIButtonListItem(m_categoryList, tr("Series"), NULL, false);
     600    m_categories << "series";
     601    new MythUIButtonListItem(m_categoryList, tr("Show"), NULL, false);
     602    m_categories << "tvshow";
     603    new MythUIButtonListItem(m_categoryList, tr("Sports"), NULL, false);
     604    m_categories << "sports";
     605    m_categoryList->SetItemCurrent(m_categories.indexOf(field[3]));
     606
     607    // genre
     608    m_genres.clear();
     609    new MythUIButtonListItem(m_genreList, tr("(Any Genre)"), NULL, false);
     610    m_genres << "";
     611
     612    MSqlQuery query(MSqlQuery::InitCon());
     613
     614    query.prepare("SELECT genre FROM programgenres GROUP BY genre;");
     615
     616    if (query.exec())
     617    {
     618        while (query.next())
     619        {
     620            QString category = query.value(0).toString();
     621            if (category.isEmpty() || category.trimmed().isEmpty())
     622                continue;
     623            category = query.value(0).toString();
     624            new MythUIButtonListItem(m_genreList, category, NULL, false);
     625            m_genres << category;
     626            if (category == field[4])
     627                m_genreList->SetItemCurrent(m_genreList->GetCount() - 1);
     628        }
     629    }
     630
     631    // channel
     632    QString channelOrdering = gCoreContext->GetSetting(
     633        "ChannelOrdering", "channum");
     634    QString channelFormat = gCoreContext->GetSetting(
     635        "ChannelFormat", "<num> <sign>");
     636
     637    m_channels.clear();
     638    new MythUIButtonListItem(m_channelList, tr("(Any Channel)"), NULL, false);
     639    m_channels << "";
     640
     641    DBChanList channels = ChannelUtil::GetChannels(0, true, "callsign");
     642    ChannelUtil::SortChannels(channels, channelOrdering, true);
     643
     644    for (uint i = 0; i < channels.size(); ++i)
     645    {
     646        QString chantext = channelFormat;
     647        chantext
     648            .replace("<num>",  channels[i].channum)
     649            .replace("<sign>", channels[i].callsign)
     650            .replace("<name>", channels[i].name);
     651
     652        m_parent->m_viewList << QString::number(channels[i].chanid);
     653        m_parent->m_viewTextList << chantext;
     654
     655        new MythUIButtonListItem(m_channelList, chantext, NULL, false);
     656
     657        m_channels << channels[i].callsign;
     658        if (channels[i].callsign == field[5])
     659            m_channelList->SetItemCurrent(m_channelList->GetCount() - 1);
     660    }
     661}