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