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