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