Index: libs/libmythtv/eit.cpp
===================================================================
--- libs/libmythtv/eit.cpp	(revision 37)
+++ libs/libmythtv/eit.cpp	(working copy)
@@ -5,6 +5,7 @@
 using namespace std;
 
 // MythTV includes
+#include "listingsources.h"
 #include "mythdb.h"
 #include "mythverbose.h"
 #include "eit.h"
@@ -388,7 +389,7 @@
     query.bindValue(":SYNDICATENO", lsyndicatedepisodenumber);
     query.bindValue(":AIRDATE",     lairdate.isEmpty() ? "0000" : lairdate);
     query.bindValue(":ORIGAIRDATE", loriginalairdate);
-    query.bindValue(":LSOURCE",     1);
+    query.bindValue(":LSOURCE",     kEIT);
     query.bindValue(":SERIESID",    lseriesId);
     query.bindValue(":PROGRAMID",   lprogramId);
     query.bindValue(":PREVSHOWN",   lpreviouslyshown);
@@ -553,7 +554,7 @@
     query.bindValue(":SYNDICATENO", syndicatedepisodenumber);
     query.bindValue(":AIRDATE",     airdate.isEmpty() ? "0000" : airdate);
     query.bindValue(":ORIGAIRDATE", originalairdate);
-    query.bindValue(":LSOURCE",     1);
+    query.bindValue(":LSOURCE",     kEIT);
     query.bindValue(":SERIESID",    lseriesId);
     query.bindValue(":PROGRAMID",   lprogramId);
     query.bindValue(":PREVSHOWN",   previouslyshown);
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 40)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -161,7 +161,7 @@
 HEADERS += viewschdiff.h            livetvchain.h
 HEADERS += playgroup.h              progdetails.h
 HEADERS += channelsettings.h        previewgenerator.h
-HEADERS += transporteditor.h
+HEADERS += transporteditor.h        listingsources.h
 HEADERS += myth_imgconvert.h
 
 # Remove when everything is switched to MythUI
Index: libs/libmythtv/dbox2epg.cpp
===================================================================
--- libs/libmythtv/dbox2epg.cpp	(revision 37)
+++ libs/libmythtv/dbox2epg.cpp	(working copy)
@@ -9,6 +9,7 @@
 
 #include "dbox2channel.h"
 #include "dbox2epg.h"
+#include "listingsources.h"
 #include "mythdb.h"
 #include "mythverbose.h"
 #include "tv_rec.h"
@@ -183,11 +184,13 @@
     query.prepare("INSERT INTO program "
                   "    (chanid,   starttime,  endtime,      "
                   "     title,    subtitle,   description,  "
-                  "     category, airdate,    stars)        "
+                  "     category, airdate,    stars,        "
+                  "     listingsource)"
                   "VALUES "
                   "    (:CHANID,  :STARTTIME, :ENDTIME,     "
                   "     :TITLE,   :SUBTITLE,  :DESCRIPTION, "
-                  "     :CATEGORY,:AIRDATE,   :STARS)");
+                  "     :CATEGORY,:AIRDATE,   :STARS,       "
+                  "     :LSOURCE);");
 
     query.bindValue(":CHANID",      chanid);
     query.bindValue(":STARTTIME",   startTime);
@@ -198,6 +201,7 @@
     query.bindValue(":CATEGORY",    category);
     query.bindValue(":AIRDATE",     "0");
     query.bindValue(":STARS",       "0");
+    query.bindValue(":LSOURCE",     kDBox2EPG);
 
     if (!query.exec())
         MythDB::DBError("Saving new program", query);
Index: libs/libmythtv/dbcheck.cpp
===================================================================
--- libs/libmythtv/dbcheck.cpp	(revision 37)
+++ libs/libmythtv/dbcheck.cpp	(working copy)
@@ -18,7 +18,7 @@
 #define MINIMUM_DBMS_VERSION 5,0,15
 
 /// This is the DB schema version expected by the running MythTV instance.
-const QString currentDatabaseVersion = "1232";
+const QString currentDatabaseVersion = "1233";
 
 static bool UpdateDBVersionNumber(const QString &newnumber);
 static bool performActualUpdate(
@@ -4458,6 +4458,18 @@
         if (!performActualUpdate(updates, "1232", dbver))  
             return false;  
     }   
