Ticket #199: channelgroup.5.diff

File channelgroup.5.diff, 64.5 KB (added by wstewart@…, 17 years ago)

Updated for SVN 20471

  • libs/libmythtv/channelgroup.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelgroup.cpp mythtv/libs/libmythtv/channelgroup.cpp
    old new  
     1#include "mythcontext.h"
     2#include "libmythdb/mythdbcon.h"
     3#include <qsqldatabase.h>
     4#include <qcursor.h>
     5#include <qlayout.h>
     6#include <iostream>
     7#include "mythstorage.h"
     8#include "mythdb.h"
     9#include "channelutil.h"
     10#include "channelgroup.h"
     11
     12#define LOC QString("Channel Group: ")
     13#define LOC_ERR QString("Channel Group, Error: ")
     14
     15ChannelGroupItem& ChannelGroupItem::operator=(const ChannelGroupItem &other)
     16{
     17    grpid     = other.grpid;
     18    name      = (other.name);
     19 
     20    return *this;
     21}
     22
     23ChannelGroupItem::ChannelGroupItem(const ChannelGroupItem &other)
     24{
     25    (*this) = other;
     26}
     27
     28inline bool lt_group(const ChannelGroupItem &a, const ChannelGroupItem &b)
     29{
     30    return QString::localeAwareCompare(a.name, b.name) < 0;
     31}
     32
     33bool ChannelGroup::ToggleChannel(uint chanid, int changrpid, int delete_chan)
     34{
     35    // Check if it already exists for that chanid...
     36    MSqlQuery query(MSqlQuery::InitCon());
     37    query.prepare(
     38        "SELECT channelgroup.id "
     39        "FROM channelgroup "
     40        "WHERE channelgroup.chanid = :CHANID AND "
     41        "channelgroup.grpid = :GRPID "
     42        "LIMIT 1");
     43    query.bindValue(":CHANID", chanid);
     44    query.bindValue(":GRPID", changrpid);
     45
     46    if (!query.exec() || !query.isActive())
     47    {
     48        MythDB::DBError("ChannelGroup::ToggleChannel", query);
     49        return false;
     50    }
     51    else if ((query.size() > 0) && delete_chan)
     52    {
     53        // We have a record...Remove it to toggle...
     54        query.next();
     55        QString id = query.value(0).toString();
     56        query.prepare(
     57            QString("DELETE FROM channelgroup "
     58                    "WHERE id = '%1'").arg(id));
     59        query.exec();
     60        VERBOSE(VB_IMPORTANT, LOC + QString("Removing channel with id=%1.").arg(id));
     61    }
     62    else if (query.size() == 0)
     63    {
     64        // We have no record...Add one to toggle...
     65        query.prepare(
     66            QString("INSERT INTO channelgroup (chanid,grpid) "
     67                    "VALUES ('%1','%2')").arg(chanid).arg(changrpid));
     68        query.exec();
     69        VERBOSE(VB_IMPORTANT, LOC + QString("Adding channel %1 to group %2.").arg(chanid).arg(changrpid));
     70    }
     71
     72    return true;
     73}
     74
     75bool ChannelGroup::AddChannel(uint chanid, int changrpid)
     76{
     77    // Check if it already exists for that chanid...
     78    MSqlQuery query(MSqlQuery::InitCon());
     79    query.prepare(
     80        "SELECT channelgroup.id "
     81        "FROM channelgroup "
     82        "WHERE channelgroup.chanid = :CHANID AND "
     83        "channelgroup.grpid = :GRPID "
     84        "LIMIT 1");
     85    query.bindValue(":CHANID", chanid);
     86    query.bindValue(":GRPID", changrpid);
     87
     88    if (!query.exec() || !query.isActive())
     89    {
     90        MythDB::DBError("ChannelGroup::ToggleChannel", query);
     91        return false;
     92    }
     93    else if (query.size() == 0)
     94    {
     95        // We have no record...Add one to toggle...
     96        query.prepare(
     97            QString("INSERT INTO channelgroup (chanid,grpid) "
     98                    "VALUES ('%1','%2')").arg(chanid).arg(changrpid));
     99        query.exec();
     100        VERBOSE(VB_IMPORTANT, LOC + QString("Adding channel %1 to group %2.").arg(chanid).arg(changrpid));
     101    }
     102
     103    return true;
     104}
     105
     106bool ChannelGroup::DeleteChannel(uint chanid, int changrpid)
     107{
     108    // Check if it already exists for that chanid...
     109    MSqlQuery query(MSqlQuery::InitCon());
     110    query.prepare(
     111        "SELECT channelgroup.id "
     112        "FROM channelgroup "
     113        "WHERE channelgroup.chanid = :CHANID AND "
     114        "channelgroup.grpid = :GRPID "
     115        "LIMIT 1");
     116    query.bindValue(":CHANID", chanid);
     117    query.bindValue(":GRPID", changrpid);
     118
     119    if (!query.exec() || !query.isActive())
     120    {
     121        MythDB::DBError("ChannelGroup::ToggleChannel", query);
     122        return false;
     123    }
     124    else if (query.size() > 0)
     125    {
     126        // We have a record...Remove it to toggle...
     127        query.next();
     128        QString id = query.value(0).toString();
     129        query.prepare(
     130            QString("DELETE FROM channelgroup "
     131                    "WHERE id = '%1'").arg(id));
     132        query.exec();
     133        VERBOSE(VB_IMPORTANT, LOC + QString("Removing channel with id=%1.").arg(id));
     134    }
     135
     136    return true;
     137}
     138
     139ChannelGroupList ChannelGroup::GetChannelGroups(void)
     140{
     141    ChannelGroupList list;
     142   
     143    MSqlQuery query(MSqlQuery::InitCon());
     144   
     145    QString qstr = "SELECT grpid, name FROM channelgroupnames order by name";
     146   
     147    query.prepare(qstr);
     148
     149    if (!query.exec() || !query.isActive())
     150        MythDB::DBError("ChannelGroup::GetChannelGroups", query);
     151    else
     152    {
     153        while (query.next())
     154        {
     155           ChannelGroupItem group(query.value(0).toUInt(),
     156                              query.value(1).toString());
     157           list.push_back(group);
     158        }
     159    }
     160   
     161//    stable_sort(list.begin(), list.end(), lt_group);
     162
     163    return list;
     164}
     165
     166// Cycle through the available groups, then all channels
     167// Will cycle through to end then return -1
     168// To signify all channels.
     169int ChannelGroup::GetNextChannelGroup(const ChannelGroupList &sorted, int grpid)
     170{
     171    // If no groups return -1 for all channels
     172    if (sorted.empty())
     173      return -1;
     174   
     175    // If grpid is all channels (-1), then return the first grpid 
     176    if (grpid == -1)
     177      return sorted[0].grpid;
     178     
     179    ChannelGroupList::const_iterator it = find(sorted.begin(), sorted.end(), grpid);
     180
     181    // If grpid is not in the list, return -1 for all channels
     182    if (it == sorted.end())
     183        return -1;
     184
     185    ++it;
     186
     187    // If we reached the end, the next option is all channels (-1)
     188    if (it == sorted.end())
     189       return -1;
     190
     191    return it->grpid;
     192}
     193
     194QString ChannelGroup::GetChannelGroupName(int grpid)
     195{
     196    // All Channels
     197    if (grpid == -1)
     198        return "All Channels";
     199
     200    MSqlQuery query(MSqlQuery::InitCon());
     201   
     202    QString qstr = QString("SELECT name FROM channelgroupnames where grpid='%1'")
     203                   .arg(grpid);
     204   
     205    query.prepare(qstr);
     206
     207    if (!query.exec() || !query.isActive())
     208        MythDB::DBError("ChannelGroup::GetChannelGroups", query);
     209    else if (query.size() > 0)
     210    {
     211        query.next();   
     212        return query.value(0).toString();
     213    }
     214   
     215    return "";
     216}
     217
     218int ChannelGroup::GetChannelGroupId(QString changroupname)
     219{
     220    // All Channels
     221    if (changroupname == "All Channels")
     222      return -1;
     223
     224    MSqlQuery query(MSqlQuery::InitCon());
     225   
     226    QString qstr = QString("SELECT grpid FROM channelgroupnames where name='%1'")
     227                   .arg(changroupname);
     228   
     229    query.prepare(qstr);
     230
     231    if (!query.exec() || !query.isActive())
     232        MythDB::DBError("ChannelGroup::GetChannelGroups", query);
     233    else if (query.size() > 0)
     234    {
     235        query.next();   
     236        return query.value(0).toUInt();
     237    }
     238   
     239    return 0;
     240}
     241 No newline at end of file
  • libs/libmythtv/channelgroup.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelgroup.h mythtv/libs/libmythtv/channelgroup.h
    old new  
     1#ifndef CHANNELGROUP_H
     2#define CHANNELGROUP_H
     3
     4class ChannelGroupItem
     5{
     6  public:
     7    ChannelGroupItem(const ChannelGroupItem&);
     8    ChannelGroupItem(const uint _grpid,
     9                  const QString &_name) :
     10        grpid(_grpid), name(_name) {}
     11
     12    bool operator == (uint _grpid) const
     13        { return grpid == _grpid; }
     14
     15    ChannelGroupItem& operator=(const ChannelGroupItem&);
     16
     17  public:
     18    uint    grpid;
     19    QString name;
     20};
     21typedef vector<ChannelGroupItem> ChannelGroupList;
     22
     23/** \class ChannelGroup
     24*/
     25class MPUBLIC ChannelGroup
     26{
     27  public:
     28    // ChannelGroup
     29    static ChannelGroupList  GetChannelGroups(void);
     30    static bool              ToggleChannel(uint chanid, int changrpid, int delete_chan);
     31    static bool              AddChannel(uint chanid, int changrpid);
     32    static bool              DeleteChannel(uint chanid, int changrpid);
     33    static int               GetNextChannelGroup(const ChannelGroupList &sorted, int grpid);
     34    static QString           GetChannelGroupName(int grpid);
     35    static int               GetChannelGroupId(QString changroupname);
     36   
     37  private:
     38
     39};
     40
     41#endif
  • libs/libmythtv/channelgroupsettings.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelgroupsettings.cpp mythtv/libs/libmythtv/channelgroupsettings.cpp
    old new  
     1#include "mythcontext.h"
     2#include "libmythdb/mythdbcon.h"
     3#include <qsqldatabase.h>
     4#include <qcursor.h>
     5#include <qlayout.h>
     6#include <iostream>
     7#include "mythstorage.h"
     8#include "mythdb.h"
     9#include "channelutil.h"
     10#include "channelgroup.h"
     11#include "channelgroupsettings.h"
     12
     13#define LOC QString("Channel Group Settings: ")
     14#define LOC_ERR QString("Channel Group Settings, Error: ")
     15
     16// Storage class for channel group editor in settings
     17class ChannelGroupStorage : public Storage
     18{
     19  public:
     20    ChannelGroupStorage(Setting *_setting,
     21                    uint _chanid, QString _grpname) :
     22        setting(_setting), chanid(_chanid), grpname(_grpname) {}
     23    virtual ~ChannelGroupStorage() {};
     24
     25    virtual void Load(void);
     26    virtual void Save(void);
     27    virtual void Save(QString destination);
     28
     29  protected:
     30    Setting *setting;
     31    uint    chanid;
     32    QString grpname;
     33    int     grpid;
     34};
     35
     36void ChannelGroupStorage::Load(void)
     37{
     38    setting->setValue("0");
     39   
     40    MSqlQuery query(MSqlQuery::InitCon());
     41   
     42    QString qstr = "SELECT grpid FROM channelgroupnames WHERE name = :GRPNAME";
     43   
     44    query.prepare(qstr);
     45    query.bindValue(":GRPNAME", grpname);
     46
     47    if (!query.exec() || !query.isActive())
     48        MythDB::DBError("ChannelGroupStorage::Load", query);
     49    else
     50    {
     51      query.next();
     52      grpid = query.value(0).toUInt();
     53   
     54      qstr = "SELECT * FROM channelgroup WHERE grpid = :GRPID AND chanid = :CHANID";
     55      query.prepare(qstr);
     56      query.bindValue(":GRPID",  grpid);
     57      query.bindValue(":CHANID", chanid);
     58
     59      if (!query.exec() || !query.isActive())
     60          MythDB::DBError("ChannelGroupStorage::Load", query);
     61      else if (query.size() > 0)
     62        setting->setValue("1");
     63    }
     64}
     65
     66void ChannelGroupStorage::Save(void)
     67{
     68    QString value = setting->getValue();
     69   
     70    if (value == "1")
     71        ChannelGroup::AddChannel(chanid, grpid);
     72    else
     73        ChannelGroup::DeleteChannel(chanid, grpid);   
     74}
     75
     76void ChannelGroupStorage::Save(QString destination)
     77{
     78    Save();
     79}
     80
     81class ChannelCheckBox : public CheckBoxSetting, public ChannelGroupStorage
     82{
     83  public:
     84    ChannelCheckBox(const ChannelGroupConfig& _parent, const uint chanid, const QString channum,
     85               const QString channame, const QString grpname):
     86        CheckBoxSetting(this),
     87        ChannelGroupStorage(this, chanid, grpname)
     88    {
     89        setLabel(QString("%1 %2").arg(channum).arg(channame));
     90        setHelpText(QObject::tr("Select/Unselect channels for this channel group"));
     91    };
     92};
     93
     94ChannelGroupConfig::ChannelGroupConfig(QString _name)
     95    : name(_name)
     96{
     97    VerticalConfigurationGroup   *cgroup;
     98    HorizontalConfigurationGroup *columns;
     99
     100    DBChanList chanlist = ChannelUtil::GetChannels(0, true, "channum, callsign");
     101    ChannelUtil::SortChannels(chanlist, "channum", true);
     102
     103    DBChanList::iterator it = chanlist.begin();
     104    int i,j = 0;
     105    int p = 1;
     106    int pages = (int)((float)chanlist.size() / 8.0 / 3.0 + 0.5);
     107   
     108    do
     109    { 
     110        columns = new HorizontalConfigurationGroup(false,false,false,false);
     111        columns->setLabel(getName() + " " +
     112                          QObject::tr("Channel Group - Page ") + QString("%1").arg(p) +
     113                          QObject::tr("of") + QString("%1").arg(pages));
     114       
     115        for (j = 0; ((j < 3) && (it < chanlist.end())); ++j)
     116        {
     117            cgroup = new VerticalConfigurationGroup(false,false,false,false);
     118           
     119            for (i = 0; ((i < 8) && (it < chanlist.end())); ++i)
     120            {
     121                cgroup->addChild(new ChannelCheckBox(*this, it->chanid, it->channum, it->name, _name));
     122                ++it;
     123            }
     124            columns->addChild(cgroup);
     125        }
     126       
     127        ++p;
     128        addChild(columns);
     129    } while (it < chanlist.end());
     130
     131}
     132
     133ChannelGroupEditor::ChannelGroupEditor(void) :
     134    listbox(new ListBoxSetting(this)), lastValue("__CREATE_NEW_GROUP__")
     135{
     136    listbox->setLabel(tr("Channel Groups"));
     137    addChild(listbox);
     138}
     139
     140void ChannelGroupEditor::open(QString name)
     141{
     142    lastValue = name;
     143    bool created = false;
     144
     145    if (name == "__CREATE_NEW_GROUP__")
     146    {
     147        name = "";
     148       
     149        bool ok = MythPopupBox::showGetTextPopup(gContext->GetMainWindow(),
     150            tr("Create New Channel Group"),
     151            tr("Enter group name or press SELECT to enter text via the "
     152               "On Screen Keyboard"), name);
     153        if (!ok)
     154            return;
     155
     156        MSqlQuery query(MSqlQuery::InitCon());
     157        query.prepare("INSERT INTO channelgroupnames (name) VALUES (:NAME);");
     158        query.bindValue(":NAME", name);
     159        if (!query.exec())
     160            MythDB::DBError("ChannelGroupEditor::open", query);
     161        else
     162            created = true;
     163    }
     164   
     165    ChannelGroupConfig group(name);
     166   
     167    if (group.exec() == QDialog::Accepted || !created)
     168        lastValue = name;
     169
     170};
     171
     172void ChannelGroupEditor::doDelete(void)
     173{
     174    QString name = listbox->getValue();
     175    if (name == "__CREATE_NEW_GROUP__")
     176        return;
     177
     178    QString message = tr("Delete '%1' Channel group?").arg(name);
     179   
     180    DialogCode value = MythPopupBox::Show2ButtonPopup(
     181        gContext->GetMainWindow(),
     182        "", message,
     183        tr("Yes, delete group"),
     184        tr("No, Don't delete group"), kDialogCodeButton1);
     185
     186    if (kDialogCodeButton0 == value)
     187    {
     188        MSqlQuery query(MSqlQuery::InitCon());
     189
     190        // Find out channel group id
     191        query.prepare("SELECT grpid FROM channelgroupnames WHERE name = :NAME;");
     192        query.bindValue(":NAME", name);
     193        if (!query.exec())
     194            MythDB::DBError("ChannelGroupEditor::doDelete", query);
     195        query.next();
     196        uint grpid = query.value(0).toUInt();
     197
     198        // Delete channels from this group
     199        query.prepare("DELETE FROM channelgroup WHERE grpid = :GRPID;");
     200        query.bindValue(":GRPID", grpid);
     201        if (!query.exec())
     202            MythDB::DBError("ChannelGroupEditor::doDelete", query);
     203       
     204        // Now delete the group from channelgroupnames
     205        query.prepare("DELETE FROM channelgroupnames WHERE name = :NAME;");
     206        query.bindValue(":NAME", name);
     207        if (!query.exec())
     208            MythDB::DBError("ChannelGroupEditor::doDelete", query);
     209
     210        lastValue = "__CREATE_NEW_GROUP__";
     211        Load();
     212    }
     213
     214    listbox->setFocus();
     215}
     216
     217void ChannelGroupEditor::Load(void)
     218{
     219    listbox->clearSelections();
     220   
     221    ChannelGroupList changrplist;
     222
     223    changrplist = ChannelGroup::GetChannelGroups();
     224
     225    ChannelGroupList::iterator it;
     226
     227    for (it = changrplist.begin(); it < changrplist.end(); ++it)
     228       listbox->addSelection(it->name);
     229       
     230    listbox->addSelection(tr("(Create new group)"), "__CREATE_NEW_GROUP__");
     231
     232    listbox->setValue(lastValue);
     233}
     234
     235DialogCode ChannelGroupEditor::exec(void)
     236{VERBOSE(VB_IMPORTANT, "ChannelGroupEditor::exec");
     237    while (ConfigurationDialog::exec() == kDialogCodeAccepted)
     238        open(listbox->getValue());
     239
     240    return kDialogCodeRejected;
     241}
     242
     243MythDialog* ChannelGroupEditor::dialogWidget(MythMainWindow* parent,
     244                                          const char* widgetName)
     245{
     246    dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
     247    connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(doDelete()));
     248    connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(doDelete()));
     249    return dialog;
     250}
  • libs/libmythtv/channelgroupsettings.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelgroupsettings.h mythtv/libs/libmythtv/channelgroupsettings.h
    old new  
     1#ifndef CHANNELGROUPSETTINGS_H
     2#define CHANNELGROUPSETTINGS_H
     3
     4#include "libmyth/settings.h"
     5
     6class MPUBLIC ChannelGroupConfig: public ConfigurationWizard
     7{
     8 public:
     9    ChannelGroupConfig(QString _name);
     10    QString getName(void) const { return name; }
     11
     12 private:
     13    QString name;
     14};
     15
     16class MPUBLIC ChannelGroupEditor : public QObject, public ConfigurationDialog
     17{
     18    Q_OBJECT
     19
     20  public:
     21    ChannelGroupEditor(void);
     22    virtual DialogCode exec(void);
     23    virtual void Load(void);
     24    virtual void Save(void) { };
     25    virtual void Save(QString) { };
     26    virtual MythDialog* dialogWidget(MythMainWindow* parent,
     27                                     const char* widgetName=0);
     28
     29  protected slots:
     30    void open(QString name);
     31    void doDelete(void);
     32
     33  protected:
     34    ListBoxSetting *listbox;
     35    QString         lastValue;
     36};
     37
     38#endif
  • libs/libmythtv/channelutil.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelutil.cpp mythtv/libs/libmythtv/channelutil.cpp
    old new bool ChannelUtil::GetChannelSettings(int  
    15701570    return true;
    15711571}
    15721572
    1573 DBChanList ChannelUtil::GetChannels(uint sourceid, bool vis_only, QString grp)
     1573DBChanList ChannelUtil::GetChannels(uint sourceid, bool vis_only, QString grp, int changrpid)
    15741574{
    15751575    DBChanList list;
    1576     QMap<uint,uint> favorites;
     1576   
    15771577    MSqlQuery query(MSqlQuery::InitCon());
    1578     query.prepare(
    1579         "SELECT chanid, favid "
    1580         "FROM favorites");
    1581     if (!query.exec() || !query.isActive())
    1582         MythDB::DBError("get channels -- favorites", query);
    1583     else
    1584     {
    1585         while (query.next())
    1586             favorites[query.value(0).toUInt()] = query.value(1).toUInt();
    1587     }
    15881578
    15891579    QString qstr =
    1590         "SELECT channum, callsign, chanid, "
     1580        "SELECT channum, callsign, channel.chanid, "
    15911581        "       atsc_major_chan, atsc_minor_chan, "
    15921582        "       name, icon, mplexid, visible "
    15931583        "FROM channel ";
    15941584
     1585    // Select only channels from the specified channel group
     1586    if (changrpid > -1)
     1587        qstr += QString(",channelgroup ");
     1588
    15951589    if (sourceid)
    15961590        qstr += QString("WHERE sourceid='%1' ").arg(sourceid);
    15971591    else
    DBChanList ChannelUtil::GetChannels(uint  
    15991593            "WHERE cardinput.sourceid = channel.sourceid   AND "
    16001594            "      cardinput.cardid   = capturecard.cardid     ";
    16011595
     1596    if (changrpid > -1)
     1597    {
     1598        qstr += QString("AND channel.chanid = channelgroup.chanid "
     1599                        "AND channelgroup.grpid ='%1' ").arg(changrpid);
     1600    }
     1601
    16021602    if (vis_only)
    16031603        qstr += "AND visible=1 ";
    16041604
    DBChanList ChannelUtil::GetChannels(uint  
    16231623            query.value(2).toUInt(),                      /* chanid     */
    16241624            query.value(3).toUInt(),                      /* ATSC major */
    16251625            query.value(4).toUInt(),                      /* ATSC minor */
    1626             favorites[query.value(2).toUInt()],           /* favid      */
    16271626            query.value(7).toUInt(),                      /* mplexid    */
    16281627            query.value(8).toBool(),                      /* visible    */
    16291628            query.value(5).toString(),                    /* name       */
    uint ChannelUtil::GetNextChannel(  
    18251824                (mplexid_restriction &&
    18261825                 (mplexid_restriction != it->mplexid))));
    18271826    }
    1828     else if (CHANNEL_DIRECTION_UP == direction)
     1827    else if ((CHANNEL_DIRECTION_UP == direction) || (CHANNEL_DIRECTION_FAVORITE == direction))
    18291828    {
    18301829        do
    18311830        {
    uint ChannelUtil::GetNextChannel(  
    18381837                (mplexid_restriction &&
    18391838                 (mplexid_restriction != it->mplexid))));
    18401839    }
    1841     else if (CHANNEL_DIRECTION_FAVORITE == direction)
    1842     {
    1843         do
    1844         {
    1845             it++;
    1846             if (it == sorted.end())
    1847                 it = sorted.begin();
    1848         }
    1849         while ((it != start) &&
    1850                (!it->favorite ||
    1851                 (skip_non_visible && !it->visible) ||
    1852                 (mplexid_restriction &&
    1853                  (mplexid_restriction != it->mplexid))));
    1854     }
    18551840
    18561841    return it->chanid;
    18571842}
  • libs/libmythtv/channelutil.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/channelutil.h mythtv/libs/libmythtv/channelutil.h
    old new class MPUBLIC ChannelUtil  
    167167    static QString GetVideoFilters(uint sourceid, const QString &channum)
    168168        { return GetChannelValueStr("videofilters", sourceid, channum); }
    169169
    170     static DBChanList GetChannels(uint srcid, bool vis_only, QString grp="");
     170    static DBChanList GetChannels(uint srcid, bool vis_only, QString grp="", int changrpid=-1);
    171171    static uint    GetChannelCount(int sourceid = -1);
    172172    static void    SortChannels(DBChanList &list, const QString &order,
    173173                                bool eliminate_duplicates = false);
  • libs/libmythtv/dbchannelinfo.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/dbchannelinfo.cpp mythtv/libs/libmythtv/dbchannelinfo.cpp
    old new DBChannel::DBChannel(const DBChannel &ot  
    2323DBChannel::DBChannel(
    2424    const QString &_channum, const QString &_callsign,
    2525    uint _chanid, uint _major_chan, uint _minor_chan,
    26     uint _favorite, uint _mplexid, bool _visible,
     26    uint _mplexid, bool _visible,
    2727    const QString &_name, const QString &_icon) :
    2828    channum(_channum),
    2929    callsign(_callsign), chanid(_chanid),
    3030    major_chan(_major_chan), minor_chan(_minor_chan),
    31     favorite(_favorite), mplexid(_mplexid), visible(_visible),
     31    mplexid(_mplexid), visible(_visible),
    3232    name(_name), icon(_icon)
    3333{
    3434    channum.detach();
    DBChannel &DBChannel::operator=(const DB  
    4646    chanid     = other.chanid;
    4747    major_chan = other.major_chan;
    4848    minor_chan = other.minor_chan;
    49     favorite   = other.favorite;
    5049    mplexid    = (other.mplexid == 32767) ? 0 : other.mplexid;
    5150    visible    = other.visible;
    5251    name       = other.name; name.detach();
  • libs/libmythtv/dbchannelinfo.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/dbchannelinfo.h mythtv/libs/libmythtv/dbchannelinfo.h
    old new class MPUBLIC DBChannel  
    2424    DBChannel(const DBChannel&);
    2525    DBChannel(const QString &_channum, const QString &_callsign,
    2626              uint _chanid, uint _major_chan, uint _minor_chan,
    27               uint _favorite, uint _mplexid, bool _visible,
     27              uint _mplexid, bool _visible,
    2828              const QString &_name, const QString &_icon);
    2929    DBChannel& operator=(const DBChannel&);
    3030
    class MPUBLIC DBChannel  
    3737    uint    chanid;
    3838    uint    major_chan;
    3939    uint    minor_chan;
    40     uint    favorite;
    4140    uint    mplexid;
    4241    bool    visible;
    4342    QString name;
  • libs/libmythtv/libmythtv.pro

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/libmythtv.pro mythtv/libs/libmythtv/libmythtv.pro
    old new HEADERS += playgroup.h prog  
    163163HEADERS += channelsettings.h        previewgenerator.h
    164164HEADERS += transporteditor.h
    165165HEADERS += myth_imgconvert.h
     166HEADERS += channelgroup.h           channelgroupsettings.h
    166167
    167168# Remove when everything is switched to MythUI
    168169HEADERS += proglist_qt.h
    SOURCES += livetvchain.cpp play  
    186187SOURCES += progdetails.cpp
    187188SOURCES += channelsettings.cpp      previewgenerator.cpp
    188189SOURCES += transporteditor.cpp
     190SOURCES += channelgroup.cpp         channelgroupsettings.cpp
    189191
    190192contains( CONFIG_SWSCALE, yes ) {
    191193    SOURCES += myth_imgconvert.cpp
  • libs/libmythtv/remoteencoder.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/remoteencoder.cpp mythtv/libs/libmythtv/remoteencoder.cpp
    old new QString RemoteEncoder::SetInput(QString  
    402402    return (lastinput.isEmpty()) ? "Error" : lastinput;
    403403}
    404404
    405 void RemoteEncoder::ToggleChannelFavorite(void)
     405void RemoteEncoder::ToggleChannelFavorite(QString changroupname)
    406406{
    407407    QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) );
    408408    strlist << "TOGGLE_CHANNEL_FAVORITE";
     409    strlist << changroupname;
    409410
    410411    SendReceiveStringList(strlist);
    411412}
  • libs/libmythtv/remoteencoder.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/remoteencoder.h mythtv/libs/libmythtv/remoteencoder.h
    old new class MPUBLIC RemoteEncoder  
    5050        PictureAdjustType type, PictureAttribute attr, bool up);
    5151    void ChangeChannel(int channeldirection);
    5252    void ChangeDeinterlacer(int deint_mode);
    53     void ToggleChannelFavorite(void);
     53    void ToggleChannelFavorite(QString);
    5454    void SetChannel(QString channel);
    5555    int  SetSignalMonitoringRate(int msec, bool notifyFrontend = true);
    5656    uint GetSignalLockTimeout(QString input);
  • libs/libmythtv/tvosdmenuentry.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/tvosdmenuentry.cpp mythtv/libs/libmythtv/tvosdmenuentry.cpp
    old new void TVOSDMenuEntryList::InitDefaultEntr  
    202202    curMenuEntries.append(
    203203        new TVOSDMenuEntry("JUMPREC",                 1,  1,  1,  0, "List of Recorded Shows"));
    204204    curMenuEntries.append(
     205        new TVOSDMenuEntry("CHANNELGROUP",            1,  1,  0,  0, "Channel Groups"));
     206    curMenuEntries.append(
    205207        new TVOSDMenuEntry("TOGGLEBROWSE",     1,  -1,  -1,  -1, "Live TV Browse Mode"));
    206208    curMenuEntries.append(
    207209        new TVOSDMenuEntry("PREVCHAN",              1,  -1,  -1,  -1, "Previous TV Channel"));
  • libs/libmythtv/tv_play.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/tv_play.cpp mythtv/libs/libmythtv/tv_play.cpp
    old new bool TV::StartTV(ProgramInfo *tvrec, boo  
    357357
    358358    bool allowrerecord = tv->getAllowRerecord();
    359359    bool deleterecording = tv->getRequestDelete();
     360   
     361    tv->SaveChannelGroup();
    360362
    361363    delete tv;
    362364
    void TV::InitKeys(void)  
    436438            "in the program guide", "0");
    437439    REG_KEY("TV Frontend", "GUIDE", "Show the Program Guide", "S");
    438440    REG_KEY("TV Frontend", "FINDER", "Show the Program Finder", "#");
    439     REG_KEY("TV Frontend", "NEXTFAV", "Toggle showing all channels or just "
    440             "favorites in the program guide.", "/");
     441    REG_KEY("TV Frontend", "NEXTFAV", "Cycle through channel groups and all channels "
     442            "in the program guide.", "/,S");
    441443    REG_KEY("TV Frontend", "CHANUPDATE", "Switch channels without exiting "
    442444            "guide in Live TV mode.", "X");
    443445    REG_KEY("TV Frontend", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down");
    bool TV::Init(bool createWindow)  
    803805    osd_general_timeout  = gContext->GetNumSetting("OSDGeneralTimeout", 2);
    804806    osd_prog_info_timeout= gContext->GetNumSetting("OSDProgramInfoTimeout", 3);
    805807    tryUnflaggedSkip     = gContext->GetNumSetting("TryUnflaggedSkip", 0);
     808    channel_group_id     = gContext->GetNumSetting("ChannelGroupDefault", -1);
     809    browse_changrp       = gContext->GetNumSetting("BrowseChannelGroup", 0);
    806810    smartForward         = gContext->GetNumSetting("SmartForward", 0);
    807811    stickykeys           = gContext->GetNumSetting("StickyKeys");
    808812    ff_rew_repos         = gContext->GetNumSetting("FFRewReposTime", 100)/100.0;
    bool TV::Init(bool createWindow)  
    817821    if (!feVBI.isEmpty())
    818822        vbimode = VBIMode::Parse(gContext->GetSetting(feVBI));
    819823
     824    channel_group_id     = gContext->GetNumSetting("ChannelGroupDefault", -1);
     825    browse_changrp       = gContext->GetNumSetting("BrowseChannelGroup", 0);
     826   
     827    if (browse_changrp && (channel_group_id > -1))
     828    {
     829      m_channellist = ChannelUtil::GetChannels(0, true, "channum, callsign", channel_group_id);
     830      ChannelUtil::SortChannels(m_channellist, "channum", true);
     831    }
     832   
     833    m_changrplist  = ChannelGroup::GetChannelGroups();
     834
    820835    if (createWindow)
    821836    {
    822837        bool fullscreen = !gContext->GetNumSetting("GuiSizeForTV", 0);
    TV::~TV(void)  
    976991}
    977992
    978993/**
     994 * \brief save channel group setting to database
     995 */
     996void TV::SaveChannelGroup(void)
     997{
     998    int remember_last_changrp = gContext->GetNumSetting("ChannelGroupRememberLast", 0);
     999
     1000    if (remember_last_changrp)
     1001       gContext->SaveSetting("ChannelGroupDefault", channel_group_id);
     1002}
     1003
     1004/**
    9791005 * \brief get tv state of active player context
    9801006 */
    9811007TVState TV::GetState(int player_idx) const
    bool TV::ToggleHandleAction(PlayerContex  
    43024328        ToggleSleepTimer(ctx);
    43034329    else if (has_action("TOGGLERECORD", actions) && islivetv)
    43044330        ToggleRecord(ctx);
    4305     else if (has_action("TOGGLEFAV", actions) && islivetv)
    4306         ToggleChannelFavorite(ctx);
     4331//    else if (has_action("TOGGLEFAV", actions) && islivetv)
     4332//        ToggleChannelFavorite(ctx);
    43074333    else if (has_action("TOGGLECHANCONTROLS", actions) && islivetv)
    43084334        DoTogglePictureAttribute(ctx, kAdjustingPicture_Channel);
    43094335    else if (has_action("TOGGLERECCONTROLS", actions) && islivetv)
    void TV::ToggleInputs(PlayerContext *ctx  
    62786304    UpdateOSDInput(ctx, inputname);
    62796305}
    62806306
    6281 void TV::ToggleChannelFavorite(PlayerContext *ctx)
     6307void TV::ToggleChannelFavorite(PlayerContext *ctx, QString changroup_name)
    62826308{
    62836309    if (ctx->recorder)
    6284         ctx->recorder->ToggleChannelFavorite();
     6310        ctx->recorder->ToggleChannelFavorite(changroup_name);
    62856311}
    62866312
    62876313QString TV::GetQueuedInput(void) const
    void TV::ChangeChannel(PlayerContext *ct  
    65366562{
    65376563    bool muted = false;
    65386564
     6565    if ((browse_changrp || (direction == CHANNEL_DIRECTION_FAVORITE)) &&
     6566        (channel_group_id > -1) && (direction != CHANNEL_DIRECTION_SAME))
     6567    {
     6568       uint    chanid;
     6569
     6570       ctx->LockPlayingInfo(__FILE__, __LINE__);
     6571       if (!ctx->playingInfo)
     6572       {
     6573           VERBOSE(VB_IMPORTANT,
     6574                   LOC_ERR + "ChangeChannel(): no active ctx playingInfo.");
     6575           ctx->UnlockPlayingInfo(__FILE__, __LINE__);
     6576           ReturnPlayerLock(ctx);
     6577           return;
     6578       }
     6579
     6580       // Collect channel info
     6581       const ProgramInfo pginfo(*ctx->playingInfo);
     6582       uint    old_chanid  = pginfo.chanid.toUInt();
     6583       ctx->UnlockPlayingInfo(__FILE__, __LINE__);
     6584     
     6585       chanid = ChannelUtil::GetNextChannel(m_channellist, old_chanid, 0, direction);
     6586
     6587       ChangeChannel(ctx, chanid, "");     
     6588       return;
     6589    } else if (direction == CHANNEL_DIRECTION_FAVORITE)
     6590        direction = CHANNEL_DIRECTION_UP;
     6591
    65396592    QString oldinputname = ctx->recorder->GetInput();
    65406593
    65416594    ctx->LockDeleteNVP(__FILE__, __LINE__);
    void TV::DoEditSchedule(int editType)  
    76587711    const ProgramInfo pginfo(*actx->playingInfo);
    76597712    uint    chanid  = pginfo.chanid.toUInt();
    76607713    QString channum = pginfo.chanstr;
     7714    int changrpid   = channel_group_id;
    76617715    actx->UnlockPlayingInfo(__FILE__, __LINE__);
    76627716
    76637717    ClearOSD(actx);
    void TV::DoEditSchedule(int editType)  
    77167770        case kScheduleProgramGuide:
    77177771        {
    77187772            isEmbedded = (isLiveTV && !pause_active && allowEmbedding);
    7719             RunProgramGuidePtr(chanid, channum, this, isEmbedded, true);
     7773            RunProgramGuidePtr(chanid, channum, this, isEmbedded, true, changrpid);
    77207774            ignoreKeyPresses = true;
    77217775            break;
    77227776        }
    void TV::DoEditSchedule(int editType)  
    77697823        actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
    77707824        StopEmbedding(actx);               // Undo any embedding
    77717825        DoSetPauseState(actx, saved_pause); // Restore pause states
     7826
    77727827        // If user selected a new channel in the EPG, change to that channel
    77737828        if (isLiveTV && changeChannel.size())
    77747829            ChangeChannel(actx, changeChannel);
    void TV::BrowseDispInfo(PlayerContext *c  
    86658720    if (!browsemode)
    86668721        BrowseStart(ctx);
    86678722
     8723    // if browsing channel groups is enabled or direction if BROWSE_FAVORITES
     8724    // Then pick the next channel in the channel group list to browse
     8725    // If channel group is ALL CHANNELS (-1), then bypass picking from
     8726    // the channel group list
     8727    if ((browse_changrp || (direction == BROWSE_FAVORITE)) &&
     8728        (channel_group_id > -1) && (direction != BROWSE_SAME) &&
     8729        (direction != BROWSE_RIGHT) && (direction != BROWSE_LEFT))
     8730    {
     8731      uint chanid;
     8732      int  dir;
     8733     
     8734      if ( (direction == BROWSE_UP) || (direction == BROWSE_FAVORITE) )
     8735        dir = CHANNEL_DIRECTION_UP;
     8736      else if (direction == BROWSE_DOWN)
     8737        dir = CHANNEL_DIRECTION_DOWN;
     8738      else // this should never happen, but just in case
     8739        dir = direction;
     8740       
     8741      chanid = ChannelUtil::GetNextChannel(m_channellist, browsechanid, 0, dir);
     8742      VERBOSE(VB_IMPORTANT, QString("Get channel: %1").arg(chanid));
     8743      browsechanid  = chanid;
     8744      browsechannum = QString::null;
     8745      direction     = BROWSE_SAME;
     8746    }
     8747    else if ((channel_group_id == -1) && (direction == BROWSE_FAVORITE))
     8748      direction = BROWSE_UP;
     8749     
    86688750    OSD *osd = GetOSDLock(ctx);
    86698751    if (ctx->paused || !osd)
    86708752    {
    void TV::TreeMenuSelected(OSDListTreeTyp  
    95689650    }
    95699651    else if (action == "GUIDE")
    95709652        EditSchedule(actx, kScheduleProgramGuide);
     9653    else if (action.left(10) == "CHANGROUP_")
     9654    {
     9655        if (action == "CHANGROUP_ALL_CHANNELS")
     9656           channel_group_id = -1;
     9657        else
     9658        {
     9659           action.remove("CHANGROUP_");
     9660           channel_group_id = action.toInt();
     9661         
     9662           if (browse_changrp)
     9663           {
     9664               m_channellist = ChannelUtil::GetChannels(0, true, "channum, callsign", channel_group_id);
     9665               ChannelUtil::SortChannels(m_channellist, "channum", true);
     9666           }
     9667        }
     9668    }
    95719669    else if (action == "FINDER")
    95729670        EditSchedule(actx, kScheduleProgramFinder);
    95739671    else if (action == "SCHEDULE")
    void TV::FillOSDTreeMenu(  
    97659863        if (lastProgram != NULL)
    97669864            new OSDGenericTree(jtp_item, lastProgram->title, "JUMPPREV");
    97679865    }
     9866    else if (category == "CHANNELGROUP")
     9867    {
     9868        FillMenuChanGroups(ctx, treeMenu);
     9869    }
    97689870    else if (category == "TOGGLEBROWSE")
    97699871    {
    97709872        if (!db_browse_always)
    void TV::FillOSDTreeMenu(  
    98199921        FillMenuSleepMode(ctx, treeMenu);
    98209922}
    98219923
     9924void TV::FillMenuChanGroups(
     9925    const PlayerContext *ctx, OSDGenericTree *treeMenu) const
     9926{
     9927    OSDGenericTree *cg_item = new OSDGenericTree(treeMenu, tr("Channel Groups"),
     9928                                                 "CHANGROUP");
     9929    new OSDGenericTree(cg_item, tr("All Channels"), "CHANGROUP_ALL_CHANNELS",
     9930                                (channel_group_id == -1) ? 1 : 0,
     9931                                NULL, "CHANNELGROUP");
     9932       
     9933    ChannelGroupList::const_iterator it;
     9934       
     9935    for (it = m_changrplist.begin(); it != m_changrplist.end(); ++it)
     9936    {
     9937        QString name = QString("CHANGROUP_%1").arg(it->grpid);
     9938        new OSDGenericTree(cg_item, it->name, name,
     9939                           ((int)(it->grpid) == channel_group_id) ? 1 : 0,
     9940                           NULL, "CHANNELGROUP");
     9941    }
     9942}
     9943
    98229944void TV::FillMenuPlaying(
    98239945    const PlayerContext *ctx, OSDGenericTree *treeMenu,
    98249946    QString category) const
  • libs/libmythtv/tv_play.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/tv_play.h mythtv/libs/libmythtv/tv_play.h
    old new  
    2525#include "videoouttypes.h"
    2626#include "volumebase.h"
    2727#include "inputinfo.h"
     28#include "channelgroup.h"
    2829
    2930#include <qobject.h>
    3031
    typedef QMap<QString,InfoMap> DDValue  
    5253typedef QMap<QString,DDValueMap> DDKeyMap;
    5354typedef ProgramInfo * (*EMBEDRETURNPROGRAM)(void *, bool);
    5455typedef void (*EMBEDRETURNVOID) (void *, bool);
    55 typedef void (*EMBEDRETURNVOIDEPG) (uint, const QString &, TV *, bool, bool);
     56typedef void (*EMBEDRETURNVOIDEPG) (uint, const QString &, TV *, bool, bool, int);
    5657typedef void (*EMBEDRETURNVOIDFINDER) (TV *, bool, bool);
    5758
    5859// Locking order
    class MPUBLIC TV : public QThread  
    276277    bool HasUDPNotifyEvent(void) const;
    277278    void HandleUDPNotifyEvent(void);
    278279
     280    // Channel Groups
     281    void SaveChannelGroup(void);
     282
    279283  public slots:
    280284    void HandleOSDClosed(int osdType);
    281285    void timerEvent(QTimerEvent*);
    class MPUBLIC TV : public QThread  
    346350    void StopStuff(PlayerContext *mctx, PlayerContext *ctx,
    347351                   bool stopRingbuffers, bool stopPlayers, bool stopRecorders);
    348352
    349     void ToggleChannelFavorite(PlayerContext*);
     353    void ToggleChannelFavorite(PlayerContext*, QString);
    350354    void ChangeChannel(PlayerContext*, int direction);
    351355    void ChangeChannel(PlayerContext*, uint chanid, const QString &channum);
    352356    void PauseLiveTV(PlayerContext*);
    class MPUBLIC TV : public QThread  
    527531    void FillMenuTimeStretch(   const PlayerContext*, OSDGenericTree*) const;
    528532    void FillMenuSleepMode(     const PlayerContext*, OSDGenericTree*) const;
    529533    bool FillMenuTracks(        const PlayerContext*, OSDGenericTree*, uint type) const;
     534    void FillMenuChanGroups(    const PlayerContext *ctx, OSDGenericTree *treeMenu) const;
    530535
    531536    void UpdateLCD(void);
    532537    bool HandleLCDTimerEvent(void);
    class MPUBLIC TV : public QThread  
    762767    QMap<int,int>             recorderPlaybackInfoTimerId;
    763768    QMap<int,ProgramInfo>     recorderPlaybackInfo;
    764769
     770    // Channel favorite group stuff   
     771    int channel_group_id;
     772    uint browse_changrp;
     773    ChannelGroupList m_changrplist;
     774    DBChanList m_channellist;
     775
    765776    // Network Control stuff
    766777    MythDeque<QString> networkControlCommands;
    767778
  • libs/libmythtv/tv_rec.cpp

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/tv_rec.cpp mythtv/libs/libmythtv/tv_rec.cpp
    old new using namespace std;  
    5959#include "iptvrecorder.h"
    6060#include "firewirerecorder.h"
    6161
     62#include "channelgroup.h"
     63
    6264#ifdef USING_V4L
    6365#include "v4lchannel.h"
    6466#endif
    void TVRec::RecorderPaused(void)  
    29152917/** \fn TVRec::ToggleChannelFavorite()
    29162918 *  \brief Toggles whether the current channel should be on our favorites list.
    29172919 */
    2918 void TVRec::ToggleChannelFavorite(void)
     2920void TVRec::ToggleChannelFavorite(QString changroupname)
    29192921{
    29202922    QMutexLocker lock(&stateChangeLock);
    29212923
    void TVRec::ToggleChannelFavorite(void)  
    29352937                "\t\t\tCould not toggle favorite.").arg(channum));
    29362938        return;
    29372939    }
    2938 
    2939     // Check if favorite exists for that chanid...
    2940     MSqlQuery query(MSqlQuery::InitCon());
    2941     query.prepare(
    2942         "SELECT favorites.favid "
    2943         "FROM favorites "
    2944         "WHERE favorites.chanid = :CHANID "
    2945         "LIMIT 1");
    2946     query.bindValue(":CHANID", chanid);
    2947 
    2948     if (!query.exec() || !query.isActive())
    2949     {
    2950         MythDB::DBError("togglechannelfavorite", query);
    2951     }
    2952     else if (query.size() > 0)
    2953     {
    2954         // We have a favorites record...Remove it to toggle...
    2955         query.next();
    2956         QString favid = query.value(0).toString();
    2957         query.prepare(
    2958             QString("DELETE FROM favorites "
    2959                     "WHERE favid = '%1'").arg(favid));
    2960         query.exec();
    2961         VERBOSE(VB_RECORD, LOC + "Removing Favorite.");
    2962     }
     2940   
     2941    int  changrpid;
     2942    bool result;
     2943   
     2944    changrpid = ChannelGroup::GetChannelGroupId(changroupname);
     2945   
     2946    if (changrpid <1)
     2947    {
     2948          VERBOSE(VB_RECORD, LOC + QString("ToggleChannelFavorite: Invalid "
     2949                   "channel group name %1, ").arg(changroupname));
     2950    }   
    29632951    else
    29642952    {
    2965         // We have no favorites record...Add one to toggle...
    2966         query.prepare(
    2967             QString("INSERT INTO favorites (chanid) "
    2968                     "VALUES ('%1')").arg(chanid));
    2969         query.exec();
    2970         VERBOSE(VB_RECORD, LOC + "Adding Favorite.");
     2953        result = ChannelGroup::ToggleChannel(chanid, changrpid, true);
     2954
     2955        if (!result)
     2956           VERBOSE(VB_RECORD, LOC + "Unable to toggle channel favorite.");
     2957        else
     2958           VERBOSE(VB_RECORD, LOC + QString("Toggled channel favorite."
     2959                   "channum %1, chan group %2").arg(channum).arg(changroupname));
    29712960    }
    29722961}
    29732962
  • libs/libmythtv/tv_rec.h

    diff -Naurp -x '*.orig' mythtv-orig/libs/libmythtv/tv_rec.h mythtv/libs/libmythtv/tv_rec.h
    old new class MPUBLIC TVRec : public SignalMonit  
    203203    QString GetChainID(void);
    204204    void StopLiveTV(void);
    205205    void PauseRecorder(void);
    206     void ToggleChannelFavorite(void);
     206    void ToggleChannelFavorite(QString);
    207207
    208208    void SetLiveRecording(int recording);
    209209
  • programs/mythbackend/encoderlink.cpp

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythbackend/encoderlink.cpp mythtv/programs/mythbackend/encoderlink.cpp
    old new QString EncoderLink::SetInput(QString in  
    728728 *         <b>This only works on local recorders.</b>
    729729 *  \return -1 if query does not succeed, otherwise.
    730730 */
    731 void EncoderLink::ToggleChannelFavorite(void)
     731void EncoderLink::ToggleChannelFavorite(QString changroup)
    732732{
    733733    if (local)
    734         tv->ToggleChannelFavorite();
     734        tv->ToggleChannelFavorite(changroup);
    735735    else
    736736        VERBOSE(VB_IMPORTANT, "Should be local only query: ToggleChannelFavorite");
    737737}
  • programs/mythbackend/encoderlink.h

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythbackend/encoderlink.h mythtv/programs/mythbackend/encoderlink.h
    old new class EncoderLink  
    111111    vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards) const;
    112112    QString GetInput(void) const;
    113113    QString SetInput(QString);
    114     void ToggleChannelFavorite(void);
     114    void ToggleChannelFavorite(QString);
    115115    void ChangeChannel(int channeldirection);
    116116    void SetChannel(const QString &name);
    117117    int  GetPictureAttribute(PictureAttribute attr);
  • programs/mythbackend/mainserver.cpp

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythbackend/mainserver.cpp mythtv/programs/mythbackend/mainserver.cpp
    old new void MainServer::HandleRecorderQuery(QSt  
    32593259    }
    32603260    else if (command == "TOGGLE_CHANNEL_FAVORITE")
    32613261    {
    3262         enc->ToggleChannelFavorite();
     3262        QString changroup = slist[2];
     3263        enc->ToggleChannelFavorite(changroup);
    32633264        retlist << "ok";
    32643265    }
    32653266    else if (command == "CHANGE_CHANNEL")
  • programs/mythfrontend/globalsettings.cpp

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythfrontend/globalsettings.cpp mythtv/programs/mythfrontend/globalsettings.cpp
    old new static HostCheckBox *EPGShowChannelIcon(  
    31213121    return gc;
    31223122}
    31233123
    3124 static HostCheckBox *EPGShowFavorites()
    3125 {
    3126     HostCheckBox *gc = new HostCheckBox("EPGShowFavorites");
    3127     gc->setLabel(QObject::tr("Only display 'favorite' channels"));
    3128     gc->setHelpText(QObject::tr("If enabled, the EPG will initially display "
    3129                     "only the channels marked as favorites. Pressing "
    3130                     "\"4\" will toggle between displaying favorites and all "
    3131                     "channels."));
    3132     gc->setValue(false);
    3133     return gc;
    3134 }
    31353124
    31363125static GlobalCheckBox *EPGEnableJumpToChannel()
    31373126{
    static GlobalCheckBox *EPGEnableJumpToCh  
    31433132    return gc;
    31443133}
    31453134
     3135static HostCheckBox *ChannelGroupRememberLast()
     3136{
     3137    HostCheckBox *gc = new HostCheckBox("ChannelGroupRememberLast");
     3138    gc->setLabel(QObject::tr("Remember last channel group"));
     3139    gc->setHelpText(QObject::tr("If enabled, the EPG will initially display "
     3140                    "only the channels from the last channel group selected. Pressing "
     3141                    "\"4\" will toggle channel group."));
     3142    gc->setValue(false);
     3143    return gc;
     3144}
     3145
     3146static HostComboBox *ChannelGroupDefault()
     3147{
     3148    HostComboBox *gc = new HostComboBox("ChannelGroupDefault");
     3149    gc->setLabel(QObject::tr("Default channel group"));
     3150
     3151    ChannelGroupList changrplist;
     3152
     3153    changrplist = ChannelGroup::GetChannelGroups();
     3154
     3155    gc->addSelection(QObject::tr("All Channels"), "-1");
     3156
     3157    ChannelGroupList::iterator it;
     3158
     3159    for (it = changrplist.begin(); it < changrplist.end(); ++it)
     3160       gc->addSelection(it->name, QString("%1").arg(it->grpid));
     3161
     3162    gc->setHelpText(QObject::tr("Default channel group to be shown in the the EPG"
     3163                    "Pressing GUIDE key will toggle channel group."));
     3164    gc->setValue(false);
     3165    return gc;
     3166}
     3167
     3168static HostCheckBox *BrowseChannelGroup()
     3169{
     3170    HostCheckBox *gc = new HostCheckBox("BrowseChannelGroup");
     3171    gc->setLabel(QObject::tr("Browse/Change channels from Channel Group"));
     3172    gc->setHelpText(QObject::tr("If enabled, LiveTV will browse or change channels "
     3173                    "from the selected channel group. \"All Channels\" "
     3174                    "channel group may be selected to browse all channels."));
     3175    gc->setValue(false);
     3176    return gc;
     3177}
     3178
     3179// Channel Group Settings
     3180class ChannelGroupSettings : public TriggeredConfigurationGroup
     3181{
     3182  public:
     3183    ChannelGroupSettings() : TriggeredConfigurationGroup(false, true, false, false)
     3184    {
     3185         setLabel(QObject::tr("Remember last channel group"));
     3186         setUseLabel(false);
     3187
     3188         Setting* RememberChanGrpEnabled = ChannelGroupRememberLast();
     3189         addChild(RememberChanGrpEnabled);
     3190         setTrigger(RememberChanGrpEnabled);
     3191
     3192         ConfigurationGroup* settings = new VerticalConfigurationGroup(false,false);
     3193         settings->addChild(ChannelGroupDefault());
     3194         addTarget("0", settings);
     3195
     3196         // show nothing if RememberChanGrpEnabled is on
     3197         addTarget("1", new VerticalConfigurationGroup(true,false));
     3198     };
     3199};
     3200
    31463201// General RecPriorities settings
    31473202
    31483203static GlobalCheckBox *GRSchedMoveHigher()
    GeneralSettings::GeneralSettings()  
    49094964    general2->addChild(RecordOverTime());
    49104965    general2->addChild(CategoryOverTimeSettings());
    49114966    addChild(general2);
    4912 
     4967   
     4968    VerticalConfigurationGroup* changrp = new VerticalConfigurationGroup(false);
     4969    changrp->setLabel(QObject::tr("General (Channel Groups)"));
     4970    ChannelGroupSettings *changroupsettings = new ChannelGroupSettings();
     4971    changrp->addChild(changroupsettings);
     4972    changrp->addChild(BrowseChannelGroup());
     4973    addChild(changrp);
    49134974}
    49144975
    49154976EPGSettings::EPGSettings()
    EPGSettings::EPGSettings()  
    49194980    epg->addChild(EPGShowCategoryColors());
    49204981    epg->addChild(EPGShowCategoryText());
    49214982    epg->addChild(EPGShowChannelIcon());
    4922     epg->addChild(EPGShowFavorites());
    49234983    epg->addChild(WatchTVGuide());
    49244984    addChild(epg);
    49254985
  • programs/mythfrontend/guidegrid.cpp

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythfrontend/guidegrid.cpp mythtv/programs/mythfrontend/guidegrid.cpp
    old new bool JumpToChannel::Update(void)  
    164164}
    165165
    166166void GuideGrid::RunProgramGuide(uint chanid, const QString &channum,
    167                     TV *player, bool embedVideo, bool allowFinder)
     167                    TV *player, bool embedVideo, bool allowFinder, int changrpid)
    168168{
    169169    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    170170    GuideGrid *gg = new GuideGrid(mainStack,
    171171                                  chanid, channum,
    172                                   player, embedVideo, allowFinder);
     172                                  player, embedVideo, allowFinder,
     173                                  changrpid);
    173174
    174175    if (gg->Create())
    175176        mainStack->AddScreen(gg, (player == NULL));
    void GuideGrid::RunProgramGuide(uint cha  
    180181GuideGrid::GuideGrid(MythScreenStack *parent,
    181182                     uint chanid, QString channum,
    182183                     TV *player, bool embedVideo,
    183                      bool allowFinder)
     184                     bool allowFinder, int changrpid)
    184185         : MythScreenType(parent, "guidegrid"),
    185186    m_allowFinder(allowFinder),
    186187    m_player(player),
    GuideGrid::GuideGrid(MythScreenStack *pa  
    196197    m_channelCount = 5;
    197198    m_timeCount = 30;
    198199    m_currentStartChannel = 0;
     200    m_changrpid = changrpid;
     201    m_changrplist = ChannelGroup::GetChannelGroups();
    199202
    200203    m_jumpToChannelEnabled = gContext->GetNumSetting("EPGEnableJumpToChannel", 1);
    201     m_showFavorites = gContext->GetNumSetting("EPGShowFavorites", 0);
    202204    m_sortReverse = gContext->GetNumSetting("EPGSortReverse", 0);
    203205    m_selectChangesChannel = gContext->GetNumSetting("SelectChangesChannel", 0);
    204206    m_selectRecThreshold = gContext->GetNumSetting("SelChangeRecThreshold", 16);
    bool GuideGrid::Create()  
    249251    UIUtilE::Assign(this, m_channelList, "channellist", &err);
    250252    UIUtilE::Assign(this, m_guideGrid, "guidegrid", &err);
    251253    UIUtilW::Assign(this, m_dateText, "datetext");
     254    UIUtilW::Assign(this, m_changroupname, "channelgroup");
    252255    UIUtilW::Assign(this, m_channelImage, "channelicon");
    253256    UIUtilW::Assign(this, m_jumpToText, "jumptotext");
    254257
    bool GuideGrid::Create()  
    291294
    292295    if (m_dateText)
    293296        m_dateText->SetText(m_currentStartTime.toString(m_dateFormat));
     297       
     298    QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
     299   
     300    if (m_changroupname)
     301        m_changroupname->SetText(changrpname);   
    294302
    295303    gContext->addListener(this);
    296304
    bool GuideGrid::keyPressEvent(QKeyEvent  
    471479        else if (action == "TOGGLERECORD")
    472480            quickRecord();
    473481        else if (action == "TOGGLEFAV")
    474             toggleChannelFavorite();
     482        {
     483            if (m_changrpid == -1)
     484                ChannelGroupMenu(0);
     485            else
     486                toggleChannelFavorite();
     487        }
    475488        else if (action == "CHANUPDATE")
    476489            channelUpdate();
    477490        else if (action == "VOLUMEUP")
    void GuideGrid::showMenu(void)  
    521534
    522535        menuPopup->AddButton(tr("Reverse Channel Order"));
    523536
    524         if (m_showFavorites)
    525             menuPopup->AddButton(tr("Show All Channels"));
    526         else
    527             menuPopup->AddButton(tr("Show Favourite Channels"));
     537        menuPopup->AddButton(tr("Choose Channel Group"));
    528538
    529539        menuPopup->AddButton(tr("Cancel"));
    530540
    void GuideGrid::fillChannelInfos(bool go  
    709719    m_channelInfoIdx.clear();
    710720    m_currentStartChannel = 0;
    711721
    712     DBChanList channels = ChannelUtil::GetChannels(0, true);
     722    DBChanList channels = ChannelUtil::GetChannels(0, true, "", m_changrpid);
    713723    ChannelUtil::SortChannels(channels, m_channelOrdering, false);
    714724
    715     if (m_showFavorites)
    716     {
    717         DBChanList tmp;
    718         for (uint i = 0; i < channels.size(); i++)
    719         {
    720             if (channels[i].favorite)
    721                 tmp.push_back(channels[i]);
    722         }
    723 
    724         if (!tmp.empty())
    725             channels = tmp;
    726     }
    727 
    728725    typedef vector<uint> uint_list_t;
    729726    QMap<QString,uint_list_t> channum_to_index_map;
    730727    QMap<QString,uint_list_t> callsign_to_index_map;
    void GuideGrid::customEvent(QEvent *even  
    12351232            }
    12361233            else if (resulttext == tr("Toggle Favourite Channel"))
    12371234            {
    1238                 toggleChannelFavorite();
     1235                if (m_changrpid == -1)
     1236                    ChannelGroupMenu(0);
     1237                else
     1238                    toggleChannelFavorite();
    12391239            }
    1240             else if (resulttext == tr("Show All Channels"))
     1240            else if (resulttext == tr("Choose Channel Group"))
    12411241            {
    1242                 m_showFavorites = false;
    1243                 generateListings();
    1244                 updateChannels();
     1242                ChannelGroupMenu(1);
    12451243            }
    1246             else if (resulttext == tr("Show Favourite Channels"))
     1244        }
     1245    else if (resultid == "channelgrouptogglemenu")
     1246        {
     1247            if (resulttext != tr("Cancel"))
    12471248            {
    1248                 m_showFavorites = true;
    1249                 generateListings();
    1250                 updateChannels();
     1249                int changroupid;
     1250                changroupid = ChannelGroup::GetChannelGroupId(resulttext);
     1251               
     1252                if (changroupid > 0)
     1253                    toggleChannelFavorite(changroupid);
     1254            }
     1255        }
     1256    else if (resultid == "channelgroupmenu")
     1257        {
     1258            if (resulttext != tr("Cancel"))
     1259            {
     1260                int changroupid;
     1261                changroupid = ChannelGroup::GetChannelGroupId(resulttext);
     1262             
     1263                if (changroupid > 0)
     1264                {
     1265                    m_changrpid = changroupid;
     1266                    generateListings();
     1267                    updateChannels();
     1268
     1269                    QString changrpname;
     1270                    changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
     1271   
     1272                    if (m_changroupname)
     1273                        m_changroupname->SetText(changrpname);
     1274                }
    12511275            }
    12521276        }
    12531277    }
    void GuideGrid::updateChannels(void)  
    13131337                m_channelList, chinfo->GetFormatted(m_channelFormat));
    13141338
    13151339        QString state = "";
    1316 
    1317         if (chinfo->favorite > 0)
    1318         {
    1319             if (unavailable)
    1320                 state = "favunavailable";
    1321             else
    1322                 state = "favourite";
    1323         }
    1324         else if (unavailable)
    1325             state = "unavailable";
    1326 
    13271340        item->SetText(chinfo->GetFormatted(m_channelFormat), "buttontext", state);
    13281341
    13291342        if (showChannelIcon && !chinfo->icon.isEmpty())
    void GuideGrid::updateInfo(void)  
    13801393
    13811394void GuideGrid::toggleGuideListing()
    13821395{
    1383     m_showFavorites = (!m_showFavorites);
    1384     generateListings();
     1396    int oldchangrpid = m_changrpid;
     1397   
     1398    m_changrpid = ChannelGroup::GetNextChannelGroup(m_changrplist, oldchangrpid);
     1399   
     1400    if (oldchangrpid != m_changrpid)
     1401      generateListings();
     1402
    13851403    updateChannels();
     1404   
     1405    QString changrpname = ChannelGroup::GetChannelGroupName(m_changrpid);
     1406   
     1407    if (m_changroupname)
     1408        m_changroupname->SetText(changrpname);
    13861409}
    13871410
    13881411void GuideGrid::generateListings()
    void GuideGrid::generateListings()  
    13991422    fillProgramInfos();
    14001423}
    14011424
    1402 void GuideGrid::toggleChannelFavorite()
     1425void GuideGrid::ChannelGroupMenu(int mode)
     1426{
     1427    if (m_changrplist.empty())
     1428    {
     1429      QString message = tr("You don't have any channel groups defined");
     1430
     1431      MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
     1432
     1433      MythConfirmationDialog *okPopup = new MythConfirmationDialog(popupStack,
     1434                                                                   message, false);
     1435      if (okPopup->Create())
     1436          popupStack->AddScreen(okPopup);
     1437      else
     1438          delete okPopup;
     1439
     1440      return;
     1441    }
     1442
     1443    QString label = tr("Select Channel Group");
     1444
     1445    MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
     1446    MythDialogBox *menuPopup = new MythDialogBox(label, popupStack, "menuPopup");
     1447
     1448    if (menuPopup->Create())
     1449    {
     1450        if (mode == 0)
     1451            menuPopup->SetReturnEvent(this, "channelgrouptogglemenu");
     1452        else
     1453            menuPopup->SetReturnEvent(this, "channelgroupmenu");           
     1454
     1455        for (uint i = 0; i < m_changrplist.size(); i++)
     1456            menuPopup->AddButton(m_changrplist[i].name);
     1457
     1458        menuPopup->AddButton(tr("Cancel"));
     1459
     1460        popupStack->AddScreen(menuPopup);
     1461    }
     1462    else
     1463    {
     1464        delete menuPopup;
     1465    }
     1466}
     1467
     1468void GuideGrid::toggleChannelFavorite(int grpid)
    14031469{
    14041470    MSqlQuery query(MSqlQuery::InitCon());
     1471   
     1472    if (grpid == -1)
     1473    {
     1474      if (m_changrpid == -1)
     1475          return;
     1476      else
     1477          grpid = m_changrpid;
     1478    }
    14051479
    14061480    // Get current channel id, and make sure it exists...
    14071481    int chanNum = m_currentRow + m_currentStartChannel;
    void GuideGrid::toggleChannelFavorite()  
    14131487        chanNum = 0;
    14141488
    14151489    PixmapChannel *ch = GetChannelInfo(chanNum);
    1416     uint favid  = ch->favorite;
    14171490    uint chanid = ch->chanid;
    14181491
    1419     if (favid > 0)
    1420     {
    1421         query.prepare("DELETE FROM favorites WHERE favid = :FAVID ;");
    1422         query.bindValue(":FAVID", favid);
    1423         query.exec();
    1424     }
     1492    if (m_changrpid == -1)
     1493        // If currently viewing all channels, allow to add only not delete
     1494        ChannelGroup::ToggleChannel(chanid, grpid, false);
    14251495    else
     1496        // Only allow delete if viewing the favorite group in question
     1497        ChannelGroup::ToggleChannel(chanid, grpid, true);
     1498     
     1499    // If viewing favorites, refresh because a channel was removed
     1500    if (m_changrpid != -1)   
    14261501    {
    1427         // We have no favorites record...Add one to toggle...
    1428         query.prepare("INSERT INTO favorites (chanid) VALUES (:FAVID);");
    1429         query.bindValue(":FAVID", chanid);
    1430         query.exec();
    1431     }
    1432 
    1433     if (m_showFavorites)
    14341502        generateListings();
    1435     else
    1436     {
    1437         int maxchannel = 0;
    1438         m_channelCount = m_guideGrid->getChannelCount();
    1439         fillChannelInfos(false);
    1440         maxchannel = max((int)GetChannelCount() - 1, 0);
    1441         m_channelCount = min(m_channelCount, maxchannel + 1);
    14421503        updateChannels();
    14431504    }
    14441505}
  • programs/mythfrontend/guidegrid.h

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythfrontend/guidegrid.h mythtv/programs/mythfrontend/guidegrid.h
    old new  
    1414#include "mythscreentype.h"
    1515#include "programinfo.h"
    1616#include "programlist.h"
     17#include "channelgroup.h"
    1718#include "channelutil.h"
    1819
    1920using namespace std;
    class MPUBLIC GuideGrid : public MythScr  
    8182                                const QString &startChanNum,
    8283                                TV            *player = NULL,
    8384                                bool           embedVideo = false,
    84                                 bool           allowFinder = true);
     85                                bool           allowFinder = true,
     86                                int            changrpid = -1);
    8587
    8688    DBChanList GetSelection(void) const;
    8789
    class MPUBLIC GuideGrid : public MythScr  
    112114    void pageDown();
    113115    void pageUp();
    114116    void toggleGuideListing();
    115     void toggleChannelFavorite();
     117    void toggleChannelFavorite(int grpid = -1);
     118    void ChannelGroupMenu(int mode = 0);
    116119    void generateListings();
    117120
    118121    void enter();
    class MPUBLIC GuideGrid : public MythScr  
    137140    GuideGrid(MythScreenStack *parentStack,
    138141              uint chanid = 0, QString channum = "",
    139142              TV *player = NULL, bool embedVideo = false,
    140               bool allowFinder = true);
     143              bool allowFinder = true,
     144              int changrpid=-1);
    141145   ~GuideGrid();
    142146
    143147  private slots:
    class MPUBLIC GuideGrid : public MythScr  
    190194    int m_currentRow;
    191195    int m_currentCol;
    192196
    193     bool    m_showFavorites;
    194197    bool    m_sortReverse;
    195198    QString m_channelFormat;
    196199
    class MPUBLIC GuideGrid : public MythScr  
    217220
    218221    QTimer *m_updateTimer;
    219222
     223    int               m_changrpid;
     224    ChannelGroupList  m_changrplist;
     225
    220226    QMutex            m_jumpToChannelLock;
    221227    JumpToChannel    *m_jumpToChannel;
    222228    bool              m_jumpToChannelEnabled;
    class MPUBLIC GuideGrid : public MythScr  
    226232    MythUIGuideGrid  *m_guideGrid;
    227233    MythUIText       *m_dateText;
    228234    MythUIText       *m_jumpToText;
     235    MythUIText       *m_changroupname;
    229236    MythUIImage      *m_channelImage;
    230237};
    231238
  • programs/mythfrontend/main.cpp

    diff -Naurp -x '*.orig' mythtv-orig/programs/mythfrontend/main.cpp mythtv/programs/mythfrontend/main.cpp
    old new using namespace std;  
    5151#include "lcddevice.h"
    5252#include "langsettings.h"
    5353#include "mythcommandlineparser.h"
     54#include "channelgroupsettings.h"
    5455
    5556#include "myththemedmenu.h"
    5657#include "myththemebase.h"
    void TVMenuCallback(void *data, QString  
    523524        EPGSettings settings;
    524525        settings.exec();
    525526    }
     527    else if (sel == "settings channelgroups")
     528    {
     529        ChannelGroupEditor editor;
     530        editor.exec();
     531    }
    526532    else if (sel == "settings generalrecpriorities")
    527533    {
    528534        GeneralRecPrioritiesSettings settings;
  • themes/classic/tv_settings.xml

    diff -Naurp -x '*.orig' mythtv-orig/themes/classic/tv_settings.xml mythtv/themes/classic/tv_settings.xml
    old new  
    9999    </button>
    100100
    101101    <button>
     102      <type>TV_SETTINGS_CHANNEL_GROUP</type>
     103      <text>Channel Groups</text>
     104      <action>SETTINGS CHANNELGROUPS</action>
     105    </button>
     106
     107    <button>
    102108        <type>TV_SETTINGS_RECORDING_PROFILES</type>
    103109        <text>Recording Profiles</text>
    104110        <text lang="IT">Registrazione</text>
  • themes/defaultmenu/tv_settings.xml

    diff -Naurp -x '*.orig' mythtv-orig/themes/defaultmenu/tv_settings.xml mythtv/themes/defaultmenu/tv_settings.xml
    old new  
    123123    </button>
    124124
    125125    <button>
     126      <type>TV_SETTINGS_CHANNEL_GROUP</type>
     127      <text>Channel Groups</text>
     128      <action>SETTINGS CHANNELGROUPS</action>
     129    </button>
     130
     131    <button>
    126132        <type>TV_SETTINGS_RECORDING_PROFILES</type>
    127133        <text>Recording Profiles</text>
    128134        <text lang="IT">Registrazioni</text>
  • themes/default-wide/schedule-ui.xml

    diff -Naurp -x '*.orig' mythtv-orig/themes/default-wide/schedule-ui.xml mythtv/themes/default-wide/schedule-ui.xml
    old new  
    3737            <cornerradius>15</cornerradius>
    3838        </shape>
    3939
     40        <textarea name="channelgroup" from="basetextarea">
     41            <area>25,245,190,25</area>
     42            <align>allcenter</align>
     43        </textarea>
     44
    4045        <textarea name="datetext" from="basetextarea">
    41             <area>25,255,190,25</area>
     46            <area>25,265,190,25</area>
    4247            <align>allcenter</align>
    4348        </textarea>
    4449
     
    255260        </imagetype>
    256261       
    257262        <textarea name="datetext" from="basetextarea">
    258             <area>25,255,190,25</area>
     263            <area>25,265,190,25</area>
     264            <align>allcenter</align>
     265        </textarea>
     266
     267        <textarea name="channelgroup" from="basetextarea">
     268            <area>25,245,190,25</area>
    259269            <align>allcenter</align>
    260270        </textarea>
    261271
  • themes/DVR/tv_settings.xml

    diff -Naurp -x '*.orig' mythtv-orig/themes/DVR/tv_settings.xml mythtv/themes/DVR/tv_settings.xml
    old new  
    9999    </button>
    100100
    101101    <button>
     102      <type>TV_SETTINGS_CHANNEL_GROUP</type>
     103      <text>Channel Groups</text>
     104      <action>SETTINGS CHANNELGROUPS</action>
     105    </button>
     106
     107    <button>
    102108        <type>TV_SETTINGS_RECORDING_PROFILES</type>
    103109        <text>Recording Profiles</text>
    104110        <text lang="IT">Registrazione</text>