[mythtv] [PATCH] Jump to channel in EPG

Jason Parekh jasonparekh at gmail.com
Wed Jun 23 21:46:15 EDT 2004


This implements the channel jumping feature that is missing from
MythTV..  It allows you to enter channels in the guide and directly
jump (the selection) to that channel.  By default, it is off.  You can
turn it on in the TV -> Guide settings.

The way this works is if you enter a digit, it will set a timer for
2.5 seconds and enter jump to channel mode where as you enter digits,
it will find the closest matching channel and show that on the program
guide.  Within the 2.5 seconds, if you press the button bound to END,
it will cancel channel jump mode and revert to the highlighted channel
before entering this mode.  If you let the timer expire, it will stay
on the selected channel. The positioning for the channel display can
be in either one of two ways.  To ensure compatibility with themes, I
made it so if it can't find a specific jumptochannel container, it
will use the date's and just overwrite the date whenever it is in
channel jump mode.  However, if there is a jumptochannel container, it
will use that.  An example container is as follows:

     <container name="jumptochannel">
     <area>20,20,115,25</area>
     <textarea name="channel" draworder="4" align="right">
         <font>info</font>
         <area>0,0,115,25</area>
         <cutdown>no</cutdown>
     </textarea>
     </container>

Jason
-------------- next part --------------
Index: mythtv/libs/libmythtv/guidegrid.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/guidegrid.cpp,v
retrieving revision 1.159
diff -u -r1.159 guidegrid.cpp
--- mythtv/libs/libmythtv/guidegrid.cpp	17 Jun 2004 02:17:24 -0000	1.159
+++ mythtv/libs/libmythtv/guidegrid.cpp	24 Jun 2004 01:38:04 -0000
@@ -94,6 +94,7 @@
 
     fullRect = QRect(0, 0, size().width(), size().height());
     dateRect = QRect(0, 0, 0, 0);
+    jumpToChannelRect = QRect(0, 0, 0, 0);
     channelRect = QRect(0, 0, 0, 0);
     timeRect = QRect(0, 0, 0, 0);
     programRect = QRect(0, 0, 0, 0);
@@ -103,6 +104,12 @@
 
     MythContext::KickDatabase(m_db);
 
+    jumpToChannelEnabled = gContext->GetNumSetting("EPGEnableJumpToChannel", 0);
+    jumpToChannelActive = false;
+    jumpToChannelHasRect = false; // by default, we assume there is no specific region for jumpToChannel in the theme
+    jumpToChannelTimer = new QTimer(this);
+    connect(jumpToChannelTimer, SIGNAL(timeout()), SLOT(jumpToChannelTimeout()));
+    
     theme = new XMLParse();
     theme->SetWMult(wmult);
     theme->SetHMult(hmult);
@@ -132,7 +139,7 @@
 
     selectChangesChannel = gContext->GetNumSetting("SelectChangesChannel", 0);
     selectRecThreshold = gContext->GetNumSetting("SelChangeRecThreshold", 16);
-    
+
     LayerSet *container = NULL;
     container = theme->GetSet("guide");
     if (container)
@@ -350,6 +357,15 @@
                 dayLeft();
             else if (action == "DAYRIGHT")
                 dayRight();
+            else if (jumpToChannelEnabled &&
+                     ((action[0] >= '0') && (action[0] <= '9')))
+                jumpToChannelDigitPress(action.toInt());
+            else if (jumpToChannelEnabled && jumpToChannelActive &&
+                     (action == "ESCAPE"))
+                jumpToChannelCancel();
+            else if (jumpToChannelEnabled && jumpToChannelActive &&
+                     (action == "DELETE"))
+                jumpToChannelDeleteLastDigit();
             else if (action == "NEXTFAV" || action == "4")
                 toggleGuideListing();
             else if (action == "6")
@@ -461,6 +477,10 @@
         timeRect = area;
     if (name.lower() == "date_info")
         dateRect = area;
+    if (name.lower() == "jumptochannel") {
+        jumpToChannelRect = area;
+        jumpToChannelHasRect = true;
+    }
     if (name.lower() == "current_info")
         curInfoRect = area;
     if (name.lower() == "current_video")
@@ -882,7 +902,7 @@
 
     if (r.intersects(infoRect))
         paintInfo(&p);
-    if (r.intersects(dateRect))
+    if (r.intersects(dateRect) && (jumpToChannelHasRect || (!jumpToChannelHasRect && !jumpToChannelActive)))
         paintDate(&p);
     if (r.intersects(channelRect))
         paintChannels(&p);
@@ -893,6 +913,11 @@
     if (r.intersects(curInfoRect))
         paintCurrentInfo(&p);
 