+    if (dbver == "1232")
+    {
+        const char *updates[] = {
+"ALTER TABLE program"
+"    ADD COLUMN lastupdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP "
+"        ON UPDATE CURRENT_TIMESTAMP, "
+"    ADD INDEX program_lastupdate (lastupdate);",
+NULL
+};
+        if (!performActualUpdate(updates, "1233", dbver))
+            return false;
+    }
 
     return true;
 }
Index: libs/libmythtv/datadirect.h
===================================================================
--- libs/libmythtv/datadirect.h	(revision 37)
+++ libs/libmythtv/datadirect.h	(working copy)
@@ -327,7 +327,7 @@
         uint sourceid, bool insert_channels, bool filter_new_channels);
     static bool UpdateChannelsUnsafe(
         uint sourceid, bool filter_new_channels);
-    static void DataDirectProgramUpdate(void);
+    static void DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to);
 
     // static command, makes Labs and Schedules Direct ProgramIDs compatible.
     static void FixProgramIDs(void);
Index: libs/libmythtv/datadirect.cpp
===================================================================
--- libs/libmythtv/datadirect.cpp	(revision 37)
+++ libs/libmythtv/datadirect.cpp	(working copy)
@@ -13,6 +13,7 @@
 #include "sourceutil.h"
 #include "channelutil.h"
 #include "frequencytables.h"
+#include "listingsources.h"
 #include "mythwidgets.h"
 #include "mythcontext.h"
 #include "mythdb.h"
@@ -824,34 +825,139 @@
     return true;
 }
 
