MythTV master
importicons.cpp
Go to the documentation of this file.
1// Qt
2#include <QBuffer>
3#include <QCoreApplication>
4#include <QDir>
5#include <QFileInfo>
6#include <QRegularExpression>
7
8// MythTV
11#include "libmythbase/mythdb.h"
23
24// MythTV Setup
25#include "importicons.h"
26
28 int sourceid, QString channelname)
29 :MythScreenType(parent, "ChannelIconImporter"),
30 m_strChannelname(std::move(channelname)), m_fRefresh(fRefresh), m_sourceId(sourceid),
31 m_url(gCoreContext->GetSetting("ServicesRepositoryURL",
32 "https://services.mythtv.org") + "/channel-icon")
33
34{
35 if (!m_strChannelname.isEmpty())
36 {
37 LOG(VB_GENERAL, LOG_INFO,
38 QString("Fetching icon for channel %1").arg(m_strChannelname));
39 }
40 else
41 {
42 LOG(VB_GENERAL, LOG_INFO, "Fetching icons for multiple channels");
43 }
44
45 m_popupStack = GetMythMainWindow()->GetStack("popup stack");
46
47 m_tmpDir = QDir(QString("%1/tmp/icon").arg(GetConfDir()));
48
49 if (!m_tmpDir.exists())
50 m_tmpDir.mkpath(m_tmpDir.absolutePath());
51}
52
54{
55 if (m_tmpDir.exists())
56 {
57 QStringList files = m_tmpDir.entryList();
58 for (const QString &file : std::as_const(files))
59 m_tmpDir.remove(file);
60 m_tmpDir.rmpath(m_tmpDir.absolutePath());
61 }
62}
63
65{
66 // Load the theme for this screen
67 bool foundtheme = LoadWindowFromXML("config-ui.xml", "iconimport", this);
68 if (!foundtheme)
69 return false;
70
71 m_iconsList = dynamic_cast<MythUIButtonList *>(GetChild("icons"));
72 m_manualEdit = dynamic_cast<MythUITextEdit *>(GetChild("manualsearch"));
73 m_nameText = dynamic_cast<MythUIText *>(GetChild("name"));
74 m_manualButton = dynamic_cast<MythUIButton *>(GetChild("search"));
75 m_skipButton = dynamic_cast<MythUIButton *>(GetChild("skip"));
76 m_statusText = dynamic_cast<MythUIText *>(GetChild("status"));
77 m_preview = dynamic_cast<MythUIImage *>(GetChild("preview"));
78 m_previewtitle = dynamic_cast<MythUIText *>(GetChild("previewtitle"));
79
82 {
83 LOG(VB_GENERAL, LOG_ERR,
84 "Unable to load window 'iconimport', missing required element(s)");
85 return false;
86 }
87
88 m_nameText->SetEnabled(false);
89
90 m_nameText->SetHelpText(tr("Name of the icon file"));
91 m_iconsList->SetHelpText(tr("List of possible icon files"));
92 m_manualEdit->SetHelpText(tr("Enter text here for the manual search"));
93 m_manualButton->SetHelpText(tr("Manually search for the text"));
94 m_skipButton->SetHelpText(tr("Skip this icon"));
95
102
104
106
107 return true;
108}
109
111{
113 Close();
114}
115
117{
118 if (m_nMaxCount > 0)
119 {
121 if (!doLoad())
122 {
123 if (!m_strMatches.isEmpty())
125 }
126 }
127}
128
130{
131 switch (state)
132 {
133 case STATE_NORMAL:
135 m_skipButton->SetText(tr("Finish"));
136 else
137 m_skipButton->SetText(tr("Skip"));
139 m_nameText->SetEnabled(true);
140 m_iconsList->SetEnabled(true);
143 break;
144 case STATE_SEARCHING:
145 m_skipButton->SetEnabled(false);
147 m_iconsList->SetEnabled(false);
150 break;
151 case STATE_DISABLED:
152 m_skipButton->SetEnabled(false);
154 m_iconsList->SetEnabled(false);
156 m_nameText->SetEnabled(false);
157 m_nameText->Reset();
158 m_manualEdit->SetEnabled(false);
161 break;
162 }
163}
164
166{
167 QString str = m_manualEdit->GetText();
168 if (!search(str))
169 m_statusText->SetText(tr("No matches found for \"%1\"").arg(str));
170 else
172}
173
175{
178
179 if (!doLoad())
180 {
181 if (!m_strMatches.isEmpty())
183 else
184 Close();
185 }
186}
187
189{
190 if (!item)
191 return;
192
193 auto entry = item->GetData().value<SearchEntry>();
194
195 LOG(VB_GENERAL, LOG_INFO, QString("Menu Selection: %1 %2 %3")
196 .arg(entry.strID, entry.strName, entry.strLogo));
197
199
200 CSVEntry entry2 = (*m_missingIter);
201 m_strMatches += QString("%1,%2,%3,%4,%5,%6,%7,%8,%9\n")
202 .arg(escape_csv(entry.strID),
203 escape_csv(entry2.strName),
204 escape_csv(entry2.strXmlTvId),
205 escape_csv(entry2.strCallsign),
209 escape_csv(entry2.strNetworkId),
210 escape_csv(entry2.strServiceId));
211
212 if (checkAndDownload(entry.strLogo, entry2.strChanId))
213 {
214 m_statusText->SetText(tr("Icon for %1 was downloaded successfully.")
215 .arg(entry2.strName));
216 }
217 else
218 {
219 m_statusText->SetText(tr("Failed to download the icon for %1.")
220 .arg(entry2.strName));
221 }
222
223 if (m_missingMaxCount > 1)
224 {
227 if (!doLoad())
228 {
229 if (!m_strMatches.isEmpty())
231 else
232 Close();
233 }
234 }
235 else
236 {
238
240 if (!m_strMatches.isEmpty())
242 else
243 Close();
244 }
245
246}
247
249{
250 if (!item)
251 return;
252
253 if (m_preview)
254 {
255 m_preview->Reset();
256 QString iconpath = item->GetImageFilename("icon");
257 if (!iconpath.isEmpty())
258 {
259 m_preview->SetFilename(iconpath);
260 m_preview->Load();
261 }
262 }
263
264 if (m_previewtitle)
265 m_previewtitle->SetText(item->GetText("iconname"));
266}
267
268bool ImportIconsWizard::initialLoad(const QString& name)
269{
270
271 QString dirpath = GetConfDir();
272 QDir configDir(dirpath);
273 if (!configDir.exists() && !configDir.mkdir(dirpath))
274 {
275 LOG(VB_GENERAL, LOG_ERR, QString("Could not create %1").arg(dirpath));
276 }
277
278 m_strChannelDir = QString("%1/%2").arg(configDir.absolutePath(),
279 "/channels");
280 QDir strChannelDir(m_strChannelDir);
281 if (!strChannelDir.exists() && !strChannelDir.mkdir(m_strChannelDir))
282 {
283 LOG(VB_GENERAL, LOG_ERR,
284 QString("Could not create %1").arg(m_strChannelDir));
285 }
286 m_strChannelDir += "/";
287
288 bool closeDialog = false;
289
290 QString querystring("SELECT chanid, name, xmltvid, callsign,"
291 "dtv_multiplex.transportid, atsc_major_chan, "
292 "atsc_minor_chan, dtv_multiplex.networkid, "
293 "channel.serviceid, channel.mplexid,"
294 "dtv_multiplex.mplexid, channel.icon, channel.visible "
295 "FROM channel LEFT JOIN dtv_multiplex "
296 "ON channel.mplexid = dtv_multiplex.mplexid "
297 "WHERE deleted IS NULL AND ");
298 if (!name.isEmpty())
299 querystring.append("name=\"" + name + "\"");
300 else
301 querystring.append("channel.visible > 0");
302 if (m_sourceId > 0)
303 querystring.append(QString(" AND channel.sourceid = %1").arg(m_sourceId));
304 querystring.append(" ORDER BY name");
305
307 query.prepare(querystring);
308
309 m_listEntries.clear();
310 m_nCount=0;
311 m_nMaxCount=0;
313
314 if (query.exec() && query.size() > 0)
315 {
317 new MythUIProgressDialog(tr("Initializing, please wait..."),
318 m_popupStack, "IconImportInitProgress");
319
321 {
324 QCoreApplication::processEvents();
325 }
326 else
327 {
328 delete m_progressDialog;
329 m_progressDialog = nullptr;
330 }
331
332 while(query.next())
333 {
334 CSVEntry entry;
335 QString relativeIconPath = query.value(11).toString();
336 QString absoluteIconPath = QString("%1%2").arg(m_strChannelDir,
337 relativeIconPath);
338
339 if (m_fRefresh && !relativeIconPath.isEmpty() &&
340 QFile(absoluteIconPath).exists() &&
341 !QImage(absoluteIconPath).isNull())
342 {
343 LOG(VB_GENERAL, LOG_NOTICE, QString("Icon already exists, skipping (%1)").arg(absoluteIconPath));
344 }
345 else
346 {
347 entry.strChanId=query.value(0).toString();
348 entry.strName=query.value(1).toString();
349 entry.strXmlTvId=query.value(2).toString();
350 entry.strCallsign=query.value(3).toString();
351 entry.strTransportId=query.value(4).toString();
352 entry.strAtscMajorChan=query.value(5).toString();
353 entry.strAtscMinorChan=query.value(6).toString();
354 entry.strNetworkId=query.value(7).toString();
355 entry.strServiceId=query.value(8).toString();
356 entry.strIconCSV= QString("%1,%2,%3,%4,%5,%6,%7,%8,%9\n").
357 arg(escape_csv(entry.strChanId),
358 escape_csv(entry.strName),
359 escape_csv(entry.strXmlTvId),
360 escape_csv(entry.strCallsign),
365 escape_csv(entry.strServiceId));
366 entry.strNameCSV=escape_csv(entry.strName);
367 LOG(VB_CHANNEL, LOG_INFO,
368 QString("chanid %1").arg(entry.strIconCSV));
369
370 m_listEntries.append(entry);
371 }
372
373 m_nMaxCount++;
375 {
377 QCoreApplication::processEvents();
378 }
379 }
380
382 {
384 m_progressDialog = nullptr;
385 }
386 }
387
388 m_iter = m_listEntries.begin();
389
391 tr("Downloading, please wait..."), m_popupStack,
392 "IconImportInitProgress");
393
395 {
398 QCoreApplication::processEvents();
399 }
400 else
401 {
402 delete m_progressDialog;
403 m_progressDialog = nullptr;
404 }
405
406 /* %1 is the current channel name
407 * %2 is the current channel position
408 * %3 is the total number of channels
409 */
410 QString downloadMessage = tr("Downloading %1 (%2 of %3)");
411
412 while (!closeDialog && (m_iter != m_listEntries.end()))
413 {
414 QString message = downloadMessage.arg(m_iter->strName)
415 .arg(m_nCount+1)
416 .arg(m_listEntries.size());
417
418 LOG(VB_GENERAL, LOG_NOTICE, message);
419
420 if (!m_missingEntries.empty())
421 {
422 message.append("\n");
423 message.append(tr("Could not find %n icon(s).", "",
424 m_missingEntries.size()));
425 }
426
427 if (!findmissing((*m_iter).strIconCSV))
428 {
429 m_missingEntries.append((*m_iter));
431 }
432
433 m_nCount++;
434 m_iter++;
436 {
439 QCoreApplication::processEvents();
440 }
441 }
442
444 {
446 m_progressDialog = nullptr;
447 }
448
449 if (m_missingEntries.empty() || closeDialog)
450 return false;
451
452 if (m_nMaxCount <= 0)
453 return false;
454
455 return true;
456}
457
459{
460 LOG(VB_CHANNEL, LOG_INFO, QString("Icons: Found %1 / Missing %2")
462
463 // skip over empty entries
464 while (m_missingIter != m_missingEntries.end() &&
465 (*m_missingIter).strName.isEmpty())
466 {
469 }
470
471 if (m_missingIter == m_missingEntries.end())
472 {
473 LOG(VB_CHANNEL, LOG_INFO, "doLoad Icon search complete");
475 return false;
476 }
477
478 // Look for the next missing icon
479 m_nameText->SetText(tr("Choose icon for channel %1")
480 .arg((*m_missingIter).strName));
481 m_manualEdit->SetText((*m_missingIter).strName);
482 if (!search((*m_missingIter).strName))
483 {
484 m_statusText->SetText(tr("No matches found for %1")
485 .arg((*m_missingIter).strName));
486 }
487 else
488 {
490 }
491
492 return true;
493}
494
495QString ImportIconsWizard::escape_csv(const QString& str)
496{
497 static const QRegularExpression rxDblForEscape("\"");
498 QString str2 = str;
499 str2.replace(rxDblForEscape,"\\\"");
500 return "\""+str2+"\"";
501}
502
503QStringList ImportIconsWizard::extract_csv(const QString &line)
504{
505 QStringList ret;
506 QString str;
507 bool in_comment = false;
508 bool in_escape = false;
509 int comma_count = 0;
510 for (const auto& cur : std::as_const(line))
511 {
512 if (in_escape)
513 {
514 str += cur;
515 in_escape = false;
516 }
517 else if (cur == '"')
518 {
519 in_comment = !in_comment;
520 }
521 else if (cur == '\\')
522 {
523 in_escape = true;
524 }
525 else if (!in_comment && (cur == ','))
526 {
527 ret += str;
528 str.clear();
529 ++comma_count;
530 }
531 else
532 {
533 str += cur;
534 }
535 }
536 if (comma_count)
537 ret += str;
538
539 // This is just to avoid segfaulting, we should add some error recovery
540 while (ret.size() < 5)
541 ret.push_back("");
542
543 return ret;
544}
545
546QString ImportIconsWizard::wget(QUrl& url, const QString& strParam )
547{
548 QByteArray data(strParam.toLatin1());
549
550 auto *req = new QNetworkRequest(url);
551 req->setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
552 req->setHeader(QNetworkRequest::ContentLengthHeader, data.size());
553
554 LOG(VB_CHANNEL, LOG_DEBUG, QString("ImportIconsWizard: posting to: %1, params: %2")
555 .arg(url.toString(), strParam));
556
557 if (GetMythDownloadManager()->post(req, &data))
558 {
559 LOG(VB_CHANNEL, LOG_DEBUG, QString("ImportIconsWizard: result: %1").arg(QString(data)));
560 return {data};
561 }
562
563 return {};
564}
565
566#include <QTemporaryFile>
567bool ImportIconsWizard::checkAndDownload(const QString& url, const QString& localChanId)
568{
569 QString filename = url.section('/', -1);
570 QString filePath = m_strChannelDir + filename;
571
572 // If we get to this point we've already checked whether the icon already
573 // exist locally, we want to download anyway to fix a broken image or
574 // get the latest version of the icon
575
576 QTemporaryFile tmpFile(filePath);
577 if (!tmpFile.open())
578 {
579 LOG(VB_GENERAL, LOG_INFO, "Icon Download: Couldn't create temporary file");
580 return false;
581 }
582
583 bool fRet = GetMythDownloadManager()->download(url, tmpFile.fileName());
584
585 if (!fRet)
586 {
587 LOG(VB_GENERAL, LOG_INFO,
588 QString("Download for icon %1 failed").arg(filename));
589 return false;
590 }
591
592 QImage icon(tmpFile.fileName());
593 if (icon.isNull())
594 {
595 LOG(VB_GENERAL, LOG_INFO,
596 QString("Downloaded icon for %1 isn't a valid image").arg(filename));
597 return false;
598 }
599
600 // Remove any existing icon
601 QFile file(filePath);
602 file.remove();
603
604 // Rename temporary file & prevent it being cleaned up
605 tmpFile.rename(filePath);
606 tmpFile.setAutoRemove(false);
607
609 QString qstr = "UPDATE channel SET icon = :ICON "
610 "WHERE chanid = :CHANID";
611
612 query.prepare(qstr);
613 query.bindValue(":ICON", filename);
614 query.bindValue(":CHANID", localChanId);
615
616 if (!query.exec())
617 {
618 MythDB::DBError("Error inserting channel icon", query);
619 return false;
620 }
621
622 return fRet;
623}
624
625bool ImportIconsWizard::lookup(const QString& strParam)
626{
627 QString strParam1 = QUrl::toPercentEncoding("callsign="+strParam);
628 QUrl url(m_url+"/lookup");
629
630 QString str = wget(url,strParam1);
631 if (str.isEmpty() || str.startsWith("Error", Qt::CaseInsensitive))
632 {
633 LOG(VB_GENERAL, LOG_ERR,
634 QString("Error from icon lookup : %1").arg(str));
635 return true;
636 }
637 LOG(VB_CHANNEL, LOG_INFO,
638 QString("Icon Import: Working lookup : %1").arg(str));
639 return false;
640}
641
642bool ImportIconsWizard::search(const QString& strParam)
643{
644
645 QString strParam1 = QUrl::toPercentEncoding(strParam);
646 bool retVal = false;
648 QUrl url(m_url+"/search");
649
650 CSVEntry entry2 = (*m_missingIter);
651 QString channelcsv = QString("%1,%2,%3,%4,%5,%6,%7,%8\n")
652 .arg(escape_csv(QUrl::toPercentEncoding(entry2.strName)),
653 escape_csv(QUrl::toPercentEncoding(entry2.strXmlTvId)),
654 escape_csv(QUrl::toPercentEncoding(entry2.strCallsign)),
658 escape_csv(entry2.strNetworkId),
659 escape_csv(entry2.strServiceId));
660
661 QString message = QObject::tr("Searching for icons for channel %1")
662 .arg(entry2.strName);
663
664 OpenBusyPopup(message);
665
666 QString str = wget(url,"s="+strParam1+"&csv="+channelcsv);
667 m_listSearch.clear();
669
670 if (str.isEmpty() || str.startsWith("#") ||
671 str.startsWith("Error", Qt::CaseInsensitive))
672 {
673 LOG(VB_GENERAL, LOG_ERR, QString("Error from search : %1").arg(str));
674 retVal = false;
675 }
676 else
677 {
678 LOG(VB_CHANNEL, LOG_INFO,
679 QString("Icon Import: Working search : %1").arg(str));
680 QStringList strSplit = str.split("\n");
681
682 // HACK HACK HACK -- begin
683 // This is needed since the user can't escape out of the progress dialog
684 // and the result set may contain thousands of channels.
685 if (strSplit.size() > 150)
686 {
687 LOG(VB_GENERAL, LOG_WARNING,
688 QString("Warning: Result set contains %1 items, "
689 "truncating to the first %2 results")
690 .arg(strSplit.size()).arg(150));
691 while (strSplit.size() > 150)
692 strSplit.removeLast();
693 }
694 // HACK HACK HACK -- end
695
696 QString prevIconName;
697 int namei = 1;
698
699 for (const QString& row : std::as_const(strSplit))
700 {
701 if (row != "#" )
702 {
703 QStringList ret = extract_csv(row);
704 LOG(VB_CHANNEL, LOG_INFO,
705 QString("Icon Import: search : %1 %2 %3")
706 .arg(ret[0], ret[1], ret[2]));
707 SearchEntry entry;
708 entry.strID = ret[0];
709 entry.strName = ret[1];
710 entry.strLogo = ret[2];
711 m_listSearch.append(entry);
712
713 MythUIButtonListItem *item = nullptr;
714 if (prevIconName == entry.strName)
715 {
716 QString newname = QString("%1 (%2)").arg(entry.strName)
717 .arg(namei);
718 item = new MythUIButtonListItem(m_iconsList, newname,
719 QVariant::fromValue(entry));
720 namei++;
721 }
722 else
723 {
724 item = new MythUIButtonListItem(m_iconsList, entry.strName,
725 QVariant::fromValue(entry));
726 namei=1;
727 }
728
729 QString iconname = entry.strName;
730
731 item->SetImage(entry.strLogo, "icon", false);
732 item->SetText(iconname, "iconname");
733
734 prevIconName = entry.strName;
735 }
736 }
737
738 retVal = true;
739 }
742 return retVal;
743}
744
745bool ImportIconsWizard::findmissing(const QString& strParam)
746{
747 QString strParam1 = QUrl::toPercentEncoding(strParam);
748 QUrl url(m_url+"/findmissing");
749
750 QString str = wget(url,"csv="+strParam1);
751 LOG(VB_CHANNEL, LOG_INFO,
752 QString("Icon Import: findmissing : strParam1 = %1. str = %2")
753 .arg(strParam1, str));
754 if (str.isEmpty() || str.startsWith("#"))
755 {
756 return false;
757 }
758 if (str.startsWith("Error", Qt::CaseInsensitive))
759 {
760 LOG(VB_GENERAL, LOG_ERR,
761 QString("Error from findmissing : %1").arg(str));
762 return false;
763 }
764
765 LOG(VB_CHANNEL, LOG_INFO,
766 QString("Icon Import: Working findmissing : %1") .arg(str));
767 QStringList strSplit = str.split("\n", Qt::SkipEmptyParts);
768 for (const auto& line : std::as_const(strSplit))
769 {
770 if (line[0] == QChar('#'))
771 continue;
772
773 const QStringList ret = extract_csv(line);
774 LOG(VB_CHANNEL, LOG_INFO,
775 QString("Icon Import: findmissing : %1 %2 %3 %4 %5")
776 .arg(ret[0], ret[1], ret[2], ret[3], ret[4]));
777 checkAndDownload(ret[4], (*m_iter).strChanId);
778 }
779 return true;
780}
781
782void ImportIconsWizard::askSubmit(const QString& strParam)
783{
784 m_strParam = strParam;
785 QString message = tr("You now have the opportunity to transmit your "
786 "choices back to mythtv.org so that others can "
787 "benefit from your selections.");
788
789 auto *confirmPopup = new MythConfirmationDialog(m_popupStack, message);
790
791 confirmPopup->SetReturnEvent(this, "submitresults");
792
793 if (confirmPopup->Create())
794 m_popupStack->AddScreen(confirmPopup, false);
795}
796
798{
799 QString strParam1 = QUrl::toPercentEncoding(m_strParam);
800 QUrl url(m_url+"/submit");
801
802 QString str = wget(url,"csv="+strParam1);
803 if (str.isEmpty() || str.startsWith("#") ||
804 str.startsWith("Error", Qt::CaseInsensitive))
805 {
806 LOG(VB_GENERAL, LOG_ERR, QString("Error from submit : %1").arg(str));
807 m_statusText->SetText(tr("Failed to submit icon choices."));
808 return false;
809 }
810
811 LOG(VB_CHANNEL, LOG_INFO, QString("Icon Import: Working submit : %1")
812 .arg(str));
813 QStringList strSplit = str.split("\n", Qt::SkipEmptyParts);
814 unsigned atsc = 0;
815 unsigned dvb = 0;
816 unsigned callsign = 0;
817 unsigned tv = 0;
818 unsigned xmltvid = 0;
819 for (const auto& line : std::as_const(strSplit))
820 {
821 if (line[0] == QChar('#'))
822 continue;
823
824 QStringList strSplit2=(line).split(":", Qt::SkipEmptyParts);
825 if (strSplit2.size() < 2)
826 continue;
827
828 QString s = strSplit2[0].trimmed();
829 if (s == "a")
830 atsc = strSplit2[1].toUInt();
831 else if (s == "c")
832 callsign = strSplit2[1].toUInt();
833 else if (s == "d")
834 dvb = strSplit2[1].toUInt();
835 else if (s == "t")
836 tv = strSplit2[1].toUInt();
837 else if (s == "x")
838 xmltvid = strSplit2[1].toUInt();
839 }
840 LOG(VB_CHANNEL, LOG_INFO,
841 QString("Icon Import: working submit : atsc=%1 callsign=%2 "
842 "dvb=%3 tv=%4 xmltvid=%5")
843 .arg(atsc).arg(callsign).arg(dvb).arg(tv).arg(xmltvid));
844 m_statusText->SetText(tr("Icon choices submitted successfully."));
845 return true;
846}
847
849{
850 if (event->type() == DialogCompletionEvent::kEventType)
851 {
852 auto *dce = (DialogCompletionEvent*)(event);
853
854 QString resultid = dce->GetId();
855 int buttonnum = dce->GetResult();
856
857 if (resultid == "submitresults")
858 {
859 switch (buttonnum)
860 {
861 case 0 :
862 Close();
863 break;
864 case 1 :
865 submit();
866 Close();
867 break;
868 }
869 }
870 }
871}
872
874{
876}
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
static const Type kEventType
Definition: mythdialogbox.h:56
bool m_fRefresh
are we doing a refresh or not
Definition: importicons.h:171
MythUITextEdit * m_manualEdit
manual edit field
Definition: importicons.h:188
ListEntriesIter m_iter
the current iterator
Definition: importicons.h:81
int m_missingCount
the current search point (0..m_missingCount)
Definition: importicons.h:175
void menuSelection(MythUIButtonListItem *item)
process the icon selection
bool checkAndDownload(const QString &url, const QString &localChanId)
checks and attempts to download the logo file to the appropriate place
bool findmissing(const QString &strParam)
retrieve the actual logo for the TV channel
QString m_strChannelDir
the location of the channel icon dir
Definition: importicons.h:167
void customEvent(QEvent *event) override
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
MythUIProgressDialog * m_progressDialog
Definition: importicons.h:185
MythUIText * m_nameText
name field for the icon
Definition: importicons.h:189
bool doLoad()
attempts to move the iteration on one/more than one
void skip()
skip this icon
void askSubmit(const QString &strParam)
int m_nMaxCount
the maximum number of TV channels
Definition: importicons.h:172
void manualSearch()
process the manual search
MythUIText * m_statusText
Definition: importicons.h:192
MythScreenStack * m_popupStack
Definition: importicons.h:184
ListEntries m_missingEntries
list of TV channels with no unique icon
Definition: importicons.h:80
static QString escape_csv(const QString &str)
changes a string into csv format
int m_missingMaxCount
the total number of missing icons
Definition: importicons.h:174
MythUIButton * m_manualButton
manual button field
Definition: importicons.h:190
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
ListSearchEntries m_listSearch
the list of SearchEntry
Definition: importicons.h:164
bool Create(void) override
Definition: importicons.cpp:64
bool lookup(const QString &strParam)
looks up the string to determine the caller/xmltvid
void itemChanged(MythUIButtonListItem *item)
MythUIButton * m_skipButton
button skip
Definition: importicons.h:191
~ImportIconsWizard() override
Definition: importicons.cpp:53
static QStringList extract_csv(const QString &strLine)
extracts the csv values out of a string
ImportIconsWizard(MythScreenStack *parent, bool fRefresh, int sourceid=0, QString channelname="")
Definition: importicons.cpp:27
bool initialLoad(const QString &name="")
attempt the inital load of the TV channel information
const QString m_url
Definition: importicons.h:179
void enableControls(ImportIconsWizard::dialogState state=STATE_NORMAL)
enable/disable the controls
void Close() override
ListEntriesIter m_missingIter
Definition: importicons.h:82
ListEntries m_listEntries
list of TV channels to search for
Definition: importicons.h:79
MythUIImage * m_preview
Definition: importicons.h:194
MythUIText * m_previewtitle
Definition: importicons.h:195
static QString wget(QUrl &url, const QString &strParam)
use the equivalent of wget to fetch the POST command
int m_nCount
the current search point (0..m_nMaxCount)
Definition: importicons.h:173
QString m_strChannelname
the channel name if searching for a single channel icon
Definition: importicons.h:168
MythUIButtonList * m_iconsList
list of potential icons
Definition: importicons.h:187
bool submit()
submit the icon information back to the remote db
int m_sourceId
selected video source or 0 for all sources
Definition: importicons.h:176
QString m_strMatches
the string for the submit() call
Definition: importicons.h:165
bool search(const QString &strParam)
search the remote db for icons etc
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
QVariant value(int i) const
Definition: mythdbcon.h:204
int size(void) const
Definition: mythdbcon.h:214
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
Dialog asking for user confirmation.
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
bool download(const QString &url, const QString &dest, bool reload=false)
Downloads a URL to a file in blocking mode.
MythScreenStack * GetStack(const QString &Stackname)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void OpenBusyPopup(const QString &message="")
void BuildFocusList(void)
bool SetFocusWidget(MythUIType *widget=nullptr)
void CloseBusyPopup(void)
virtual void Close()
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
QString GetImageFilename(const QString &name="") const
QString GetText(const QString &name="") const
void SetText(const QString &text, const QString &name="", const QString &state="")
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
void itemClicked(MythUIButtonListItem *item)
void itemSelected(MythUIButtonListItem *item)
A single button widget.
Definition: mythuibutton.h:22
void SetText(const QString &msg)
void Clicked()
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:98
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
void Reset(void) override
Reset the image back to the default defined in the theme.
bool Create(void) override
void SetProgress(uint count)
void SetMessage(const QString &message)
A text entry and edit widget.
QString GetText(void) const
void SetText(const QString &text, bool moveCursor=true)
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
All purpose text widget, displays a text string.
Definition: mythuitext.h:29
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:65
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
void SetEnabled(bool enable)
void SetHelpText(const QString &text)
Definition: mythuitype.h:177
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString GetConfDir(void)
Definition: mythdirs.cpp:263
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
STL namespace.
bool exists(str path)
Definition: xbmcvfs.py:51
describes the TV channel name
Definition: importicons.h:61
QString strAtscMinorChan
ATSC minor number.
Definition: importicons.h:68
QString strAtscMajorChan
ATSC major number.
Definition: importicons.h:67
QString strServiceId
service id
Definition: importicons.h:70
QString strTransportId
transport id
Definition: importicons.h:66
QString strNetworkId
network id
Definition: importicons.h:69
QString strChanId
local channel id
Definition: importicons.h:62
QString strIconCSV
icon name (csv form)
Definition: importicons.h:71
QString strXmlTvId
the xmltvid
Definition: importicons.h:64
QString strName
channel name
Definition: importicons.h:63
QString strCallsign
callsign
Definition: importicons.h:65
QString strNameCSV
name (csv form)
Definition: importicons.h:72
search entry results
Definition: importicons.h:45
QString strName
the remote name
Definition: importicons.h:47
QString strLogo
the actual logo
Definition: importicons.h:48
QString strID
the remote channel id
Definition: importicons.h:46