+    // if jumpToChannel has its own rect, use that; otherwise use the date's rect
+    if ((jumpToChannelHasRect && r.intersects(jumpToChannelRect)) ||
+        (!jumpToChannelHasRect && r.intersects(dateRect)))
+        paintJumpToChannel(&p);
+
     qApp->unlock();
 }
 
@@ -927,6 +952,49 @@
     p->drawPixmap(dr.topLeft(), pix);
 }
 
+void GuideGrid::paintJumpToChannel(QPainter *p)
+{
+    if (!jumpToChannelEnabled || !jumpToChannelActive)
+        return;
+
+    QRect jtcr;
+    LayerSet *container = NULL;
+
+    if (jumpToChannelHasRect) {
+        jtcr = jumpToChannelRect;
+        container = theme->GetSet("jumptochannel");
+    } else {
+        jtcr = dateRect;
+        container = theme->GetSet("date_info");
+    }
+
+    QPixmap pix(jtcr.size());
+    pix.fill(this, jtcr.topLeft());
+    QPainter tmp(&pix);
+
+    if (container)
+    {
+        UITextType *type = (UITextType *)container->GetType((jumpToChannelHasRect) ? "channel" : "date");
+        if (type) {
+            type->SetText(QString::number(jumpToChannel));
+        }
+    }
+
+    if (container)
+    {
+        container->Draw(&tmp, 1, m_context);
+        container->Draw(&tmp, 2, m_context);
+        container->Draw(&tmp, 3, m_context);
+        container->Draw(&tmp, 4, m_context);
+        container->Draw(&tmp, 5, m_context);
+        container->Draw(&tmp, 6, m_context);
+        container->Draw(&tmp, 7, m_context);
+        container->Draw(&tmp, 8, m_context);
+    }
+    tmp.end();
+    p->drawPixmap(jtcr.topLeft(), pix);
+}
+
 void GuideGrid::paintCurrentInfo(QPainter *p)
 {
     QRect dr = curInfoRect;
@@ -1325,6 +1393,7 @@
     repaint(programRect, false);
     repaint(infoRect, false);
     repaint(dateRect, false);
+    repaint(jumpToChannelRect, false);
     repaint(timeRect, false);
 }
 
@@ -1346,6 +1415,7 @@
     repaint(programRect, false);
     repaint(infoRect, false);
     repaint(dateRect, false);
+    repaint(jumpToChannelRect, false);
     repaint(timeRect, false);
 }
 
@@ -1558,6 +1628,7 @@
 
     m_recList.FromScheduler();
     fillProgramInfos();
+
     repaint(fullRect, false);
 }
 
@@ -1602,3 +1673,110 @@
     m_player->EPGChannelUpdate(m_channelInfos[chanNum].chanstr);
 }
 
+//
+// jumpToChannel - Jason Parekh <jasonparekh at gmail.com> - 06/23/2004
+//
+// The way this works is if you enter a digit, it will set a timer for 2.5 seconds and enter
+// jump to channel mode where as you enter digits, it will find the closest matching channel
+// and show that on the program guide.  Within the 2.5 seconds, if you press the button bound
+// to END, it will cancel channel jump mode and revert to the highlighted channel before entering
+// this mode.  If you let the timer expire, it will stay on the selected channel.
+//
+// The positioning for the channel display can be in either one of two ways.  To ensure compatibility
+// with themes, I made it so if it can't find a specific jumptochannel container, it will use the date's
+// and just overwrite the date whenever it is in channel jump mode.  However, if there is a jumptochannel
+// container, it will use that.  An example container is as follows:
+//
+//     <container name="jumptochannel">
+//     <area>20,20,115,25</area>
+//     <textarea name="channel" draworder="4" align="right">
+//         <font>info</font>
+//         <area>0,0,115,25</area>
+//         <cutdown>no</cutdown>
+//     </textarea>
+//     </container>
+//
+
+void GuideGrid::jumpToChannelDigitPress(int digit)
+{
+    // if this is the first digit press (coming from inactive mode)
+    if (jumpToChannelActive == false) {
+        jumpToChannelActive = true;
+        jumpToChannel = 0;
+        jumpToChannelPreviousStartChannel = m_currentStartChannel;
+        jumpToChannelPreviousRow = m_currentRow;
+    }
+    
+    // setup the timeout timer for jump mode
+    jumpToChannelTimer->stop();
+    jumpToChannelTimer->start(3500, true);
+
+    jumpToChannel = (jumpToChannel * 10) + digit;
+
+    // So it will move to the closest channels while they enter the digits
+    jumpToChannelShowSelection();
+}
+
+void GuideGrid::jumpToChannelDeleteLastDigit()
+{
+    jumpToChannel /= 10;
+    
+    if (jumpToChannel == 0) {
+        jumpToChannelCancel();
+    }
+}
+
+void GuideGrid::jumpToChannelShowSelection()
+{
+    unsigned int i;
+    
+    // Not the best method, but the channel list is small and this isn't time critical
+    // Go through until the ith channel is equal to or greater than the one we're looking for
+    for (i=0; (i < m_channelInfos.size()-1) &&
+             (m_channelInfos[i].chanstr.toInt() < jumpToChannel); i++);
+    
+    if ((i > 0) &&
+        ((m_channelInfos[i].chanstr.toInt() - jumpToChannel) > (jumpToChannel - m_channelInfos[i-1].chanstr.toInt()))) {
+        i--;
+    }
+
+    // DISPLAY_CHANS to center
+    setStartChannel(i-DISPLAY_CHANS/2);
+    m_currentRow = DISPLAY_CHANS/2;
+    
+    fillProgramInfos();
+
+    repaint(fullRect, false);
+}
+
+void GuideGrid::jumpToChannelCommit()
+{
+    jumpToChannelResetAndHide();
+}
+
+void GuideGrid::jumpToChannelCancel()
+{
+    setStartChannel(jumpToChannelPreviousStartChannel);
+    m_currentRow = jumpToChannelPreviousRow;
+    
+    fillProgramInfos();
+    
+    repaint(fullRect, false);
+    
+    jumpToChannelResetAndHide();
+}
+
+void GuideGrid::jumpToChannelResetAndHide()
+{
+    jumpToChannelActive = false;
+
+    jumpToChannelTimer->stop();
+
+    repaint(fullRect, false);
+}
+
+void GuideGrid::jumpToChannelTimeout()
+{
+    jumpToChannelCommit();
+}
+
Index: mythtv/libs/libmythtv/guidegrid.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/guidegrid.h,v
retrieving revision 1.56
diff -u -r1.56 guidegrid.h
--- mythtv/libs/libmythtv/guidegrid.h	17 Jun 2004 02:17:24 -0000	1.56
+++ mythtv/libs/libmythtv/guidegrid.h	24 Jun 2004 01:38:04 -0000
@@ -79,6 +79,7 @@
 
   private slots:
     void timeout();