-void DataDirectProcessor::DataDirectProgramUpdate(void)
+void DataDirectProcessor::DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to)
 {
     MSqlQuery query(MSqlQuery::DDCon());
 
+    QString queryString("DELETE program FROM program"
+                        " LEFT JOIN channel"
+                        "  ON program.chanid = channel.chanid"
+                        " LEFT JOIN dd_genre"
+                        "  ON program.programid = dd_genre.programid"
+                        "  AND program.category = dd_genre.class"
+                        "  AND dd_genre.relevance = '0'"
+                        " LEFT JOIN dd_v_program"
+                        "  ON program.chanid = dd_v_program.chanid"
+                        "  AND program.starttime = DATE_ADD(dd_v_program.starttime, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.endtime = DATE_ADD(dd_v_program.endtime, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.title = dd_v_program.title"
+                        "  AND program.subtitle = dd_v_program.subtitle"
+                        "  AND program.description = dd_v_program.description"
+                        "  AND program.showtype = dd_v_program.showtype"
+                        "  AND program.category_type = dd_v_program.category_type"
+                        "  AND program.airdate = dd_v_program.airdate"
+                        "  AND program.stars = dd_v_program.stars"
+                        "  AND program.stereo = dd_v_program.stereo"
+                        "  AND program.subtitled = dd_v_program.subtitled"
+                        "  AND program.subtitletypes = (dd_v_program.subtitled << 1) | dd_v_program.closecaptioned"
+                        "  AND program.videoprop = dd_v_program.hdtv"
+                        "  AND program.audioprop = (dd_v_program.dolby << 3) | dd_v_program.stereo"
+                        "  AND program.hdtv = dd_v_program.hdtv"
+                        "  AND program.closecaptioned = dd_v_program.closecaptioned"
+                        "  AND program.partnumber = dd_v_program.partnumber"
+                        "  AND program.parttotal = dd_v_program.parttotal"
+                        "  AND program.seriesid = dd_v_program.seriesid"
+                        "  AND program.originalairdate <=> dd_v_program.originalairdate"
+                        "  AND program.colorcode = dd_v_program.colorcode"
+                        "  AND program.syndicatedepisodenumber = dd_v_program.syndicatedepisodenumber"
+                        "  AND program.programid = dd_v_program.programid"
+                        " WHERE"
+                        "  (channel.chanid is NULL"
+                        "   OR (dd_genre.programid is NULL"
+                        "       AND (SELECT COUNT(*) FROM dd_genre"
+                        "             WHERE programid = program.programid))"
+                        "   OR dd_v_program.chanid is NULL)"
+                        "  AND program.starttime >= DATE_ADD(:FROM, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.starttime < DATE_ADD(:TO, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND channel.sourceid = :SOURCEID");
+
+    QString preferredSource(gContext->GetSetting("PreferredListingsSource"));
+    if (!preferredSource.isEmpty() && preferredSource != "datadirect")
+        queryString += "  AND program.listingsource = " + QString::number(kDataDirect);
+
+    queryString += ';';
+
+    query.prepare(queryString);
+    query.bindValue(":FROM", from);
+    query.bindValue(":TO", to);
+    query.bindValue(":SOURCEID", sourceid);
+    if (!query.exec())
+        MythDB::DBError("Deleting changed entries from program table", query);
+
+    query.prepare("DELETE dd_v_program FROM dd_v_program"
+                  " INNER JOIN channel"
+                  "  ON dd_v_program.chanid = channel.chanid"
+                  " LEFT JOIN dd_genre"
+                  "  ON dd_v_program.programid = dd_genre.programid"
+                  "  AND dd_genre.relevance = '0'"
+                  " INNER JOIN program"
+                  "  ON (program.chanid = dd_v_program.chanid"
+                  "   AND program.starttime = DATE_ADD(dd_v_program.starttime, INTERVAL channel.tmoffset MINUTE)"
+                  "   AND program.endtime = DATE_ADD(dd_v_program.endtime, INTERVAL channel.tmoffset MINUTE)"
+                  "   AND program.title = dd_v_program.title"
+                  "   AND program.subtitle = dd_v_program.subtitle"
+                  "   AND program.description = dd_v_program.description"
+                  "   AND program.showtype = dd_v_program.showtype"
+                  "   AND program.category = dd_genre.class"
+                  "   AND program.category_type = dd_v_program.category_type"
+                  "   AND program.airdate = dd_v_program.airdate"
+                  "   AND program.stars = dd_v_program.stars"
+                  "   AND program.stereo = dd_v_program.stereo"
+                  "   AND program.subtitled = dd_v_program.subtitled"
+                  "   AND program.subtitletypes = (dd_v_program.subtitled << 1) | dd_v_program.closecaptioned"
+                  "   AND program.videoprop = dd_v_program.hdtv"
+                  "   AND program.audioprop = (dd_v_program.dolby << 3) | dd_v_program.stereo"
+                  "   AND program.hdtv = dd_v_program.hdtv"
+                  "   AND program.closecaptioned = dd_v_program.closecaptioned"
+                  "   AND program.partnumber = dd_v_program.partnumber"
+                  "   AND program.parttotal = dd_v_program.parttotal"
+                  "   AND program.seriesid = dd_v_program.seriesid"
+                  "   AND program.originalairdate <=> dd_v_program.originalairdate"
+                  "   AND program.colorcode = dd_v_program.colorcode"
+                  "   AND program.syndicatedepisodenumber = dd_v_program.syndicatedepisodenumber"
+                  "   AND program.programid = dd_v_program.programid"
+                  " WHERE dd_genre.programid IS NOT NULL"
+                  "  OR program.category = ''"
+                  ";");
+
+    if (!query.exec("DELETE dd_v_program FROM dd_v_program"
+                    " INNER JOIN program"
+                    "  ON dd_v_program.chanid = program.chanid"
+                    "   AND ((dd_v_program.endtime > program.starttime"
+                    "     AND dd_v_program.endtime <= program.endtime)"
+                    "    OR (dd_v_program.starttime >= program.starttime"
+                    "     AND dd_v_program.starttime < program.endtime)"
+                    "    OR (dd_v_program.starttime < program.starttime"
+                    "     AND dd_v_program.endtime > program.endtime));"))
+        MythDB::DBError("Deleting up-to-date entries from listings source data", query);
+
     //cerr << "Adding rows to main program table from view table..\n";
-    if (!query.exec("INSERT IGNORE INTO program (chanid, starttime, endtime, "
-                    "title, subtitle, description, "
-                    "showtype, category, category_type, "
-                    "airdate, stars, previouslyshown, stereo, subtitled, "
-                    "subtitletypes, videoprop, audioprop, "
-                    "hdtv, closecaptioned, partnumber, parttotal, seriesid, "
-                    "originalairdate, colorcode, syndicatedepisodenumber, "
-                    "programid) "
-                    "SELECT dd_v_program.chanid, "
-                    "DATE_ADD(starttime, INTERVAL channel.tmoffset MINUTE), "
-                    "DATE_ADD(endtime, INTERVAL channel.tmoffset MINUTE), "
-                    "title, subtitle, description, "
-                    "showtype, dd_genre.class, category_type, "
-                    "airdate, stars, previouslyshown, stereo, subtitled, "
-                    "(subtitled << 1 ) | closecaptioned, hdtv, "
-                    "(dolby << 3) | stereo, "
-                    "hdtv, closecaptioned, partnumber, parttotal, seriesid, "
-                    "originalairdate, colorcode, syndicatedepisodenumber, "
-                    "dd_v_program.programid FROM (dd_v_program, channel) "
-                    "LEFT JOIN dd_genre ON ("
-                    "dd_v_program.programid = dd_genre.programid AND "
-                    "dd_genre.relevance = '0') "
-                    "WHERE dd_v_program.chanid = channel.chanid;"))
+    query.prepare("INSERT IGNORE INTO program (chanid, starttime, endtime, "
+                  "title, subtitle, description, "
+                  "showtype, category, category_type, "
+                  "airdate, stars, previouslyshown, stereo, subtitled, "
+                  "subtitletypes, videoprop, audioprop, "
+                  "hdtv, closecaptioned, partnumber, parttotal, seriesid, "
+                  "originalairdate, colorcode, syndicatedepisodenumber, "
+                  "programid, listingsource) "
+                  "SELECT dd_v_program.chanid, "
+                  "DATE_ADD(starttime, INTERVAL channel.tmoffset MINUTE), "
+                  "DATE_ADD(endtime, INTERVAL channel.tmoffset MINUTE), "
+                  "title, subtitle, description, "
+                  "showtype, dd_genre.class, category_type, "
+                  "airdate, stars, previouslyshown, stereo, subtitled, "
+                  "(subtitled << 1 ) | closecaptioned, hdtv, "
+                  "(dolby << 3) | stereo, "
+                  "hdtv, closecaptioned, partnumber, parttotal, seriesid, "
+                  "originalairdate, colorcode, syndicatedepisodenumber, "
+                  "dd_v_program.programid, :LSOURCE "
+                  "FROM (dd_v_program, channel) "
+                  "LEFT JOIN dd_genre ON ("
+                  "dd_v_program.programid = dd_genre.programid AND "
+                  "dd_genre.relevance = '0') "
+                  "WHERE dd_v_program.chanid = channel.chanid;");
+    query.bindValue(":LSOURCE", kDataDirect);
+    if (!query.exec())
         MythDB::DBError("Inserting into program table", query);
 
     //cerr << "Finished adding rows to main program table...\n";
Index: libs/libmythtv/programdata.cpp
===================================================================
--- libs/libmythtv/programdata.cpp	(revision 37)
+++ libs/libmythtv/programdata.cpp	(working copy)
@@ -1,4 +1,5 @@
 // MythTV headers
+#include "listingsources.h"
 #include "mythdb.h"
 #include "mythverbose.h"
 #include "programinfo.h"
@@ -27,7 +28,7 @@
     return false;
 }
 
