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