MythTV master
restoredata.cpp
Go to the documentation of this file.
1/*
2 * $Id$
3 * vim: set expandtab tabstop=4 shiftwidth=4:
4 *
5 * Original Project
6 * MythTV http://www.mythtv.org
7 *
8 * Description:
9 * Restore data from deleted channels after scan for new channels
10 *
11 * When all channels are deleted and a new scan is done then
12 * all the non-scanned data is lost.
13 * This are the following fields:
14 * xmltvid Channel identification for XMLTV including Schedules Direct
15 * iconpath File name of icon for this channel
16 * visible Visible status
17 * When a channel is deleted it is not immediately deleted from the database;
18 * it is kept for a while with the "deleted" field set to the date at which it
19 * is deleted.
20 * This makes it possible to retrieve this data from the deleted records
21 * when the same channel is found again in a new scan.
22 *
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
36 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
37 *
38 */
39
40// C++ includes
41#include <vector>
42#include <iostream>
43
44// MythTV includes
45#include "libmythbase/mythdb.h"
50#include "libmythui/themeinfo.h"
51
52#include "restoredata.h"
53#include "sourceutil.h"
54#include "videosource.h"
55
56#define LOC QString("RestoreData: ")
57
59{
60 public:
62 {
63 setLabel(QObject::tr("Restore XMLTV ID"));
65 QObject::tr(
66 "If checked, copy the XMLTV ID in field \"xmltvid\" "
67 "from a deleted channel "
68 "or from a channel in another video source."));
69 setValue(false);
70 };
71};
72
74{
75 public:
77 {
78 setLabel(QObject::tr("Restore Visible status"));
80 QObject::tr(
81 "If checked, copy the Visible status in field \"visible\" "
82 "from a deleted channel in this video source."));
83 setValue(false);
84 };
85};
86
88{
89 public:
91 {
92 setLabel(QObject::tr("Restore Icon filename"));
94 QObject::tr(
95 "If checked, copy the Icon filename in field \"icon\" "
96 "from a deleted channel "
97 "or from a channel in another video source."));
98 setValue(false);
99 };
100};
101
103
105{
106 if (s_Instance != nullptr)
107 {
108 if (sourceid != s_Instance->m_sourceid)
109 {
110 delete s_Instance;
111 s_Instance = nullptr;
112 }
113 }
114 if (s_Instance == nullptr)
115 s_Instance = new RestoreData(sourceid, false);
116 return s_Instance;
117}
118
120{
121 if (s_Instance != nullptr)
122 {
123 delete s_Instance;
124 s_Instance = nullptr;
125 }
126}
127
128RestoreData::RestoreData(uint sourceid, bool useGUI) :
129 m_sourceid(sourceid), m_useGUI(useGUI)
130{
131 if (!m_useGUI)
132 return;
133 setLabel(tr("Restore Data"));
134
137 QObject::tr(
138 "The video source is selected in the Channel Editor page. "
139 "Searching for non-scanned data is done for all channels in this video source."
140 ));
142
145
148
151
152 auto *newTransport = new ButtonStandardSetting(tr("Search"));
153 newTransport->setHelpText(
154 QObject::tr(
155 "Start searching for non-scanned data. The data is written to the database "
156 "when \'Save and Exit\' is selected in the \'Exit Settings?\' dialog box."
157 ));
158 addChild(newTransport);
159 connect(newTransport, &ButtonStandardSetting::clicked, this, &RestoreData::Restore);
160}
161
163{
164 if (!m_useGUI)
165 return;
166 bool do_xmltvid = m_restoreXMLTVID->boolValue();
167 bool do_icon = m_restoreIcon->boolValue();
168 bool do_visible = m_restoreVisible->boolValue();
169 doRestore(do_xmltvid, do_icon, do_visible);
170}
171
172QString RestoreData::doRestore(bool do_xmltvid, bool do_icon, bool do_visible)
173{
174 if (do_xmltvid || do_icon || do_visible)
175 {
176 QString msg = QString("Restore data from deleted channels for fields ");
177 if (do_xmltvid)
178 {
179 msg += "xmltvid ";
180 }
181 if (do_icon)
182 {
183 msg += "icon ";
184 }
185 if (do_visible)
186 {
187 msg += "visible ";
188 }
189 LOG(VB_GENERAL, LOG_INFO, LOC + msg);
190 }
191
192 // Old Channel Data
193 m_ocd.clear();
194
197
198 // For all channels in this videosource
199 query.prepare(
200 "SELECT chanid, channum, name, serviceid, transportid, networkid, "
201 " channel.xmltvid, "
202 " channel.icon, "
203 " channel.visible "
204 "FROM channel, dtv_multiplex "
205 "WHERE channel.sourceid = :SOURCEID "
206 " AND channel.mplexid = dtv_multiplex.mplexid "
207 " AND deleted IS NULL ");
208 query.bindValue(":SOURCEID", m_sourceid);
209 if (!query.exec() || !query.isActive())
210 {
211 MythDB::DBError("RestoreData::Restore(1)", query);
212 return {};
213 }
214 while (query.next())
215 {
217 cd.chanid = query.value(0).toUInt();
218 cd.channum = query.value(1).toString();
219 cd.name = query.value(2).toString();
220 cd.serviceid = query.value(3).toUInt();
221 cd.transportid = query.value(4).toUInt();
222 cd.networkid = query.value(5).toUInt();
223 cd.xmltvid = query.value(6).toString();
224 cd.icon = query.value(7).toString();
225 cd.visible = query.value(8).toInt();
226
227 bool nullNetwork = query.isNull(5);
228 cd.found_xmltvid = false;
229 cd.found_icon = false;
230 cd.found_visible = false;
231
232 QString networkCheck;
233 if (nullNetwork)
234 networkCheck = " networkid IS NULL";
235 else
236 networkCheck = " networkid = :NETWORKID ";
237
238 // Get xmltvid from the last deleted channel
239 // from any video source or from a channel
240 // on a different video source
241 if (do_xmltvid && cd.xmltvid.isEmpty())
242 {
243 query2.prepare(
244 "SELECT xmltvid "
245 "FROM channel, dtv_multiplex "
246 "WHERE serviceid = :SERVICEID "
247 " AND transportid = :TRANSPORTID "
248 " AND " + networkCheck +
249 " AND channel.mplexid = dtv_multiplex.mplexid "
250 " AND xmltvid != ''"
251 " AND (deleted IS NOT NULL OR "
252 " channel.sourceid != :SOURCEID)"
253 "ORDER BY deleted DESC;");
254 query2.bindValue(":SERVICEID", cd.serviceid);
255 query2.bindValue(":TRANSPORTID", cd.transportid);
256 if (!nullNetwork)
257 query2.bindValue(":NETWORKID", cd.networkid);
258 query2.bindValue(":SOURCEID", m_sourceid);
259 if (!query2.exec() || !query2.isActive())
260 {
261 MythDB::DBError("RestoreData::Restore(2)", query);
262 return {};
263 }
264 if (query2.next())
265 {
266 cd.xmltvid = query2.value(0).toString();
267 cd.found_xmltvid = true;
268 }
269 }
270
271 // Get icon from the last deleted channel
272 // from any video source or from a channel
273 // on a different video source
274 if (do_icon && cd.icon.isEmpty())
275 {
276 query2.prepare(
277 "SELECT icon "
278 "FROM channel, dtv_multiplex "
279 "WHERE serviceid = :SERVICEID "
280 " AND transportid = :TRANSPORTID "
281 " AND channel.mplexid = dtv_multiplex.mplexid "
282 " AND icon != ''"
283 " AND (deleted IS NOT NULL OR "
284 " channel.sourceid != :SOURCEID)"
285 "ORDER BY deleted DESC;");
286 query2.bindValue(":SERVICEID", cd.serviceid);
287 query2.bindValue(":TRANSPORTID", cd.transportid);
288 if (!nullNetwork)
289 query2.bindValue(":NETWORKID", cd.networkid);
290 query2.bindValue(":SOURCEID", m_sourceid);
291 if (!query2.exec() || !query2.isActive())
292 {
293 MythDB::DBError("RestoreData::Restore(3)", query);
294 return {};
295 }
296 if (query2.next())
297 {
298 cd.icon = query2.value(0).toString();
299 cd.found_icon = true;
300 }
301 }
302
303 // Get visible from the last deleted channel
304 // but only from the same video source
305 if (do_visible)
306 {
307 query2.prepare(
308 "SELECT channel.visible "
309 "FROM channel, dtv_multiplex "
310 "WHERE serviceid = :SERVICEID "
311 " AND transportid = :TRANSPORTID "
312 " AND " + networkCheck +
313 " AND channel.sourceid = :SOURCEID "
314 " AND channel.mplexid = dtv_multiplex.mplexid "
315 " AND deleted IS NOT NULL "
316 "ORDER BY deleted DESC;");
317 query2.bindValue(":SERVICEID", cd.serviceid);
318 query2.bindValue(":TRANSPORTID", cd.transportid);
319 if (!nullNetwork)
320 query2.bindValue(":NETWORKID", cd.networkid);
321 query2.bindValue(":SOURCEID", m_sourceid);
322 if (!query2.exec() || !query2.isActive())
323 {
324 MythDB::DBError("RestoreData::Restore(4)", query);
325 return {};
326 }
327 if (query2.next())
328 {
329 int visible = query2.value(0).toInt();
330 if (visible != cd.visible)
331 {
332 cd.visible = visible;
333 cd.found_visible = true;
334 }
335 }
336 }
337
338 if (cd.found_xmltvid || cd.found_icon || cd.found_visible)
339 {
340 m_ocd.push_back(cd);
341 }
342 }
343
344 // Header line for log of all changes
345 if (m_ocd.empty())
346 {
347 LOG(VB_GENERAL, LOG_INFO, LOC + "No data found in deleted channels or no data needed");
348 }
349 else
350 {
351 LOG(VB_GENERAL, LOG_INFO, LOC +
352 QString("Restoring data in %1 channels from deleted channels:")
353 .arg(m_ocd.size()));
354 }
355
356 // Log of all channels that will be updated
357 m_num_xmltvid = 0;
358 m_num_icon = 0;
359 m_num_visible = 0;
360 for (auto & cd : m_ocd)
361 {
362 QString msg = QString("Channel %1 \'%2\' update ").arg(cd.channum, cd.name);
363 if (cd.found_xmltvid)
364 {
365 msg += QString("xmltvid(%1) ").arg(cd.xmltvid);
367 }
368 if (cd.found_icon)
369 {
370 msg += QString("icon(%1) ").arg(cd.icon);
371 m_num_icon++;
372 }
373 if (cd.found_visible)
374 {
375 msg += QString("visible(%1) ").arg(cd.visible);
377 }
378 LOG(VB_GENERAL, LOG_INFO, LOC + msg);
379 }
380 m_num_channels = m_ocd.size();
381
382 // Show totals of what has been found.
383 {
384 QString msg;
385 if (m_ocd.empty())
386 {
387 msg = "No data found";
388 }
389 else
390 {
391 msg = QString("Found data for %1 channels\n").arg(m_ocd.size());
392 if (m_num_xmltvid > 0)
393 {
394 msg += QString("xmltvid: %1 ").arg(m_num_xmltvid);
395 }
396 if (m_num_icon > 0)
397 {
398 msg += QString("icon: %1 ").arg(m_num_icon);
399 }
400 if (m_num_visible > 0)
401 {
402 msg += QString("visible: %1").arg(m_num_visible);
403 }
404 }
405 if (m_useGUI)
406 WaitFor(ShowOkPopup(msg));
407 return msg;
408 }
409
410}
411
412// Load value of selected video source (for display only)
414{
416}
417
418// Do the actual updating if "Save and Exit" is selected in the "Exit Settings?" dialog.
420{
421 doSave();
422}
423
425{
426 if (m_ocd.empty())
427 {
428 LOG(VB_GENERAL, LOG_INFO, LOC + QString("No data to Restore"));
429 return false;
430 }
432 for (auto & cd : m_ocd)
433 {
434 query.prepare(
435 "UPDATE channel "
436 "SET icon = :ICON, "
437 " xmltvid = :XMLTVID, "
438 " visible = :VISIBLE "
439 "WHERE chanid = :CHANID");
440 query.bindValue(":ICON", cd.icon);
441 query.bindValue(":XMLTVID", cd.xmltvid);
442 query.bindValue(":VISIBLE", cd.visible);
443 query.bindValue(":CHANID", cd.chanid);
444 if (!query.exec() || !query.isActive())
445 {
446 MythDB::DBError("RestoreData::Restore(5)", query);
447 return false;
448 }
449 }
450 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Restored data for %1 channels").arg(m_ocd.size()));
451 return true;
452}
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
bool isNull(int field) const
Definition: mythdbcon.h:219
QVariant value(int i) const
Definition: mythdbcon.h:204
bool isActive(void) const
Definition: mythdbcon.h:215
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
void setValue(const QString &newValue) override
bool doSave(void)
RestoreXMLTVID * m_restoreXMLTVID
Definition: restoredata.h:100
static void freeInstance()
RestoreData(uint sourceid, bool useGUI=true)
void Save(void) override
QString doRestore(bool do_xmltvid, bool do_icon, bool do_visible)
void Load(void) override
int m_num_xmltvid
Definition: restoredata.h:112
int m_num_visible
Definition: restoredata.h:114
void Restore(void)
uint m_sourceid
Definition: restoredata.h:104
int m_num_channels
Definition: restoredata.h:111
std::vector< OldChannelData > m_ocd
Definition: restoredata.h:107
static RestoreData * getInstance(uint sourceid)
RestoreIcon * m_restoreIcon
Definition: restoredata.h:102
VideoSourceShow * m_videosource
Definition: restoredata.h:99
static RestoreData * s_Instance
Definition: restoredata.h:98
RestoreVisible * m_restoreVisible
Definition: restoredata.h:101
virtual void addChild(StandardSetting *child)
virtual void Load(void)
virtual void setHelpText(const QString &str)
virtual void setLabel(QString str)
unsigned int uint
Definition: compat.h:68
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
bool WaitFor(MythConfirmationDialog *dialog)
Blocks until confirmation dialog exits.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
Definition: restoredata.cpp:56
QString xmltvid
Definition: restoredata.h:70
bool found_xmltvid
Definition: restoredata.h:74
bool found_visible
Definition: restoredata.h:76
QString channum
Definition: restoredata.h:68
QString icon
Definition: restoredata.h:71
QString name
Definition: restoredata.h:69