-void ProgramData::clearDataByChannel(int chanid, QDateTime from, QDateTime to)
+void ProgramData::clearDataByChannel(int chanid, QDateTime from, QDateTime to, bool clearprogram)
 {
     int secs;
     QDateTime newFrom, newTo;
@@ -49,13 +50,15 @@
     newFrom = from.addSecs(secs);
     newTo = to.addSecs(secs);
 
-    query.prepare("DELETE FROM program "
-                  "WHERE starttime >= :FROM AND starttime < :TO "
-                  "AND chanid = :CHANID ;");
-    query.bindValue(":FROM", newFrom);
-    query.bindValue(":TO", newTo);
-    query.bindValue(":CHANID", chanid);
-    query.exec();
+    if (clearprogram) {
+        query.prepare("DELETE FROM program "
+                      "WHERE starttime >= :FROM AND starttime < :TO "
+                      "AND chanid = :CHANID ;");
+        query.bindValue(":FROM", newFrom);
+        query.bindValue(":TO", newTo);
+        query.bindValue(":CHANID", chanid);
+        query.exec();
+    }
 
     query.prepare("DELETE FROM programrating "
                   "WHERE starttime >= :FROM AND starttime < :TO "
@@ -82,7 +85,7 @@
     query.exec();
 }
 
-void ProgramData::clearDataBySource(int sourceid, QDateTime from, QDateTime to)
+void ProgramData::clearDataBySource(int sourceid, QDateTime from, QDateTime to, bool clearprogram)
 {
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT chanid FROM channel WHERE "
@@ -97,7 +100,7 @@
         while (query.next())
         {
             int chanid = query.value(0).toInt();
-            clearDataByChannel(chanid, from, to);
+            clearDataByChannel(chanid, from, to, clearprogram);
         }
     }
 }
