MythTV  master
proglist.cpp
Go to the documentation of this file.
1 
2 #include "proglist.h"
3 
4 // C/C++
5 #include <algorithm>
6 #include <functional>
7 #include <deque> // for _Deque_iterator, operator-, etc
8 #include <iterator> // for reverse_iterator
9 using namespace std;
10 
11 // Qt
12 #include <QCoreApplication>
13 #include <QLocale>
14 #include <QRegExp>
15 #include <utility>
16 
17 // MythTV
18 #include "mythmiscutil.h"
19 #include "scheduledrecording.h"
20 #include "mythuibuttonlist.h"
21 #include "mythuistatetype.h"
22 #include "mythcorecontext.h"
23 #include "mythdialogbox.h"
24 #include "recordinginfo.h"
25 #include "recordingrule.h"
26 #include "channelinfo.h"
27 #include "channelutil.h"
28 #include "mythuitext.h"
29 #include "tv_actions.h" // for ACTION_CHANNELSEARCH
30 #include "mythdb.h"
31 #include "mythdate.h"
32 
33 #define LOC QString("ProgLister: ")
34 #define LOC_WARN QString("ProgLister, Warning: ")
35 #define LOC_ERR QString("ProgLister, Error: ")
36 
38  QString view, QString extraArg,
39  QDateTime selectedTime) :
40  ScheduleCommon(parent, "ProgLister"),
41  m_type(pltype),
42  m_extraArg(std::move(extraArg)),
43  m_startTime(MythDate::current()),
44  m_searchTime(m_startTime),
45  m_selectedTime(std::move(selectedTime)),
46  m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
47  m_view(std::move(view))
48 {
49  if (pltype == plMovies)
50  {
52  query.prepare("SELECT COUNT(*) FROM program WHERE stars > 0");
53 
54  if (query.exec() && query.next())
55  {
56  if (query.value(0).toInt() == 0) // No ratings in database
57  {
58  m_curView = 0; // Show All
59  m_allowViewDialog = false;
60  }
61  }
62  }
63 
64  switch (pltype)
65  {
69  case plPowerSearch:
70  case plSQLSearch:
72  default: m_searchType = kNoSearch; break;
73  }
74 }
75 
76 // previously recorded ctor
78  MythScreenStack *parent, uint recid, QString title) :
79  ScheduleCommon(parent, "PreviousList"),
80  m_type(plPreviouslyRecorded),
81  m_recid(recid),
82  m_title(std::move(title)),
83  m_startTime(MythDate::current()),
84  m_searchTime(m_startTime),
85  m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
86  m_view("reverse time"),
87  m_reverseSort(true)
88 {
89 }
90 
92 {
93  m_itemList.clear();
96 }
97 
99 {
100  if (!LoadWindowFromXML("schedule-ui.xml", "programlist", this))
101  return false;
102 
103  bool err = false;
104  UIUtilW::Assign(this, m_curviewText, "curview", &err);
105  UIUtilE::Assign(this, m_progList, "proglist", &err);
106  UIUtilW::Assign(this, m_schedText, "sched", &err);
107  UIUtilW::Assign(this, m_messageText, "msg", &err);
108  UIUtilW::Assign(this, m_positionText, "position", &err);
109 
110  if (err)
111  {
112  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'programlist'");
113  return false;
114  }
115 
116  connect(m_progList, SIGNAL(itemSelected(MythUIButtonListItem*)),
117  this, SLOT( HandleSelected( MythUIButtonListItem*)));
118 
119  connect(m_progList, SIGNAL(itemVisible(MythUIButtonListItem*)),
120  this, SLOT( HandleVisible( MythUIButtonListItem*)));
121 
122  connect(m_progList, SIGNAL(itemLoaded(MythUIButtonListItem*)),
123  this, SLOT( HandleVisible( MythUIButtonListItem*)));
124 
126  {
127  connect(m_progList, SIGNAL(itemClicked(MythUIButtonListItem*)),
128  this, SLOT( ShowOldRecordedMenu()));
129  }
130  else
131  {
132  connect(m_progList, SIGNAL(itemClicked(MythUIButtonListItem*)),
133  this, SLOT( EditRecording()));
134  }
135 
136  m_progList->SetLCDTitles(tr("Program List"), "title|channel|shortstarttimedate");
137  m_progList->SetSearchFields("titlesubtitle");
138 
139  BuildFocusList();
140 
141  QString value;
142  switch (m_type)
143  {
144  case plTitle: value = tr("Program Listings"); break;
145  case plNewListings: value = tr("New Title Search"); break;
146  case plTitleSearch: value = tr("Title Search"); break;
147  case plKeywordSearch: value = tr("Keyword Search"); break;
148  case plPeopleSearch: value = tr("People Search"); break;
149  case plStoredSearch: value = tr("Stored Search"); break;
150  case plPowerSearch:
151  case plSQLSearch: value = tr("Power Search"); break;
152  case plRecordid: value = tr("Rule Search"); break;
153  case plCategory: value = tr("Category Search"); break;
154  case plChannel: value = tr("Channel Search"); break;
155  case plMovies: value = tr("Movie Search"); break;
156  case plTime: value = tr("Time Search"); break;
157  case plPreviouslyRecorded: value = tr("Previously Recorded"); break;
158  default: value = tr("Unknown Search"); break;
159  }
160 
161  if (m_schedText)
162  m_schedText->SetText(value);
163 
164  gCoreContext->addListener(this);
165 
167 
168  return true;
169 }
170 
172 {
173  if (m_viewList.isEmpty() || m_curView < 0)
175 
176  FillItemList(false, false);
177 
178  auto *slce = new ScreenLoadCompletionEvent(objectName());
179  QCoreApplication::postEvent(this, slce);
180 }
181 
182 bool ProgLister::keyPressEvent(QKeyEvent *e)
183 {
184  if (!m_allowEvents)
185  return true;
186 
188  {
189  m_allowEvents = true;
190  return true;
191  }
192 
193  m_allowEvents = false;
194 
195  QStringList actions;
196  bool handled = GetMythMainWindow()->TranslateKeyPress(
197  "TV Frontend", e, actions);
198 
199  bool needUpdate = false;
200  for (uint i = 0; i < uint(actions.size()) && !handled; ++i)
201  {
202  QString action = actions[i];
203  handled = true;
204 
205  if (action == "PREVVIEW")
207  else if (action == "NEXTVIEW")
209  else if (action == "CUSTOMEDIT")
210  EditCustom();
211  else if (action == "EDIT")
212  EditScheduled();
213  else if (action == "DELETE")
215  else if (action == "UPCOMING" && m_type != plTitle)
216  ShowUpcoming();
217  else if (action == "PREVRECORDED" && m_type != plPreviouslyRecorded)
218  ShowPrevious();
219  else if (action == "DETAILS" || action == "INFO")
220  ShowDetails();
221  else if (action == "GUIDE")
222  ShowGuide();
223  else if (action == ACTION_CHANNELSEARCH && m_type != plChannel)
225  else if (action == "TOGGLERECORD")
226  QuickRecord();
227  else if (action == "1")
228  {
229  if (m_titleSort)
230  {
231  m_titleSort = false;
233  }
234  else
235  {
237  }
238  needUpdate = true;
239  }
240  else if (action == "2")
241  {
242  if (!m_titleSort)
243  {
244  m_titleSort = true;
245  m_reverseSort = false;
246  }
247  else
248  {
250  }
251  needUpdate = true;
252  }
253  else
254  {
255  handled = false;
256  }
257  }
258 
259  if (!handled && MythScreenType::keyPressEvent(e))
260  handled = true;
261 
262  if (needUpdate)
264 
265  m_allowEvents = true;
266 
267  return handled;
268 }
269 
271 {
272  auto *sortMenu = new MythMenu(tr("Sort Options"), this, "sortmenu");
273  sortMenu->AddItem(tr("Reverse Sort Order"));
274  sortMenu->AddItem(tr("Sort By Title"));
275  sortMenu->AddItem(tr("Sort By Time"));
276 
277  auto *menu = new MythMenu(tr("Options"), this, "menu");
278 
280  {
281  menu->AddItem(tr("Choose Search Phrase..."), SLOT(ShowChooseViewMenu()));
282  }
283 
284  menu->AddItem(tr("Sort"), nullptr, sortMenu);
285 
287  menu->AddItem(tr("Record"), SLOT(QuickRecord()));
288 
289  menu->AddItem(tr("Edit Schedule"), SLOT(EditScheduled()));
290  menu->AddItem(tr("Program Details"), SLOT(ShowDetails()));
291  menu->AddItem(tr("Program Guide"), SLOT(ShowGuide()));
292  if (m_type != plChannel)
293  menu->AddItem(tr("Channel Search"), SLOT(ShowChannelSearch()));
294  if (m_type != plTitle)
295  menu->AddItem(tr("Upcoming"), SLOT(ShowUpcoming()));
297  menu->AddItem(tr("Previously Recorded"),SLOT(ShowPrevious()));
298  menu->AddItem(tr("Custom Edit"), SLOT(EditCustom()));
299 
302  {
303  if (pi && pi->GetRecordingRuleID())
304  menu->AddItem(tr("Delete Rule"), SLOT(ShowDeleteRuleMenu()));
305  }
306  else
307  {
308  menu->AddItem(
309  tr("Delete Episode"), SLOT(ShowDeleteOldEpisodeMenu()));
310  }
311 
312  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
313  auto *menuPopup = new MythDialogBox(menu, popupStack, "menuPopup");
314 
315  if (!menuPopup->Create())
316  {
317  delete menuPopup;
318  return;
319  }
320 
321  popupStack->AddScreen(menuPopup);
322 }
323 
325 {
326  if (m_type == plTime && !m_viewList.empty() && !m_viewTextList.empty())
327  {
328  m_searchTime = m_searchTime.addSecs(-3600);
329  m_curView = 0;
334  return;
335  }
336 
337  if (m_viewList.size() <= 1)
338  return;
339 
340  m_curView--;
341  if (m_curView < 0)
342  m_curView = m_viewList.size() - 1;
343 
345 }
346 
348 {
349  if (m_type == plTime && !m_viewList.empty() && !m_viewTextList.empty())
350  {
351  m_searchTime = m_searchTime.addSecs(3600);
352  m_curView = 0;
357 
358  return;
359  }
360 
361  if (m_viewList.size() <= 1)
362  return;
363 
364  m_curView++;
365  if (m_curView >= m_viewList.size())
366  m_curView = 0;
367 
369 }
370 
371 void ProgLister::UpdateKeywordInDB(const QString &text, const QString &oldValue)
372 {
373  int oldview = m_viewList.indexOf(oldValue);
374  int newview = m_viewList.indexOf(text);
375 
376  if (newview >= 0 && newview == oldview)
377  return;
378 
379  if (oldview >= 0)
380  {
381  QString qphrase = m_viewList[oldview];
382 
384  query.prepare("DELETE FROM keyword "
385  "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
386  query.bindValue(":PHRASE", qphrase);
387  query.bindValue(":TYPE", m_searchType);
388  if (!query.exec())
389  {
391  "ProgLister::updateKeywordInDB -- delete", query);
392  }
393  m_viewList.removeAll(qphrase);
394  m_viewTextList.removeAll(qphrase);
395  }
396 
397  if (newview < 0)
398  {
399  const QString& qphrase = text;
400 
402  query.prepare("REPLACE INTO keyword (phrase, searchtype)"
403  "VALUES(:PHRASE, :TYPE );");
404  query.bindValue(":PHRASE", qphrase);
405  query.bindValue(":TYPE", m_searchType);
406  if (!query.exec())
407  {
409  "ProgLister::updateKeywordInDB -- replace", query);
410  }
411  m_viewList.push_back(qphrase);
412  m_viewTextList.push_back(qphrase);
413  }
414 }
415 
417 {
418  MythScreenStack *popupStack =
419  GetMythMainWindow()->GetStack("popup stack");
420  MythScreenType *screen = nullptr;
421  bool connect_string = true;
422 
423  switch (m_type)
424  {
425  case plChannel:
426  case plCategory:
427  case plMovies:
428  case plNewListings:
429  case plStoredSearch:
430  {
431  if (m_viewList.empty())
432  return;
433 
434  QString msg;
435  switch (m_type)
436  {
437  case plMovies: msg = tr("Select Rating"); break;
438  case plChannel: msg = tr("Select Channel"); break;
439  case plCategory: msg = tr("Select Category"); break;
440  case plNewListings: msg = tr("Select List"); break;
441  case plStoredSearch: msg = QString("%1\n%2")
442  .arg(tr("Select a search stored from"))
443  .arg(tr("Custom Record")); break;
444  default: // silence warning
445  break;
446  }
447 
448  screen = new MythUISearchDialog(
449  popupStack, msg, m_viewTextList, true, "");
450 
451  break;
452  }
453  case plTitleSearch:
454  case plKeywordSearch:
455  case plPeopleSearch:
456  screen = new PhrasePopup(
457  popupStack, this, m_searchType, m_viewTextList,
458  (m_curView >= 0) ? m_viewList[m_curView] : QString());
459  break;
460  case plPowerSearch:
461  screen = new PowerSearchPopup(
462  popupStack, this, m_searchType, m_viewTextList,
463  (m_curView >= 0) ? m_viewList[m_curView] : QString());
464  break;
465  case plTime:
466  {
467  QString message = tr("Start search from date and time");
468  int flags = (MythTimeInputDialog::kDay |
471  screen = new MythTimeInputDialog(popupStack, message, flags);
472  connect_string = false;
473  break;
474  }
475  case plRecordid:
477  case plUnknown:
478  case plTitle:
479  case plSQLSearch:
480  break;
481  }
482 
483  if (!screen)
484  return;
485 
486  if (!screen->Create())
487  {
488  delete screen;
489  return;
490  }
491 
492  if (connect_string)
493  {
494  connect(screen, SIGNAL(haveResult( QString)),
495  this, SLOT( SetViewFromList(QString)));
496  }
497  else
498  {
499  connect(screen, SIGNAL(haveResult( QDateTime)),
500  this, SLOT( SetViewFromTime(QDateTime)));
501  }
502 
503  popupStack->AddScreen(screen);
504 }
505 
506 void ProgLister::SetViewFromTime(QDateTime searchTime)
507 {
508  if (m_viewList.empty() || m_viewTextList.empty())
509  return;
510 
511  m_searchTime = std::move(searchTime);
512  m_curView = 0;
516 
518 }
519 
520 void ProgLister::SetViewFromList(const QString& item)
521 {
522  m_curView = m_viewTextList.indexOf(item);
523  if (m_curView >= 0)
525 }
526 
528  const QString &qphrase, QString &output, MSqlBindings &bindings)
529 {
530  output.clear();
531 
532  QStringList field = qphrase.split(':');
533  if (field.size() != 6)
534  {
535  LOG(VB_GENERAL, LOG_ERR, LOC + "Power search should have 6 fields," +
536  QString("\n\t\t\tnot %1 (%2)") .arg(field.size()).arg(qphrase));
537  return false;
538  };
539 
540  static const QString kBindingList[6] =
541  {
542  ":POWERTITLE",
543  ":POWERSUB",
544  ":POWERDESC",
545  ":POWERCATTYPE",
546  ":POWERGENRE",
547  ":POWERCALLSIGN",
548  };
549 
550  static const QString kOutputList[6] =
551  {
552  "program.title LIKE :POWERTITLE ",
553  "program.subtitle LIKE :POWERSUB ",
554  "program.description LIKE :POWERDESC ",
555  "program.category_type = :POWERCATTYPE ",
556  "programgenres.genre = :POWERGENRE ",
557  "channel.callsign = :POWERCALLSIGN ",
558  };
559 
560  for (uint i = 0; i < (uint) field.size(); i++)
561  {
562  if (field[i].isEmpty())
563  continue;
564 
565  if (!output.isEmpty())
566  output += "\nAND ";
567 
568  output += kOutputList[i];
569  bindings[kBindingList[i]] =
570  (!kOutputList[i].contains("=")) ?
571  QString('%') + field[i] + QString('%') : field[i];
572  }
573 
574  return output.contains("programgenres");
575 }
576 
578 {
579  int pos = m_progList->GetCurrentPos();
580  if (pos >= 0 && pos < (int) m_itemList.size())
581  return m_itemList[pos];
582  return nullptr;
583 }
584 
586 {
589  else
591 }
592 
594 {
596 
597  if (!pi || !pi->GetRecordingRuleID())
598  return;
599 
600  auto *record = new RecordingRule();
601  if (!record->LoadByProgram(pi))
602  {
603  delete record;
604  return;
605  }
606 
607  QString message = tr("Delete '%1' %2 rule?").arg(record->m_title)
608  .arg(toString(pi->GetRecordingRuleType()));
609 
610  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
611 
612  auto *okPopup = new MythConfirmationDialog(
613  popupStack, message, true);
614 
615  okPopup->SetReturnEvent(this, "deleterule");
616  okPopup->SetData(QVariant::fromValue(record));
617 
618  if (okPopup->Create())
619  popupStack->AddScreen(okPopup);
620  else
621  delete okPopup;
622 }
623 
625 {
627 
628  if (!pi)
629  return;
630 
631  QString message = tr("Delete this episode of '%1'?").arg(pi->GetTitle());
632 
633  ShowOkPopup(message, this, SLOT(DeleteOldEpisode(bool)), true);
634 }
635 
637 {
639  if (!ok || !pi)
640  return;
641 
643  query.prepare(
644  "DELETE FROM oldrecorded "
645  "WHERE chanid = :CHANID AND "
646  " starttime = :STARTTIME");
647  query.bindValue(":CHANID", pi->GetChanID());
648  query.bindValue(":STARTTIME", pi->GetScheduledStartTime());
649 
650  if (!query.exec())
651  MythDB::DBError("ProgLister::DeleteOldEpisode", query);
652 
653  ScheduledRecording::RescheduleCheck(*pi, "DeleteOldEpisode");
654  FillItemList(true);
655 }
656 
658 {
660 
661  if (!pi)
662  return;
663 
664  QString message = tr("Delete all episodes of '%1'?").arg(pi->GetTitle());
665 
666  ShowOkPopup(message, this, SLOT(DeleteOldSeries(bool)), true);
667 }
668 
670 {
672  if (!ok || !pi)
673  return;
674 
676  query.prepare("DELETE FROM oldrecorded "
677  "WHERE title = :TITLE AND future = 0");
678  query.bindValue(":TITLE", pi->GetTitle());
679  if (!query.exec())
680  MythDB::DBError("ProgLister::DeleteOldSeries -- delete", query);
681 
682  // Set the programid to the special value of "**any**" which the
683  // scheduler recognizes to mean the entire series was deleted.
684  RecordingInfo tempri(*pi);
685  tempri.SetProgramID("**any**");
686  ScheduledRecording::RescheduleCheck(tempri, "DeleteOldSeries");
687  FillItemList(true);
688 }
689 
691 {
693 
694  if (!pi)
695  return;
696 
697  QString message = pi->toString(ProgramInfo::kTitleSubtitle, " - ");
698 
699  if (!pi->GetDescription().isEmpty())
700  message += "\n\n" + pi->GetDescription();
701 
702  message += "\n\n\n" + tr("NOTE: removing items from this list will not "
703  "delete any recordings.");
704 
705  QString title = tr("Previously Recorded");
706 
707  auto *menu = new MythMenu(title, message, this, "deletemenu");
708  if (pi->IsDuplicate())
709  menu->AddItem(tr("Allow this episode to re-record"));
710  else
711  menu->AddItem(tr("Never record this episode"));
712  menu->AddItem(tr("Remove this episode from the list"));
713  menu->AddItem(tr("Remove all episodes for this title"));
714  menu->AddItem(tr("Cancel"));
715 
717  auto *menuPopup = new MythDialogBox(menu, mainStack, "deletepopup", true);
718 
719  if (menuPopup->Create())
720  mainStack->AddScreen(menuPopup);
721  else
722  delete menuPopup;
723 }
724 
725 void ProgLister::FillViewList(const QString &view)
726 {
727  m_viewList.clear();
728  m_viewTextList.clear();
729 
730  if (m_type == plChannel) // list by channel
731  {
733  0, true, "channum, chanid");
735 
736  for (auto & channel : channels)
737  {
738  QString chantext = channel.GetFormatted(ChannelInfo::kChannelShort);
739 
740  m_viewList.push_back(QString::number(channel.m_chanId));
741  m_viewTextList.push_back(chantext);
742  }
743 
744  if (!view.isEmpty())
745  m_curView = m_viewList.indexOf(view);
746  }
747  else if (m_type == plCategory) // list by category
748  {
749  QDateTime query_starttime = m_startTime.addSecs(50 -
750  m_startTime.time().second());
752  query.prepare("SELECT g1.genre, g2.genre "
753  "FROM program "
754  "JOIN programgenres g1 ON "
755  " program.chanid = g1.chanid AND "
756  " program.starttime = g1.starttime "
757  "LEFT JOIN programgenres g2 ON "
758  " g1.chanid = g2.chanid AND "
759  " g1.starttime = g2.starttime "
760  "WHERE program.endtime > :PGILSTART "
761  "GROUP BY g1.genre, g2.genre;");
762  query.bindValue(":PGILSTART", query_starttime);
763 
764  m_useGenres = false;
765 
766  if (query.exec())
767  {
768  QString lastGenre1;
769 
770  while (query.next())
771  {
772  m_useGenres = true;
773 
774  QString genre1 = query.value(0).toString();
775  if (genre1.isEmpty())
776  continue;
777 
778  if (genre1 != lastGenre1)
779  {
780  m_viewList.push_back(genre1);
781  m_viewTextList.push_back(genre1);
782  lastGenre1 = genre1;
783  }
784 
785  QString genre2 = query.value(1).toString();
786  if (genre2.isEmpty() || genre2 == genre1)
787  continue;
788 
789  m_viewList.push_back(genre1 + ":/:" + genre2);
790  m_viewTextList.push_back(" " + genre1 + " / " + genre2);
791  }
792  }
793 
794  if (!m_useGenres)
795  {
796  query.prepare("SELECT category "
797  "FROM program "
798  "WHERE program.endtime > :PGILSTART "
799  "GROUP BY category");
800  query.bindValue(":PGILSTART", query_starttime);
801 
802  if (query.exec())
803  {
804  while (query.next())
805  {
806  QString category = query.value(0).toString();
807  if (category.isEmpty())
808  continue;
809  category = query.value(0).toString();
810  m_viewList.push_back(category);
811  m_viewTextList.push_back(category);
812  }
813  }
814  }
815 
816  if (!view.isEmpty())
817  m_curView = m_viewList.indexOf(view);
818  }
819  else if (m_type == plTitleSearch || m_type == plKeywordSearch ||
821  {
823  query.prepare("SELECT phrase FROM keyword "
824  "WHERE searchtype = :SEARCHTYPE;");
825  query.bindValue(":SEARCHTYPE", m_searchType);
826 
827  if (query.exec())
828  {
829  while (query.next())
830  {
831  /* The keyword.phrase column uses utf8_bin collation, so
832  * Qt uses QString::fromAscii() for toString(). Explicitly
833  * convert the value using QString::fromUtf8() to prevent
834  * corruption. */
835  QString phrase = QString::fromUtf8(query.value(0)
836  .toByteArray().constData());
837  if (phrase.isEmpty())
838  continue;
839  m_viewList.push_back(phrase);
840  m_viewTextList.push_back(phrase);
841  }
842  }
843 
844  if (!view.isEmpty())
845  {
846  m_curView = m_viewList.indexOf(view);
847 
848  if (m_curView < 0)
849  {
850  const QString& qphrase = view;
851 
852  MSqlQuery query2(MSqlQuery::InitCon());
853  query2.prepare("REPLACE INTO keyword (phrase, searchtype)"
854  "VALUES(:VIEW, :SEARCHTYPE );");
855  query2.bindValue(":VIEW", qphrase);
856  query2.bindValue(":SEARCHTYPE", m_searchType);
857  if (!query2.exec())
858  MythDB::DBError("ProgLister::FillViewList -- "
859  "replace keyword", query2);
860 
861  m_viewList.push_back(qphrase);
862  m_viewTextList.push_back(qphrase);
863 
864  m_curView = m_viewList.size() - 1;
865  }
866  }
867  else
868  {
869  m_curView = -1;
870  }
871  }
872  else if (m_type == plTitle)
873  {
874  if (!view.isEmpty())
875  {
876  m_viewList.push_back(view);
877  m_viewTextList.push_back(view);
878  m_curView = 0;
879  }
880  else
881  {
882  m_curView = -1;
883  }
884  }
885  else if (m_type == plNewListings)
886  {
887  m_viewList.push_back("all");
888  m_viewTextList.push_back(tr("All"));
889 
890  m_viewList.push_back("premieres");
891  m_viewTextList.push_back(tr("Premieres"));
892 
893  m_viewList.push_back("movies");
894  m_viewTextList.push_back(tr("Movies"));
895 
896  m_viewList.push_back("series");
897  m_viewTextList.push_back(tr("Series"));
898 
899  m_viewList.push_back("specials");
900  m_viewTextList.push_back(tr("Specials"));
901 
902  if (!view.isEmpty())
903  m_curView = m_viewList.indexOf(view);
904  }
905  else if (m_type == plMovies)
906  {
907  m_viewList.push_back(">= 0.0");
908  m_viewTextList.push_back(tr("All"));
909  m_viewList.push_back("= 0.0");
910  m_viewTextList.push_back(tr("Unrated"));
911  m_viewList.push_back(QString(">= %1").arg((10 - 0.5) / 10.0 - 0.001));
912  m_viewTextList.push_back(tr("%n star(s)", "", 10));
913  for (int i = 9; i > 0; i--)
914  {
915  float stars = (i - 0.5 ) / 10.0 - 0.001;
916  m_viewList.push_back(QString(">= %1").arg(stars));
917  m_viewTextList.push_back(tr("%n star(s) and above", "", i));
918  }
919 
920  if (!view.isEmpty())
921  m_curView = m_viewList.indexOf(view);
922  }
923  else if (m_type == plTime)
924  {
925  m_curView = 0;
928  m_viewTextList.push_back(m_viewList[m_curView]);
929  }
930  else if (m_type == plSQLSearch)
931  {
932  m_curView = 0;
933  m_viewList.push_back(view);
934  m_viewTextList.push_back(tr("Power Recording Rule"));
935  }
936  else if (m_type == plRecordid)
937  {
938  m_curView = 0;
939 
941  query.prepare("SELECT title FROM record "
942  "WHERE recordid = :RECORDID");
943  query.bindValue(":RECORDID", view);
944 
945  if (query.exec() && query.next())
946  {
947  QString title = query.value(0).toString();
948  m_viewList.push_back(view);
949  m_viewTextList.push_back(title);
950  }
951  }
952  else if (m_type == plStoredSearch) // stored searches
953  {
955  query.prepare("SELECT rulename FROM customexample "
956  "WHERE search > 0 ORDER BY rulename;");
957 
958  if (query.exec())
959  {
960  while (query.next())
961  {
962  QString rulename = query.value(0).toString();
963  if (rulename.isEmpty() || rulename.trimmed().isEmpty())
964  continue;
965  rulename = query.value(0).toString();
966  m_viewList.push_back(rulename);
967  m_viewTextList.push_back(rulename);
968  }
969  }
970  if (!view.isEmpty())
971  m_curView = m_viewList.indexOf(view);
972  }
973  else if (m_type == plPreviouslyRecorded) // previously recorded
974  {
975  m_viewList.push_back("sort by time");
976  m_viewTextList.push_back(tr("Time"));
977 
978  m_viewList.push_back("reverse time");
979  m_viewTextList.push_back(tr("Reverse Time"));
980 
981  m_viewList.push_back("sort by title");
982  m_viewTextList.push_back(tr("Title"));
983 
984  m_viewList.push_back("reverse title");
985  m_viewTextList.push_back(tr("Reverse Title"));
986 
987  if (!view.isEmpty())
988  m_curView = m_viewList.indexOf(view);
989  }
990 
991  if (m_curView >= m_viewList.size())
992  m_curView = m_viewList.size() - 1;
993 }
994 
995 class plCompare : binary_function<const ProgramInfo*, const ProgramInfo*, bool>
996 {
997  public:
998  virtual bool operator()(const ProgramInfo*, const ProgramInfo*) = 0;
999  virtual ~plCompare() = default;
1000 };
1001 
1002 class plTitleSort : public plCompare
1003 {
1004  public:
1005  bool operator()(const ProgramInfo *a, const ProgramInfo *b) override // plCompare
1006  {
1007  if (a->GetSortTitle() != b->GetSortTitle())
1008  return naturalCompare(a->GetSortTitle(), b->GetSortTitle()) < 0;
1009  if (a->GetSortSubtitle() != b->GetSortSubtitle())
1010  return naturalCompare(a->GetSortSubtitle(), b->GetSortSubtitle()) < 0;
1011 
1012  if (a->GetRecordingStatus() == b->GetRecordingStatus())
1013  return a->GetScheduledStartTime() < b->GetScheduledStartTime();
1014 
1015  if (a->GetRecordingStatus() == RecStatus::Recording ||
1016  a->GetRecordingStatus() == RecStatus::Tuning ||
1017  a->GetRecordingStatus() == RecStatus::Failing)
1018  return true;
1019  if (b->GetRecordingStatus() == RecStatus::Recording ||
1020  b->GetRecordingStatus() == RecStatus::Tuning ||
1021  b->GetRecordingStatus() == RecStatus::Failing)
1022  return false;
1023 
1024  if (a->GetRecordingStatus() == RecStatus::WillRecord ||
1025  a->GetRecordingStatus() == RecStatus::Pending)
1026  return true;
1027  if (b->GetRecordingStatus() == RecStatus::WillRecord ||
1028  b->GetRecordingStatus() == RecStatus::Pending)
1029  return false;
1030 
1031  return a->GetScheduledStartTime() < b->GetScheduledStartTime();
1032  }
1033 };
1034 
1036 {
1037  public:
1039 
1040  bool operator()(const ProgramInfo *a, const ProgramInfo *b) override // plCompare
1041  {
1042  if (a->GetSortTitle() != b->GetSortTitle())
1043  return naturalCompare(a->GetSortTitle(), b->GetSortTitle()) < 0;
1044  if (a->GetSortSubtitle() != b->GetSortSubtitle())
1045  return naturalCompare(a->GetSortSubtitle(), b->GetSortSubtitle()) < 0;
1046 
1047  if (a->GetProgramID() != b->GetProgramID())
1048  return a->GetProgramID() < b->GetProgramID();
1049 
1050  return a->GetScheduledStartTime() < b->GetScheduledStartTime();
1051  }
1052 };
1053 
1054 class plTimeSort : public plCompare
1055 {
1056  public:
1057  plTimeSort(void) {;}
1058 
1059  bool operator()(const ProgramInfo *a, const ProgramInfo *b) override // plCompare
1060  {
1061  if (a->GetScheduledStartTime() == b->GetScheduledStartTime())
1062  return (a->GetChanID() < b->GetChanID());
1063 
1064  return (a->GetScheduledStartTime() < b->GetScheduledStartTime());
1065  }
1066 };
1067 
1068 void ProgLister::FillItemList(bool restorePosition, bool updateDisp)
1069 {
1071  {
1072  if (!m_titleSort)
1073  {
1074  if (!m_reverseSort)
1075  m_curView = 0;
1076  else
1077  m_curView = 1;
1078  }
1079  else
1080  {
1081  if (!m_reverseSort)
1082  m_curView = 2;
1083  else
1084  m_curView = 3;
1085  }
1086  }
1087 
1088  if (m_curView < 0)
1089  return;
1090 
1091  QString where;
1092  QString qphrase = m_viewList[m_curView];
1093 
1094  MSqlBindings bindings;
1095 
1097  bindings[":PGILSTART"] =
1098  m_startTime.addSecs(50 - m_startTime.time().second());
1099 
1100  if (m_type == plTitle) // per title listings
1101  {
1102  where = "WHERE channel.deleted IS NULL "
1103  " AND channel.visible > 0 "
1104  " AND program.endtime > :PGILSTART "
1105  " AND (program.title = :PGILPHRASE0 OR "
1106  " (program.seriesid <> '' AND "
1107  " program.seriesid = :PGILPHRASE1)) ";
1108  bindings[":PGILPHRASE0"] = qphrase;
1109  bindings[":PGILPHRASE1"] = m_extraArg;
1110  }
1111  else if (m_type == plNewListings) // what's new list
1112  {
1113  where = "LEFT JOIN oldprogram ON "
1114  " oldprogram.oldtitle = program.title "
1115  "WHERE channel.deleted IS NULL "
1116  " AND channel.visible > 0 "
1117  " AND program.endtime > :PGILSTART "
1118  " AND oldprogram.oldtitle IS NULL "
1119  " AND program.manualid = 0 ";
1120 
1121  if (qphrase == "premieres")
1122  {
1123  where += " AND ( ";
1124  where += " ( program.originalairdate = DATE(";
1125  where += " CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM'))";
1126  where += " AND (program.category = 'Special' ";
1127  where += " OR program.programid LIKE 'EP%0001')) ";
1128  where += " OR (program.category_type='movie' ";
1129  where += " AND program.stars > 0.5 ";
1130  where += " AND program.airdate >= YEAR(NOW()) - 2) ";
1131  where += " ) ";
1132  }
1133  else if (qphrase == "movies")
1134  {
1135  where += " AND program.category_type = 'movie' ";
1136  }
1137  else if (qphrase == "series")
1138  {
1139  where += " AND program.category_type = 'series' ";
1140  }
1141  else if (qphrase == "specials")
1142  {
1143  where += " AND program.category_type = 'tvshow' ";
1144  }
1145  else
1146  {
1147  where += " AND (program.category_type <> 'movie' ";
1148  where += " OR program.airdate >= YEAR(NOW()) - 3) ";
1149  }
1150  }
1151  else if (m_type == plTitleSearch) // keyword search
1152  {
1153  where = "WHERE channel.deleted IS NULL "
1154  " AND channel.visible > 0 "
1155  " AND program.endtime > :PGILSTART "
1156  " AND program.title LIKE :PGILLIKEPHRASE0 ";
1157  bindings[":PGILLIKEPHRASE0"] = QString("%") + qphrase + '%';
1158  }
1159  else if (m_type == plKeywordSearch) // keyword search
1160  {
1161  where = "WHERE channel.deleted IS NULL "
1162  " AND channel.visible > 0 "
1163  " AND program.endtime > :PGILSTART "
1164  " AND (program.title LIKE :PGILLIKEPHRASE1 "
1165  " OR program.subtitle LIKE :PGILLIKEPHRASE2 "
1166  " OR program.description LIKE :PGILLIKEPHRASE3 ) ";
1167  bindings[":PGILLIKEPHRASE1"] = QString("%") + qphrase + '%';
1168  bindings[":PGILLIKEPHRASE2"] = QString("%") + qphrase + '%';
1169  bindings[":PGILLIKEPHRASE3"] = QString("%") + qphrase + '%';
1170  }
1171  else if (m_type == plPeopleSearch) // people search
1172  {
1173  where = ", people, credits "
1174  "WHERE channel.deleted IS NULL "
1175  " AND channel.visible > 0 "
1176  " AND program.endtime > :PGILSTART "
1177  " AND people.name LIKE :PGILPHRASE1 "
1178  " AND credits.person = people.person "
1179  " AND program.chanid = credits.chanid "
1180  " AND program.starttime = credits.starttime";
1181  bindings[":PGILPHRASE1"] = qphrase;
1182  }
1183  else if (m_type == plPowerSearch) // complex search
1184  {
1185  QString powerWhere;
1186  MSqlBindings powerBindings;
1187 
1188  bool genreflag = PowerStringToSQL(qphrase, powerWhere, powerBindings);
1189 
1190  if (!powerWhere.isEmpty())
1191  {
1192  if (genreflag)
1193  {
1194  where = QString("LEFT JOIN programgenres ON "
1195  "program.chanid = programgenres.chanid AND "
1196  "program.starttime = programgenres.starttime ");
1197  }
1198 
1199  where += QString("WHERE channel.deleted IS NULL "
1200  " AND channel.visible > 0 "
1201  " AND program.endtime > :PGILSTART "
1202  " AND ( ") + powerWhere + " ) ";
1203  MSqlAddMoreBindings(bindings, powerBindings);
1204  }
1205  }
1206  else if (m_type == plSQLSearch) // complex search
1207  {
1208  qphrase.remove(QRegExp("^\\s*AND\\s+", Qt::CaseInsensitive));
1209  where = QString("WHERE channel.deleted iS NULL "
1210  " AND channel.visible > 0 "
1211  " AND program.endtime > :PGILSTART "
1212  " AND ( %1 ) ").arg(qphrase);
1213  if (!m_extraArg.isEmpty())
1214  where = m_extraArg + ' ' + where;
1215  }
1216  else if (m_type == plChannel) // list by channel
1217  {
1218  where = "WHERE channel.deleted IS NULL "
1219  " AND channel.visible > 0 "
1220  " AND program.endtime > :PGILSTART "
1221  " AND channel.chanid = :PGILPHRASE2 ";
1222  bindings[":PGILPHRASE2"] = qphrase;
1223  }
1224  else if (m_type == plCategory) // list by category
1225  {
1226  if (!m_useGenres)
1227  {
1228  where = "WHERE channel.deleted IS NULL "
1229  " AND channel.visible > 0 "
1230  " AND program.endtime > :PGILSTART "
1231  " AND program.category = :PGILPHRASE3 ";
1232  bindings[":PGILPHRASE3"] = qphrase;
1233  }
1234  else if (m_viewList[m_curView].indexOf(":/:") < 0)
1235  {
1236  where = "JOIN programgenres g ON "
1237  " program.chanid = g.chanid AND "
1238  " program.starttime = g.starttime AND "
1239  " genre = :PGILPHRASE4 "
1240  "WHERE channel.deleted IS NULL "
1241  " AND channel.visible > 0 "
1242  " AND program.endtime > :PGILSTART ";
1243  bindings[":PGILPHRASE4"] = qphrase;
1244  }
1245  else
1246  {
1247  where = "JOIN programgenres g1 ON "
1248  " program.chanid = g1.chanid AND "
1249  " program.starttime = g1.starttime AND "
1250  " g1.genre = :GENRE1 "
1251  "JOIN programgenres g2 ON "
1252  " program.chanid = g2.chanid AND "
1253  " program.starttime = g2.starttime AND "
1254  " g2.genre = :GENRE2 "
1255  "WHERE channel.deleted IS NULL "
1256  " AND channel.visible > 0 "
1257  " AND program.endtime > :PGILSTART ";
1258  bindings[":GENRE1"] = m_viewList[m_curView].section(":/:", 0, 0);
1259  bindings[":GENRE2"] = m_viewList[m_curView].section(":/:", 1, 1);
1260  }
1261  }
1262  else if (m_type == plMovies) // list movies
1263  {
1264  where = "WHERE channel.deleted IS NULL "
1265  " AND channel.visible > 0 "
1266  " AND program.endtime > :PGILSTART "
1267  " AND program.category_type = 'movie' "
1268  " AND program.stars " + qphrase + ' ';
1269  }
1270  else if (m_type == plTime) // list by time
1271  {
1272  QDateTime searchTime(m_searchTime);
1273  searchTime.setTime(QTime(searchTime.time().hour(), 0, 0));
1274  bindings[":PGILSEARCHTIME1"] = searchTime;
1275  where = "WHERE channel.deleted IS NULL "
1276  " AND channel.visible > 0 "
1277  " AND program.starttime >= :PGILSEARCHTIME1 ";
1278  if (m_titleSort)
1279  {
1280  where += " AND program.starttime < DATE_ADD(:PGILSEARCHTIME2, "
1281  "INTERVAL '1' HOUR) ";
1282  bindings[":PGILSEARCHTIME2"] = bindings[":PGILSEARCHTIME1"];
1283  }
1284  }
1285  else if (m_type == plRecordid) // list by recordid
1286  {
1287  where = "JOIN recordmatch ON "
1288  " (program.starttime = recordmatch.starttime "
1289  " AND program.chanid = recordmatch.chanid) "
1290  "WHERE channel.deleted IS NULL "
1291  " AND channel.visible > 0 "
1292  " AND program.endtime > :PGILSTART "
1293  " AND recordmatch.recordid = :PGILPHRASE5 ";
1294  bindings[":PGILPHRASE5"] = qphrase;
1295  }
1296  else if (m_type == plStoredSearch) // stored search
1297  {
1299  query.prepare("SELECT fromclause, whereclause FROM customexample "
1300  "WHERE rulename = :RULENAME;");
1301  query.bindValue(":RULENAME", qphrase);
1302 
1303  if (query.exec() && query.next())
1304  {
1305  QString fromc = query.value(0).toString();
1306  QString wherec = query.value(1).toString();
1307 
1308  where = QString("WHERE channel.deleted IS NULL "
1309  " AND channel.visible > 0 "
1310  " AND program.endtime > :PGILSTART "
1311  " AND ( %1 ) ").arg(wherec);
1312  if (!fromc.isEmpty())
1313  where = fromc + ' ' + where;
1314  }
1315  }
1316  else if (m_type == plPreviouslyRecorded)
1317  {
1318  if (m_recid && !m_title.isEmpty())
1319  {
1320  where = QString("AND ( recordid = %1 OR title = :MTITLE )")
1321  .arg(m_recid);
1322  bindings[":MTITLE"] = m_title;
1323  }
1324  else if (!m_title.isEmpty())
1325  {
1326  where = QString("AND title = :MTITLE ");
1327  bindings[":MTITLE"] = m_title;
1328  }
1329  else if (m_recid)
1330  {
1331  where = QString("AND recordid = %1 ").arg(m_recid);
1332  }
1333  }
1334 
1335  ProgramInfo selected;
1336  const ProgramInfo *selectedP = (restorePosition) ? GetCurrentProgram() : nullptr;
1337  if (selectedP)
1338  {
1339  selected = *selectedP;
1340  selectedP = &selected;
1341  }
1342 
1343  // Save a copy of m_itemList so that deletion of the ProgramInfo
1344  // objects can be deferred until background processing of old
1345  // ProgramInfo objects has completed.
1348  m_itemList.setAutoDelete(false);
1349  m_itemList.clear();
1350  m_itemList.setAutoDelete(true);
1351 
1353  {
1354  LoadFromOldRecorded(m_itemList, where, bindings);
1355  }
1356  else
1357  {
1359  LoadFromProgram(m_itemList, where, bindings, m_schedList);
1360  }
1361 
1362  if (m_type == plNewListings || m_titleSort)
1363  {
1366  {
1367  // Prune to one per title
1368  QString curtitle;
1369  auto it = m_itemList.begin();
1370  while (it != m_itemList.end())
1371  {
1372  if ((*it)->GetSortTitle() != curtitle)
1373  {
1374  curtitle = (*it)->GetSortTitle();
1375  ++it;
1376  }
1377  else
1378  {
1379  it = m_itemList.erase(it);
1380  }
1381  }
1382  }
1383  }
1384 
1385  if (!m_titleSort)
1387 
1388  if (updateDisp)
1389  UpdateDisplay(selectedP);
1390 }
1391 
1393 {
1394  if (!m_titleSort)
1395  return kTimeSort;
1397  return kPrevTitleSort;
1398  return kTitleSort;
1399 }
1400 
1401 void ProgLister::SortList(SortBy sortby, bool reverseSort)
1402 {
1403  if (reverseSort)
1404  {
1405  if (kTimeSort == sortby)
1406  {
1407  stable_sort(m_itemList.rbegin(), m_itemList.rend(), plTimeSort());
1408  }
1409  else if (kPrevTitleSort == sortby)
1410  {
1411  stable_sort(m_itemList.rbegin(), m_itemList.rend(),
1412  plPrevTitleSort());
1413  }
1414  else
1415  {
1416  stable_sort(m_itemList.rbegin(), m_itemList.rend(), plTitleSort());
1417  }
1418  }
1419  else
1420  {
1421  if (kTimeSort == sortby)
1422  {
1423  stable_sort(m_itemList.begin(), m_itemList.end(), plTimeSort());
1424  }
1425  else if (kPrevTitleSort == sortby)
1426  {
1427  stable_sort(m_itemList.begin(), m_itemList.end(),plPrevTitleSort());
1428  }
1429  else
1430  {
1431  stable_sort(m_itemList.begin(), m_itemList.end(), plTitleSort());
1432  }
1433  }
1434 }
1435 
1437 {
1438  InfoMap infoMap;
1439  ProgramInfo pginfo;
1440  pginfo.ToMap(infoMap);
1441  ResetMap(infoMap);
1442 
1443  if (m_positionText)
1444  m_positionText->Reset();
1445 }
1446 
1448 {
1449  int offset = 0;
1450 
1451  if (selected)
1453 
1454  m_progList->Reset();
1455 
1456  if (m_messageText)
1458 
1460 
1461  if (m_curviewText && m_curView >= 0)
1463 
1464  UpdateButtonList();
1465 
1466  if (selected)
1467  RestoreSelection(selected, offset);
1468  else if (m_selectedTime.isValid())
1469  {
1470  size_t i = 0;
1471  for (i = 0; i < m_itemList.size(); ++i)
1472  {
1473  if (m_selectedTime <= m_itemList[i]->GetScheduledStartTime())
1474  break;
1475  }
1477  m_selectedTime = QDateTime();
1478  }
1479 }
1480 
1482  int selectedOffset)
1483 {
1484  plCompare *comp = nullptr;
1485  if (!m_titleSort)
1486  comp = new plTimeSort();
1487  else if (m_type == plPreviouslyRecorded)
1488  comp = new plPrevTitleSort();
1489  else
1490  comp = new plTitleSort();
1491 
1492  int i = 0;
1493  for (i = m_itemList.size() - 2; i >= 0; i--)
1494  {
1495  bool dobreak = false;
1496  if (m_reverseSort)
1497  dobreak = comp->operator()(selected, m_itemList[i]);
1498  else
1499  dobreak = comp->operator()(m_itemList[i], selected);
1500  if (dobreak)
1501  break;
1502  }
1503 
1504  delete comp;
1505 
1506  m_progList->SetItemCurrent(i + 1, i + 1 - selectedOffset);
1507 }
1508 
1510 {
1511  auto *pginfo = item->GetData().value<ProgramInfo*>();
1512 
1513  if (item->GetText("is_item_initialized").isNull())
1514  {
1515  InfoMap infoMap;
1516  pginfo->ToMap(infoMap);
1517 
1518  QString state = RecStatus::toUIState(pginfo->GetRecordingStatus());
1519  if ((state == "warning") && (plPreviouslyRecorded == m_type))
1520  state = "disabled";
1521 
1522  item->SetTextFromMap(infoMap, state);
1523 
1524  if (m_type == plTitle)
1525  {
1526  QString tempSubTitle = pginfo->GetSubtitle();
1527  if (tempSubTitle.trimmed().isEmpty())
1528  tempSubTitle = pginfo->GetTitle();
1529  item->SetText(tempSubTitle, "titlesubtitle", state);
1530  }
1531 
1532  item->DisplayState(QString::number(pginfo->GetStars(10)),
1533  "ratingstate");
1534 
1535  item->DisplayState(state, "status");
1536 
1537  // Mark this button list item as initialized.
1538  item->SetText("yes", "is_item_initialized");
1539  }
1540 }
1541 
1543 {
1544  for (auto *it : m_itemList)
1545  new MythUIButtonListItem(m_progList, "", QVariant::fromValue(it));
1547 
1548  if (m_positionText)
1549  {
1551  tr("%1 of %2", "Current position in list where %1 is the "
1552  "position, %2 is the total count")
1553  .arg(QLocale::system().toString(m_progList->IsEmpty() ? 0 : m_progList->GetCurrentPos() + 1))
1554  .arg(QLocale::system().toString(m_progList->GetCount())));
1555  }
1556 }
1557 
1559 {
1560  if (!item)
1561  {
1563  return;
1564  }
1565 
1566  auto *pginfo = item->GetData().value<ProgramInfo*> ();
1567  if (!pginfo)
1568  {
1570  return;
1571  }
1572 
1573  InfoMap infoMap;
1574  pginfo->ToMap(infoMap);
1575  SetTextFromMap(infoMap);
1576 
1577  if (m_positionText)
1578  {
1580  tr("%1 of %2", "Current position in list where %1 is the "
1581  "position, %2 is the total count")
1582  .arg(QLocale::system().toString(m_progList->IsEmpty() ? 0 : m_progList->GetCurrentPos() + 1))
1583  .arg(QLocale::system().toString(m_progList->GetCount())));
1584  }
1585 
1586  MythUIStateType *ratingState = dynamic_cast<MythUIStateType*>
1587  (GetChild("ratingstate"));
1588 
1589  if (ratingState)
1590  {
1591  QString rating = QString::number(pginfo->GetStars(10));
1592  ratingState->DisplayState(rating);
1593  }
1594 }
1595 
1596 void ProgLister::customEvent(QEvent *event)
1597 {
1598  bool needUpdate = false;
1599 
1600  if (event->type() == DialogCompletionEvent::kEventType)
1601  {
1602  auto *dce = (DialogCompletionEvent*)(event);
1603 
1604  QString resultid = dce->GetId();
1605  QString resulttext = dce->GetResultText();
1606  int buttonnum = dce->GetResult();
1607 
1608  if (resultid == "sortmenu")
1609  {
1610  switch (buttonnum)
1611  {
1612  case 0:
1614  needUpdate = true;
1615  break;
1616  case 1:
1617  m_titleSort = true;
1618  m_reverseSort = false;
1619  needUpdate = true;
1620  break;
1621  case 2:
1622  m_titleSort = false;
1624  needUpdate = true;
1625  break;
1626  }
1627  }
1628  else if (resultid == "deletemenu")
1629  {
1630  switch (buttonnum)
1631  {
1632  case 0:
1633  {
1635  if (pi)
1636  {
1637  RecordingInfo ri(*pi);
1638  if (ri.IsDuplicate())
1639  ri.ForgetHistory();
1640  else
1641  ri.SetDupHistory();
1642  *pi = ri;
1643  }
1644  break;
1645  }
1646  case 1:
1648  break;
1649  case 2:
1651  break;
1652  }
1653  }
1654  else if (resultid == "deleterule")
1655  {
1656  auto *record = dce->GetData().value<RecordingRule *>();
1657  if (record && buttonnum > 0 && !record->Delete())
1658  {
1659  LOG(VB_GENERAL, LOG_ERR, LOC +
1660  "Failed to delete recording rule");
1661  }
1662  delete record;
1663  }
1664  else
1665  {
1667  }
1668  }
1669  else if (event->type() == ScreenLoadCompletionEvent::kEventType)
1670  {
1671  auto *slce = (ScreenLoadCompletionEvent*)(event);
1672  QString id = slce->GetId();
1673 
1674  if (id == objectName())
1675  {
1676  CloseBusyPopup(); // opened by LoadInBackground()
1677  UpdateDisplay();
1678 
1679  if (m_curView < 0 && m_type != plPreviouslyRecorded)
1681  }
1682  }
1683  else if (event->type() == MythEvent::MythEventMessage)
1684  {
1685  auto *me = dynamic_cast<MythEvent *>(event);
1686  if (me == nullptr)
1687  return;
1688 
1689  const QString& message = me->Message();
1690 
1691  if (m_allowViewDialog && message == "CHOOSE_VIEW")
1693  else if (message == "SCHEDULE_CHANGE")
1694  needUpdate = true;
1695  }
1696 
1697  if (needUpdate)
1698  FillItemList(true);
1699 }
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:98
MythScreenType::LoadInBackground
void LoadInBackground(const QString &message="")
Definition: mythscreentype.cpp:302
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
ProgLister::Load
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
Definition: proglist.cpp:171
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:304
MythUIButtonList::GetTopItemPos
int GetTopItemPos(void) const
Definition: mythuibuttonlist.h:192
e
QDomElement e
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1417
channel
QDomElement channel
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:498
MythUISearchDialog
Provide a dialog to quickly find an entry in a list.
Definition: mythdialogbox.h:348
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:73
plPeopleSearch
@ plPeopleSearch
Definition: proglist.h:18
ProgLister::m_progList
MythUIButtonList * m_progList
Definition: proglist.h:128
MythTimeInputDialog::kHours
@ kHours
Definition: mythdialogbox.h:407
ProgramInfo::IsDuplicate
bool IsDuplicate(void) const
Definition: programinfo.h:481
mythuitext.h
plCompare
Definition: proglist.cpp:995
plPrevTitleSort::plPrevTitleSort
plPrevTitleSort(void)
Definition: proglist.cpp:1038
LoadFromScheduler
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, const QString &altTable="", int recordid=-1)
Definition: programinfo.h:879
MythUIText::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:83
ProgLister::DeleteOldEpisode
void DeleteOldEpisode(bool ok)
Definition: proglist.cpp:636
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:550
mythdb.h
ProgLister::GetSortBy
SortBy GetSortBy(void) const
Definition: proglist.cpp:1392
MythUIButtonListItem::DisplayState
void DisplayState(const QString &state, const QString &name)
Definition: mythuibuttonlist.cpp:3507
ChannelInfo::kChannelShort
@ kChannelShort
Definition: channelinfo.h:51
MythUIComposite::ResetMap
virtual void ResetMap(const InfoMap &infoMap)
Definition: mythuicomposite.cpp:28
ProgLister::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: proglist.cpp:182
MythTimeInputDialog::kDay
@ kDay
Definition: mythdialogbox.h:403
ProgLister::kTitleSort
@ kTitleSort
Definition: proglist.h:86
ScheduleCommon::customEvent
void customEvent(QEvent *event) override
Definition: schedulecommon.cpp:475
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:633
RecStatus::Tuning
@ Tuning
Definition: recStatus.h:22
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1106
MythUIType::GetChild
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:130
RecordingInfo::ForgetHistory
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
Definition: recordinginfo.cpp:1378
plChannel
@ plChannel
Definition: proglist.h:24
plUnknown
@ plUnknown
Definition: proglist.h:14
ProgLister::m_viewList
QStringList m_viewList
Definition: proglist.h:109
MSqlAddMoreBindings
void MSqlAddMoreBindings(MSqlBindings &output, MSqlBindings &addfrom)
Add the entries in addfrom to the map in output.
Definition: mythdbcon.cpp:907
DialogCompletionEvent::kEventType
static Type kEventType
Definition: mythdialogbox.h:57
AutoDeleteDeque::clear
void clear(void)
Definition: autodeletedeque.h:40
ProgLister::m_allowEvents
bool m_allowEvents
Definition: proglist.h:120
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
ProgramInfo::kTitleSubtitle
@ kTitleSubtitle
Definition: programinfo.h:496
AutoDeleteDeque::empty
bool empty(void) const
Definition: autodeletedeque.h:66
ProgLister::m_searchTime
QDateTime m_searchTime
Definition: proglist.h:101
mythdialogbox.h
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
MythScreenStack
Definition: mythscreenstack.h:15
MythScreenType::Create
virtual bool Create(void)
Definition: mythscreentype.cpp:282
arg
arg(title).arg(filename).arg(doDelete))
plCategory
@ plCategory
Definition: proglist.h:23
RecordingRule
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
ProgLister::ShowOldRecordedMenu
void ShowOldRecordedMenu(void)
Definition: proglist.cpp:690
category
QString category
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1419
ScheduleCommon::ShowGuide
virtual void ShowGuide(void) const
Show the program guide.
Definition: schedulecommon.cpp:132
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:44
mythuistatetype.h
ProgLister::m_viewTextList
QStringList m_viewTextList
Definition: proglist.h:110
ProgramInfo::SetProgramID
void SetProgramID(const QString &id)
Definition: programinfo.h:520
MythUIButtonList::SetSearchFields
void SetSearchFields(const QString &fields)
Definition: mythuibuttonlist.h:206
ScreenLoadCompletionEvent::kEventType
static Type kEventType
Definition: mythscreentype.h:32
kKeywordSearch
@ kKeywordSearch
Definition: recordingtypes.h:74
ProgLister::PhrasePopup
friend class PhrasePopup
Definition: proglist.h:33
ProgLister::SwitchToPreviousView
void SwitchToPreviousView(void)
Definition: proglist.cpp:324
menu
static MythThemedMenu * menu
Definition: mythtv/programs/mythtv-setup/main.cpp:55
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:309
mythuibuttonlist.h
ProgLister::ShowDeleteRuleMenu
void ShowDeleteRuleMenu(void)
Definition: proglist.cpp:593
MythUIButtonList::GetCount
int GetCount() const
Definition: mythuibuttonlist.cpp:1655
ScheduleCommon::ShowDetails
virtual void ShowDetails(void) const
Show the Program Details screen.
Definition: schedulecommon.cpp:33
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
ProgLister::SortList
void SortList(SortBy sortby, bool reverseSort)
Definition: proglist.cpp:1401
ScheduleCommon::EditRecording
virtual void EditRecording(bool may_watch_now=false)
Creates a dialog for editing the recording status, blocking until user leaves dialog.
Definition: schedulecommon.cpp:274
LOC
#define LOC
Definition: proglist.cpp:33
ScheduleCommon::EditScheduled
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
Definition: schedulecommon.cpp:166
proglist.h
ProgLister::kTimeSort
@ kTimeSort
Definition: proglist.h:86
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:112
ProgLister::UpdateKeywordInDB
void UpdateKeywordInDB(const QString &text, const QString &oldValue)
Definition: proglist.cpp:371
ProgLister::kPrevTitleSort
@ kPrevTitleSort
Definition: proglist.h:86
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MythUIButtonListItem::SetText
void SetText(const QString &text, const QString &name="", const QString &state="")
Definition: mythuibuttonlist.cpp:3272
ChannelUtil::SortChannels
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
Definition: channelutil.cpp:2282
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
ProgLister::DeleteOldSeries
void DeleteOldSeries(bool ok)
Definition: proglist.cpp:669
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
RecStatus::WillRecord
@ WillRecord
Definition: recStatus.h:31
MythUIButtonListItem
Definition: mythuibuttonlist.h:27
AutoDeleteDeque::setAutoDelete
void setAutoDelete(bool auto_delete)
Definition: autodeletedeque.h:72
ProgLister::m_itemListSave
ProgramList m_itemListSave
Definition: proglist.h:113
plPreviouslyRecorded
@ plPreviouslyRecorded
Definition: proglist.h:28
toString
QString toString(MarkTypes type)
Definition: programtypes.cpp:26
ScheduleCommon::ShowPrevious
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
Definition: schedulecommon.cpp:248
ProgLister::m_reverseSort
bool m_reverseSort
Definition: proglist.h:122
MythUIButtonList::IsEmpty
bool IsEmpty() const
Definition: mythuibuttonlist.cpp:1671
mythdate.h
ProgLister::PowerSearchPopup
friend class PowerSearchPopup
Definition: proglist.h:35
AutoDeleteDeque::rend
reverse_iterator rend(void)
Definition: autodeletedeque.h:57
plTitleSearch
@ plTitleSearch
Definition: proglist.h:16
RecStatus::toUIState
static QString toUIState(Type recstatus)
Definition: recStatus.cpp:4
ProgListType
ProgListType
Definition: proglist.h:13
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:384
ProgLister::m_startTime
QDateTime m_startTime
Definition: proglist.h:100
ScheduleCommon::EditCustom
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
Definition: schedulecommon.cpp:202
ProgLister::ShowMenu
void ShowMenu(void) override
Definition: proglist.cpp:270
kPowerSearch
@ kPowerSearch
Definition: recordingtypes.h:72
MythUIButtonList::GetCurrentPos
int GetCurrentPos() const
Definition: mythuibuttonlist.h:190
tv_actions.h
ProgLister::m_schedText
MythUIText * m_schedText
Definition: proglist.h:125
ProgLister::UpdateButtonList
void UpdateButtonList(void)
Definition: proglist.cpp:1542
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:137
MythUIButtonList::LoadInBackground
void LoadInBackground(int start=0, int pageSize=20)
Definition: mythuibuttonlist.cpp:2760
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:355
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
ProgramInfo::GetDescription
QString GetDescription(void) const
Definition: programinfo.h:359
ProgLister::HandleSelected
void HandleSelected(MythUIButtonListItem *item)
Definition: proglist.cpp:1558
ProgLister::m_curView
int m_curView
Definition: proglist.h:108
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
ProgLister::HandleVisible
void HandleVisible(MythUIButtonListItem *item)
Definition: proglist.cpp:1509
ProgLister::FillViewList
void FillViewList(const QString &view)
Definition: proglist.cpp:725
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:222
hardwareprofile.scan.rating
def rating(profile, smoonURL, gate)
Definition: scan.py:39
RecStatus::Failing
@ Failing
Definition: recStatus.h:18
ACTION_CHANNELSEARCH
#define ACTION_CHANNELSEARCH
Definition: tv_actions.h:28
ProgLister::m_selectedTime
QDateTime m_selectedTime
Definition: proglist.h:102
ProgLister::m_recid
uint m_recid
Definition: proglist.h:97
MythUIComposite::SetTextFromMap
virtual void SetTextFromMap(const InfoMap &infoMap)
Definition: mythuicomposite.cpp:9
ScheduleCommon
Definition: schedulecommon.h:15
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1830
ProgLister::FillItemList
void FillItemList(bool restorePosition, bool updateDisp=true)
Definition: proglist.cpp:1068
scheduledrecording.h
plTitleSort::operator()
bool operator()(const ProgramInfo *a, const ProgramInfo *b) override
Definition: proglist.cpp:1005
plPowerSearch
@ plPowerSearch
Definition: proglist.h:19
ProgLister::SetViewFromTime
void SetViewFromTime(QDateTime searchTime)
Definition: proglist.cpp:506
ScheduledRecording::RescheduleCheck
static void RescheduleCheck(const RecordingInfo &recinfo, const QString &why)
Definition: scheduledrecording.h:23
ProgLister::PowerStringToSQL
static bool PowerStringToSQL(const QString &qphrase, QString &output, MSqlBindings &bindings)
Definition: proglist.cpp:527
MythUIButtonList::SetLCDTitles
void SetLCDTitles(const QString &title, const QString &columnList="")
Definition: mythuibuttonlist.cpp:3038
kNoSearch
@ kNoSearch
Definition: recordingtypes.h:71
ChannelInfoList
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:133
plTitle
@ plTitle
Definition: proglist.h:15
naturalCompare
int naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity)
Definition: mythmiscutil.cpp:1032
MythUIButtonListItem::GetData
QVariant GetData()
Definition: mythuibuttonlist.cpp:3588
ChannelUtil::GetChannels
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:240
plTimeSort::operator()
bool operator()(const ProgramInfo *a, const ProgramInfo *b) override
Definition: proglist.cpp:1059
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
plTimeSort
Definition: proglist.cpp:1054
AutoDeleteDeque::end
iterator end(void)
Definition: autodeletedeque.h:51
ProgLister::GetCurrentProgram
ProgramInfo * GetCurrentProgram(void) const override
Definition: proglist.cpp:577
ProgLister::m_curviewText
MythUIText * m_curviewText
Definition: proglist.h:126
kTitleSearch
@ kTitleSearch
Definition: recordingtypes.h:73
plStoredSearch
@ plStoredSearch
Definition: proglist.h:27
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
ProgLister::SetViewFromList
void SetViewFromList(const QString &item)
Definition: proglist.cpp:520
channelutil.h
MythUIButtonListItem::SetTextFromMap
void SetTextFromMap(const InfoMap &infoMap, const QString &state="")
Definition: mythuibuttonlist.cpp:3289
RecStatus::Pending
@ Pending
Definition: recStatus.h:17
MythDate::kSimplify
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:23
MythUIButtonListItem::GetText
QString GetText(const QString &name="") const
Definition: mythuibuttonlist.cpp:3313
ProgLister::m_title
QString m_title
Definition: proglist.h:98
ScreenLoadCompletionEvent
Event that can be dispatched from a MythScreenType when it has completed loading.
Definition: mythscreentype.h:24
channelinfo.h
plCompare::operator()
virtual bool operator()(const ProgramInfo *, const ProgramInfo *)=0
ProgLister::m_allowViewDialog
bool m_allowViewDialog
Definition: proglist.h:131
recordinginfo.h
ProgLister::~ProgLister
~ProgLister() override
Definition: proglist.cpp:91
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:366
ProgramInfo::GetRecordingRuleType
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:445
MythMenu
Definition: mythdialogbox.h:92
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:414
mythmiscutil.h
ProgLister::m_positionText
MythUIText * m_positionText
Definition: proglist.h:127
RecStatus::Recording
@ Recording
Definition: recStatus.h:30
MythConfirmationDialog
Dialog asking for user confirmation. Ok and optional Cancel button.
Definition: mythdialogbox.h:221
mythcorecontext.h
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
ProgLister::ShowChooseViewMenu
void ShowChooseViewMenu(void)
Definition: proglist.cpp:416
ProgLister::ClearCurrentProgramInfo
void ClearCurrentProgramInfo(void)
Definition: proglist.cpp:1436
plTime
@ plTime
Definition: proglist.h:25
MythDate
Definition: mythdate.cpp:7
ProgLister::m_itemList
ProgramList m_itemList
Definition: proglist.h:112
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
LoadFromProgram
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
Definition: programinfo.cpp:5469
ProgLister::m_searchType
RecSearchType m_searchType
Definition: proglist.h:105
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
plTimeSort::plTimeSort
plTimeSort(void)
Definition: proglist.cpp:1057
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:135
ProgLister::m_type
ProgListType m_type
Definition: proglist.h:96
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1080
plTitleSort
Definition: proglist.cpp:1002
ProgramInfo::ToMap
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
Definition: programinfo.cpp:1469
ScheduleCommon::ShowUpcoming
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
Definition: schedulecommon.cpp:73
ScheduleCommon::QuickRecord
virtual void QuickRecord(void)
Create a kSingleRecord or bring up recording dialog.
Definition: schedulecommon.cpp:147
MythUIButtonList::Reset
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttonlist.cpp:113
plMovies
@ plMovies
Definition: proglist.h:22
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:107
plPrevTitleSort::operator()
bool operator()(const ProgramInfo *a, const ProgramInfo *b) override
Definition: proglist.cpp:1040
MythUIButtonList::SetItemCurrent
void SetItemCurrent(MythUIButtonListItem *item)
Definition: mythuibuttonlist.cpp:1557
build_compdb.action
action
Definition: build_compdb.py:9
ProgLister::m_schedList
ProgramList m_schedList
Definition: proglist.h:114
ProgLister::m_channelOrdering
QString m_channelOrdering
Definition: proglist.h:103
ProgLister::ProgLister
ProgLister(MythScreenStack *parent, ProgListType pltype, QString view, QString extraArg, QDateTime selectedTime=QDateTime())
Definition: proglist.cpp:37
ProgLister::Create
bool Create(void) override
Definition: proglist.cpp:98
ProgLister::m_extraArg
QString m_extraArg
Definition: proglist.h:99
AutoDeleteDeque::rbegin
reverse_iterator rbegin(void)
Definition: autodeletedeque.h:56
LoadFromOldRecorded
bool LoadFromOldRecorded(ProgramList &destination, const QString &sql, const MSqlBindings &bindings)
Definition: programinfo.cpp:5657
plRecordid
@ plRecordid
Definition: proglist.h:26
plPrevTitleSort
Definition: proglist.cpp:1035
ProgLister::ShowDeleteOldEpisodeMenu
void ShowDeleteOldEpisodeMenu(void)
Definition: proglist.cpp:624
ProgLister::RestoreSelection
void RestoreSelection(const ProgramInfo *selected, int selectedOffset)
Definition: proglist.cpp:1481
MythTimeInputDialog::kFutureDates
@ kFutureDates
Definition: mythdialogbox.h:411
ScheduleCommon::ShowChannelSearch
virtual void ShowChannelSearch(void) const
Show the channel search.
Definition: schedulecommon.cpp:113
plSQLSearch
@ plSQLSearch
Definition: proglist.h:20
plNewListings
@ plNewListings
Definition: proglist.h:21
ProgLister::customEvent
void customEvent(QEvent *event) override
Definition: proglist.cpp:1596
ProgLister::SwitchToNextView
void SwitchToNextView(void)
Definition: proglist.cpp:347
AutoDeleteDeque::erase
iterator erase(iterator it)
Definition: autodeletedeque.h:34
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:20
ProgramInfo::GetRecordingRuleID
uint GetRecordingRuleID(void) const
Definition: programinfo.h:443
ProgLister::ShowDeleteItemMenu
void ShowDeleteItemMenu(void)
Definition: proglist.cpp:585
recordingrule.h
ProgLister::SortBy
SortBy
Definition: proglist.h:86
plCompare::~plCompare
virtual ~plCompare()=default
MythTimeInputDialog
Definition: mythdialogbox.h:392
ProgLister::ShowDeleteOldSeriesMenu
void ShowDeleteOldSeriesMenu(void)
Definition: proglist.cpp:657
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:49
query
MSqlQuery query(MSqlQuery::InitCon())
ProgLister::m_titleSort
bool m_titleSort
Definition: proglist.h:121
ProgLister::UpdateDisplay
void UpdateDisplay(const ProgramInfo *selected=nullptr)
Definition: proglist.cpp:1447
output
#define output
Definition: synaesthesia.cpp:221
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
kPeopleSearch
@ kPeopleSearch
Definition: recordingtypes.h:75
MythScreenType::CloseBusyPopup
void CloseBusyPopup(void)
Definition: mythscreentype.cpp:354
MythUIStateType
This widget is used for grouping other widgets for display when a particular named state is called....
Definition: mythuistatetype.h:22
GetSetting
t<< doc.toString(4);f.close();LOG(VB_JOBQUEUE, LOG_INFO, "Copying video file");bool res=copyFile(filename, saveDirectory+title+"/"+baseName);if(!res) return 0;if(QFile::exists(filename+".png")) { LOG(VB_JOBQUEUE, LOG_INFO, "Copying preview image");res=copyFile(filename+".png", saveDirectory+title+"/"+baseName+".png");if(!res) return 0;} LOG(VB_JOBQUEUE, LOG_INFO, "Item Archived OK");return 1;}int NativeArchive::exportVideo(QDomElement &itemNode, const QString &saveDirectory){ QString dbVersion=gCoreContext-> GetSetting("DBSchemaVer", "")
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:628
AutoDeleteDeque::size
size_t size(void) const
Definition: autodeletedeque.h:67
MythUIStateType::DisplayState
bool DisplayState(const QString &name)
Definition: mythuistatetype.cpp:84
ProgLister::m_view
QString m_view
Definition: proglist.h:107
plKeywordSearch
@ plKeywordSearch
Definition: proglist.h:17
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
ProgLister::m_useGenres
bool m_useGenres
Definition: proglist.h:123
RecordingInfo::SetDupHistory
void SetDupHistory(void)
Set the duplicate flag in oldrecorded.
Definition: recordinginfo.cpp:1561
ProgLister::m_messageText
MythUIText * m_messageText
Definition: proglist.h:129