Go to the documentation of this file.
2 #include <QCoreApplication>
27 #define LOC QString("ProgFinder: ")
28 #define LOC_ERR QString("ProgFinder, Error: ")
29 #define LOC_WARN QString("ProgFinder, Warning: ")
37 programFind =
new JaProgFinder(mainStack, allowEPG, player, embedVideo);
39 programFind =
new HeProgFinder(mainStack, allowEPG, player, embedVideo);
41 programFind =
new RuProgFinder(mainStack, allowEPG, player, embedVideo);
43 programFind =
new ProgFinder(mainStack, allowEPG, player, embedVideo);
46 mainStack->
AddScreen(programFind, (player ==
nullptr));
52 TV *player,
bool embedVideo)
55 m_embedVideo(embedVideo),
78 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'programfind'");
179 for (
int i = 0; i < actions.size() && !handled; ++i)
181 const QString&
action = actions[i];
186 else if (
action ==
"CUSTOMEDIT")
188 else if (
action ==
"UPCOMING")
190 else if (
action ==
"PREVRECORDED")
194 else if (
action ==
"TOGGLERECORD")
200 else if (
action ==
"ESCAPE")
224 QString label = tr(
"Options");
227 auto *menuPopup =
new MythDialogBox(label, popupStack,
"menuPopup");
229 if (menuPopup->Create())
231 menuPopup->SetReturnEvent(
this,
"menu");
234 menuPopup->AddButton(tr(
"Clear Search"));
235 menuPopup->AddButton(tr(
"Edit Search"));
238 menuPopup->AddButton(tr(
"Toggle Record"));
239 menuPopup->AddButton(tr(
"Program Details"));
240 menuPopup->AddButton(tr(
"Upcoming"));
241 menuPopup->AddButton(tr(
"Previously Recorded"));
242 menuPopup->AddButton(tr(
"Custom Edit"));
243 menuPopup->AddButton(tr(
"Program Guide"));
244 menuPopup->AddButton(tr(
"Channel Search"));
259 auto *me =
dynamic_cast<MythEvent *
>(event);
263 const QString& message = me->
Message();
265 if (message ==
"SCHEDULE_CHANGE")
280 QString resultid = dce->GetId();
281 QString resulttext = dce->GetResultText();
283 if (resultid ==
"menu")
285 if (resulttext == tr(
"Clear Search"))
293 else if (resulttext == tr(
"Edit Search"))
298 if (textInput->Create())
300 textInput->SetReturnEvent(
this,
"searchtext");
304 else if (resulttext == tr(
"Toggle Record"))
308 else if (resulttext == tr(
"Program Details"))
312 else if (resulttext == tr(
"Upcoming"))
316 else if (resulttext == tr(
"Previously Recorded"))
320 else if (resulttext == tr(
"Custom Edit"))
324 else if (resulttext == tr(
"Program Guide"))
328 else if (resulttext == tr(
"Channel Search"))
333 else if (resultid ==
"searchtext")
363 "Please select another search."));
371 "then press SELECT or the right arrow."));
383 "When finished return with the left arrow key. "
384 "Press SELECT to schedule a recording."));
399 "this search. Please select another "
418 uint startchanid = 0;
424 if (pginfo !=
nullptr)
458 starttime =
show->GetScheduledStartTime();
465 item->SetText(itemText,
"buttontext", state);
466 item->DisplayState(state,
"status");
468 show->ToMap(infoMap);
469 item->SetTextFromMap(infoMap, state);
495 data = query.
value(0).toString();
509 ShowName::Iterator it;
512 QString tmpProgData = *it;
527 QString querystr =
"WHERE program.title = :TITLE "
528 " AND program.endtime > :ENDTIME "
529 " AND channel.deleted IS NULL "
530 " AND channel.visible > 0 ";
531 bindings[
":TITLE"] = progTitle;
532 bindings[
":ENDTIME"] = progStart.addSecs(50 - progStart.time().second());
544 for (
int charNum = 48; charNum < 91; ++charNum)
560 if (searchChar.isEmpty())
563 if (searchChar.contains(
'@'))
565 where =
"SELECT DISTINCT title FROM program "
566 "LEFT JOIN channel ON program.chanid = channel.chanid "
567 "WHERE channel.deleted IS NULL AND "
568 " channel.visible > 0 AND "
569 "( title NOT REGEXP '^[A-Z0-9]' AND "
570 " title NOT REGEXP '^The [A-Z0-9]' AND "
571 " title NOT REGEXP '^A [A-Z0-9]' AND "
572 " title NOT REGEXP '^An [A-Z0-9]' AND "
573 " starttime > :STARTTIME ) ";
576 where +=
"AND title LIKE :SEARCH ";
580 where +=
"ORDER BY title;";
582 bindings[
":STARTTIME"] =
583 progStart.addSecs(50 - progStart.time().second());
587 QString one = searchChar +
'%';
588 QString two = QString(
"The ") + one;
589 QString three = QString(
"A ") + one;
590 QString four = QString(
"An ") + one;
592 where =
"SELECT DISTINCT title FROM program "
593 "LEFT JOIN channel ON program.chanid = channel.chanid "
594 "WHERE channel.deleted IS NULL "
595 "AND channel.visible > 0 "
596 "AND ( title LIKE :ONE OR title LIKE :TWO "
597 " OR title LIKE :THREE "
598 " OR title LIKE :FOUR ) "
599 "AND starttime > :STARTTIME ";
601 where +=
"AND title LIKE :SEARCH ";
603 where +=
"ORDER BY title;";
605 bindings[
":ONE"] = one;
606 bindings[
":TWO"] = two;
607 bindings[
":THREE"] = three;
608 bindings[
":FOUR"] = four;
609 bindings[
":STARTTIME"] =
610 progStart.addSecs(50 - progStart.time().second());
622 if (searchChar ==
"T")
624 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
628 else if (data.startsWith(
"The T"))
630 data = data.mid(4) +
", The";
632 else if (data.startsWith(
"A T"))
634 data = data.mid(2) +
", A";
642 else if (searchChar ==
"A")
644 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
648 else if (data.startsWith(
"The A"))
650 data = data.mid(4) +
", The";
652 else if (data.startsWith(
"A A"))
654 data = data.mid(2) +
", A";
656 else if (data.startsWith(
"An A"))
658 data = data.mid(3) +
", An";
668 if (data.startsWith(
"The "))
669 data = data.mid(4) +
", The";
670 else if (data.startsWith(
"A "))
671 data = data.mid(2) +
", A";
672 else if (data.startsWith(
"An "))
673 data = data.mid(3) +
", An";
683 if (charNum == 29 || charNum == 10)
685 if ((data.startsWith(
"The T") && charNum == 29) ||
686 (data.startsWith(
"The A") && charNum == 10))
687 data = data.mid(4) +
", The";
688 else if ((data.startsWith(
"A T") && charNum == 29) ||
689 (data.startsWith(
"A A") && charNum == 10))
690 data = data.mid(2) +
", A";
691 else if (data.startsWith(
"An A") && charNum == 10)
692 data = data.mid(3) +
", An";
693 else if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
705 if (data.startsWith(
"The "))
706 data = data.mid(4) +
", The";
707 if (data.startsWith(
"A "))
708 data = data.mid(2) +
", A";
709 if (data.startsWith(
"An "))
710 data = data.mid(3) +
", An";
718 if (data.endsWith(
", The"))
719 data =
"The " + data.left(data.length() - 5);
720 if (data.endsWith(
", A"))
721 data =
"A " + data.left(data.length() - 3);
731 QChar(0x3042), QChar(0x304b), QChar(0x3055), QChar(0x305f),
733 QChar(0x306a), QChar(0x306f), QChar(0x307e), QChar(0x3084),
735 QChar(0x3089), QChar(0x308f), QChar(0x82f1), QChar(0x6570),
755 where =
"SELECT DISTINCT title FROM program "
756 "LEFT JOIN channel ON program.chanid = channel.chanid "
757 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
761 where +=
"AND ( title_pronounce >= 'あ' AND title_pronounce <= 'お') ";
764 where +=
"AND ( title_pronounce >= 'か' AND title_pronounce <= 'ご') ";
767 where +=
"AND ( title_pronounce >= 'さ' AND title_pronounce <= 'そ') ";
770 where +=
"AND ( title_pronounce >= 'た' AND title_pronounce <= 'ど') ";
773 where +=
"AND ( title_pronounce >= 'な' AND title_pronounce <= 'の') ";
776 where +=
"AND ( title_pronounce >= 'は' AND title_pronounce <= 'ぽ') ";
779 where +=
"AND ( title_pronounce >= 'ま' AND title_pronounce <= 'も') ";
782 where +=
"AND ( title_pronounce >= 'や' AND title_pronounce <= 'よ') ";
785 where +=
"AND ( title_pronounce >= 'ら' AND title_pronounce <= 'ろ') ";
788 where +=
"AND ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') ";
791 where +=
"AND ( title_pronounce >= 'A' AND title_pronounce <= 'z') ";
794 where +=
"AND ( title_pronounce >= '0' AND title_pronounce <= '9') ";
798 where +=
"AND starttime > :STARTTIME ";
802 where +=
"AND title_pronounce LIKE :SEARCH ";
806 where +=
"ORDER BY title_pronounce;";
808 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
818 [[maybe_unused]]
int charNum)
833 QChar(0x5d0), QChar(0x5d1), QChar(0x5d2), QChar(0x5d3),
835 QChar(0x5d4), QChar(0x5d5), QChar(0x5d6), QChar(0x5d7),
837 QChar(0x5d8), QChar(0x5d9), QChar(0x5db), QChar(0x5dc),
839 QChar(0x5de), QChar(0x5e0), QChar(0x5e1), QChar(0x5e2),
841 QChar(0x5e4), QChar(0x5e6), QChar(0x5e7), QChar(0x5e8),
843 QChar(0x5e9), QChar(0x5ea), QChar(
'E'), QChar(
'#'),
861 if (searchChar.isEmpty())
864 where =
"SELECT DISTINCT title FROM program "
865 "LEFT JOIN channel ON program.chanid = channel.chanid "
866 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
868 if (searchChar.contains(
'E'))
870 where +=
"AND ( title REGEXP '^[A-Z]') ";
872 else if (searchChar.contains(
'#'))
874 where +=
"AND ( title REGEXP '^[0-9]') ";
878 QString one = searchChar +
'%';
879 bindings[
":ONE"] = one;
880 where +=
"AND ( title LIKE :ONE ) ";
883 where +=
"AND starttime > :STARTTIME ";
887 where +=
"AND title LIKE :SEARCH ";
891 where +=
"ORDER BY title;";
893 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
902 [[maybe_unused]]
int charNum)
918 QChar(0x410), QChar(0x411), QChar(0x412), QChar(0x413),
920 QChar(0x414), QChar(0x415), QChar(0x401), QChar(0x416),
922 QChar(0x417), QChar(0x418), QChar(0x419), QChar(0x41a),
924 QChar(0x41b), QChar(0x41c), QChar(0x41d), QChar(0x41e),
926 QChar(0x41f), QChar(0x420), QChar(0x421), QChar(0x422),
928 QChar(0x423), QChar(0x424), QChar(0x425), QChar(0x426),
930 QChar(0x427), QChar(0x428), QChar(0x429), QChar(0x42a),
932 QChar(0x42b), QChar(0x44c), QChar(0x42d), QChar(0x42e),
934 QChar(0x42f), QChar(
'0'), QChar(
'1'), QChar(
'2'),
935 QChar(
'3'), QChar(
'4'), QChar(
'5'), QChar(
'6'),
936 QChar(
'7'), QChar(
'8'), QChar(
'9'), QChar(
'@'),
937 QChar(
'A'), QChar(
'B'), QChar(
'C'), QChar(
'D'),
938 QChar(
'E'), QChar(
'F'), QChar(
'G'), QChar(
'H'),
939 QChar(
'I'), QChar(
'J'), QChar(
'K'), QChar(
'L'),
940 QChar(
'M'), QChar(
'N'), QChar(
'O'), QChar(
'P'),
941 QChar(
'Q'), QChar(
'R'), QChar(
'S'), QChar(
'T'),
942 QChar(
'U'), QChar(
'V'), QChar(
'W'), QChar(
'X'),
943 QChar(
'Y'), QChar(
'Z')
962 if (searchChar.isEmpty())
966 if (searchChar.contains(
'@'))
968 where =
"SELECT DISTINCT title FROM program "
969 "LEFT JOIN channel ON program.chanid = channel.chanid "
970 "WHERE channel.deleted IS NULL AND "
971 " channel.visible > 0 AND "
973 "title NOT REGEXP '^[A-Z0-9]' AND "
974 "title NOT REGEXP '^The [A-Z0-9]' AND "
975 "title NOT REGEXP '^A [A-Z0-9]' AND "
976 "title NOT REGEXP '^[0-9]' AND "
977 "starttime > :STARTTIME ) ";
980 where +=
"AND title LIKE :SEARCH ";
984 where +=
"ORDER BY title;";
986 bindings[
":STARTTIME"] =
987 progStart.addSecs(50 - progStart.time().second());
991 QString one = searchChar +
'%';
992 QString two = QString(
"The ") + one;
993 QString three = QString(
"A ") + one;
994 QString four = QString(
"An ") + one;
995 QString five = QString(
"\"") + one;
997 where =
"SELECT DISTINCT title FROM program "
998 "LEFT JOIN channel ON program.chanid = channel.chanid "
999 "WHERE channel.deleted IS NULL "
1000 "AND channel.visible > 0 "
1001 "AND ( title LIKE :ONE OR title LIKE :TWO "
1002 " OR title LIKE :THREE "
1003 " OR title LIKE :FOUR "
1004 " OR title LIKE :FIVE )"
1005 "AND starttime > :STARTTIME ";
1007 where +=
"AND title LIKE :SEARCH ";
1009 where +=
"ORDER BY title;";
1011 bindings[
":ONE"] = one;
1012 bindings[
":TWO"] = two;
1013 bindings[
":THREE"] = three;
1014 bindings[
":FOUR"] = four;
1015 bindings[
":FIVE"] = five;
1016 bindings[
":STARTTIME"] =
1017 progStart.addSecs(50 - progStart.time().second());
1030 [[maybe_unused]]
int charNum)
1064 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'searchpopup'");
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
void LoadInBackground(const QString &message="")
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
MythScreenStack * GetMainStack()
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
static QString toUIState(RecStatus::Type recstatus)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
void ShowGuide() const override
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
static const Type kMythEventMessage
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, const QString &altTable="", int recordid=-1)
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual void ResetMap(const InfoMap &infoMap)
void customEvent(QEvent *event) override
void restoreSelectedData(QString &data) override
void alphabetListItemSelected(MythUIButtonListItem *item)
void RunProgramFinder(TV *player, bool embedVideo, bool allowEPG)
void bindValues(const MSqlBindings &bindings)
Add all the bindings in the passed in bindings.
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
This class is used as a container for messages.
void initAlphabetList() override
virtual bool formatSelectedData(QString &data)
static const std::vector< QChar > kSearchChars
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static void show(uint8_t *buf, int length)
QString GetText(void) const
MythUITextEdit * m_textEdit
virtual void ShowDetails(void) const
Show the Program Details screen.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
const QString & Message() const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
virtual void EditRecording(bool may_watch_now=false)
Creates a dialog for editing the recording status, blocking until user leaves dialog.
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
MythUIButtonList * m_timesList
MythUIType * GetFocusWidget(void) const
QHash< QString, QString > InfoMap
void addListener(QObject *listener)
Add a listener to the observable.
MythUIButtonList * m_alphabetList
ProgFinder(MythScreenStack *parentStack, bool allowEPG=true, TV *player=nullptr, bool embedVideo=false)
void SetText(const QString &text, bool moveCursor=true)
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
void timesListTakeFocus(void)
virtual void initAlphabetList(void)
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
static const std::vector< QChar > kSearchChars
void showListTakeFocus(void)
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
bool Create(void) override
bool SetFocusWidget(MythUIType *widget=nullptr)
Basic menu dialog, message and a list of options.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetTitle(void) const
bool formatSelectedData(QString &data) override
static void DBError(const QString &where, const MSqlQuery &query)
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
void BuildFocusList(void)
#define ACTION_CHANNELSEARCH
virtual void SetTextFromMap(const InfoMap &infoMap)
MythUIButtonList * m_showList
void SetPassword(bool isPassword)
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
void SetFilter(InputFilter filter)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythUIText * m_searchText
QString GetLanguage(void)
Returns two character ISO-639 language descriptor for UI language.
MythScreenStack * GetScreenStack() const
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
static const std::vector< QChar > kSearchChars
void restoreSelectedData(QString &data) override
void initAlphabetList() override
void ShowMenu(void) override
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
bool formatSelectedData(QString &data) override
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
virtual void whereClauseGetSearchData(QString &where, MSqlBindings &bindings)
Holds information on recordings and videos.
All purpose text widget, displays a text string.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void restoreSelectedData(QString &data) override
void timesListLosingFocus(void)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void selectShowData(QString progTitle, int newCurShow)
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
void customEvent(QEvent *e) override
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
void initAlphabetList() override
virtual void SetText(const QString &text)
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
static const Type kEventType
virtual void QuickRecord(void)
Create a kSingleRecord or bring up recording dialog.
MythMainWindow * GetMythMainWindow(void)
MythScreenStack * GetStack(const QString &Stackname)
ProgramInfo * GetCurrentProgram(void) const override
virtual void ShowChannelSearch(void) const
Show the channel search.
bool formatSelectedData(QString &data) override
@ kDateTimeFull
Default local time.
virtual int IncrRef(void)
Increments reference count.
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void removeListener(QObject *listener)
Remove a listener to the observable.
QString GetSetting(const QString &key, const QString &defaultval="")
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
virtual void restoreSelectedData(QString &data)