@@ -347,7 +350,8 @@
                               "audioprop,videoprop,subtitletypes,subtitled,"
                               "closecaptioned,partnumber,parttotal,"
                               "seriesid,originalairdate,showtype,colorcode,"
-                              "syndicatedepisodenumber,programid) "
+                              "syndicatedepisodenumber,programid,"
+                              "listingsource) "
                               "VALUES(:CHANID,:STARTTIME,:ENDTIME,:TITLE,"
                               ":SUBTITLE,:DESCRIPTION,:CATEGORY,:CATEGORY_TYPE,"
                               ":AIRDATE,:STARS,:PREVIOUSLYSHOWN,"
@@ -355,7 +359,7 @@
                               ":AUDIOPROP,:VIDEOPROP,:SUBTYPES,:SUBTITLED,"
                               ":CLOSECAPTIONED,:PARTNUMBER,:PARTTOTAL,"
                               ":SERIESID,:ORIGINALAIRDATE,:SHOWTYPE,:COLORCODE,"
-                              ":SYNDICATEDEPISODENUMBER,:PROGRAMID);");
+                              ":SYNDICATEDEPISODENUMBER,:PROGRAMID,:LSOURCE);");
                 query.bindValue(":CHANID", chanid);
                 query.bindValue(":STARTTIME", (*i).start);
                 query.bindValue(":ENDTIME", (*i).end);
@@ -383,6 +387,7 @@
                 query.bindValue(":COLORCODE", (*i).colorcode);
                 query.bindValue(":SYNDICATEDEPISODENUMBER", (*i).syndicatedepisodenumber);
                 query.bindValue(":PROGRAMID", (*i).programid);
+                query.bindValue(":LSOURCE", kXMLTV);
                 if (!query.exec())
                     MythDB::DBError("program insert", query);
 
Index: libs/libmythtv/programdata.h
===================================================================
--- libs/libmythtv/programdata.h	(revision 37)
+++ libs/libmythtv/programdata.h	(working copy)
@@ -104,8 +104,10 @@
                         QMap<QString, QList<ProgInfo> > *proglist);
 
     static int  fix_end_times(void);
-    static void clearDataByChannel(int chanid, QDateTime from, QDateTime to);
-    static void clearDataBySource(int sourceid, QDateTime from, QDateTime to);
+    static void clearDataByChannel(int chanid, QDateTime from, QDateTime to,
+                                   bool clearprogram = FALSE);
+    static void clearDataBySource(int sourceid, QDateTime from, QDateTime to,
+                                  bool clearprogram = FALSE);
 
   private:
     void fixProgramList(QList<ProgInfo> *fixlist);
Index: programs/mythfilldatabase/filldata.cpp
===================================================================
--- programs/mythfilldatabase/filldata.cpp	(revision 37)
+++ programs/mythfilldatabase/filldata.cpp	(working copy)
@@ -308,7 +308,8 @@
     VERBOSE(VB_GENERAL, "Data for source cleared.");
 
     VERBOSE(VB_GENERAL, "Updating programs.");
-    DataDirectProcessor::DataDirectProgramUpdate();
+    DataDirectProcessor::DataDirectProgramUpdate(source.id, fromlocaldt,
+                                                 tolocaldt);
     VERBOSE(VB_GENERAL, "Program table update complete.");
 
     return true;
Index: programs/mythfilldatabase/main.cpp
===================================================================
--- programs/mythfilldatabase/main.cpp	(revision 39)
+++ programs/mythfilldatabase/main.cpp	(working copy)
@@ -713,7 +713,7 @@
         query.prepare("UPDATE program SET generic = 1 WHERE "
             "((programid = '' AND subtitle = '' AND description = '') OR "
             " (programid <> '' AND category_type = 'series' AND "
-            "  program.programid LIKE '%0000'));");
+            "  program.programid LIKE '%0000') AND generic <> 1);");
 
         if (!query.exec())
             MythDB::DBError("mark generic", query);
@@ -814,7 +814,6 @@
     if (grab_data)
     {
         MSqlQuery updt(MSqlQuery::InitCon());
-        updt.exec("UPDATE program SET first = 0, last = 0;");
 
         VERBOSE(VB_GENERAL, "Marking episode first showings.");
 
@@ -828,10 +827,19 @@
             {
                 updt.prepare("UPDATE program set first = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         int found = query.size();
@@ -848,12 +856,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
@@ -870,10 +891,19 @@
             {
                 updt.prepare("UPDATE program set last = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         found = query.size();
@@ -890,12 +920,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