+    void jumpToChannelTimeout();
 
   private:
     void keyPressEvent(QKeyEvent *e);
@@ -86,6 +87,7 @@
 
     void updateBackground(void);
     void paintDate(QPainter *);
+    void paintJumpToChannel(QPainter *);
     void paintChannels(QPainter *);
     void paintTimes(QPainter *);
     void paintPrograms(QPainter *);
@@ -108,6 +110,7 @@
 
     QRect fullRect;
     QRect dateRect;
+    QRect jumpToChannelRect;
     QRect channelRect;
     QRect timeRect;
     QRect programRect;
@@ -166,6 +169,20 @@
     QSqlDatabase *m_db;
 
     bool keyDown;
+
+    void jumpToChannelResetAndHide();
+    void jumpToChannelCancel();
+    void jumpToChannelCommit();
+    void jumpToChannelShowSelection();
+    void jumpToChannelDeleteLastDigit();
+    void jumpToChannelDigitPress(int);
+    int jumpToChannel;
+    int jumpToChannelPreviousStartChannel;
+    int jumpToChannelPreviousRow;
+    bool jumpToChannelEnabled;
+    bool jumpToChannelActive;
+    bool jumpToChannelHasRect;
+    QTimer *jumpToChannelTimer;
 };
 
 #endif
Index: mythtv/programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.178
diff -u -r1.178 globalsettings.cpp
--- mythtv/programs/mythfrontend/globalsettings.cpp	16 Jun 2004 23:37:39 -0000	1.178
+++ mythtv/programs/mythfrontend/globalsettings.cpp	24 Jun 2004 01:38:05 -0000
@@ -1681,6 +1681,19 @@
     };
 };
 
+class EPGEnableJumpToChannel: public CheckBoxSetting, public GlobalSetting {
+public:
+    EPGEnableJumpToChannel():
+        GlobalSetting("EPGEnableJumpToChannel") {
+        setLabel(QObject::tr("Enable Jump to Channel Mode"));
+        setHelpText(QObject::tr("If enabled, you will be able to press numbers "
+                                "and jump the selection to whatever channel you enter. "
+                                "There is no need to scroll through all your channels to "
+                                "reach that distant channel anymore!"));
+        setValue(false);
+    };
+};
+
 // General RecPriorities settings
 
 class GRSchedMoveHigher: public CheckBoxSetting, public BackendSetting {
@@ -2558,6 +2571,7 @@
     gen->addChild(new DefaultTVChannel());
     gen->addChild(new SelectChangesChannel());
     gen->addChild(new EPGRecThreshold());
+    gen->addChild(new EPGEnableJumpToChannel());
     addChild(gen);
 }
 


More information about the mythtv-dev mailing list