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 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")
222 QString label = tr(
"Options");
225 auto *menuPopup =
new MythDialogBox(label, popupStack,
"menuPopup");
227 if (menuPopup->Create())
229 menuPopup->SetReturnEvent(
this,
"menu");
232 menuPopup->AddButton(tr(
"Clear Search"));
233 menuPopup->AddButton(tr(
"Edit Search"));
236 menuPopup->AddButton(tr(
"Toggle Record"));
237 menuPopup->AddButton(tr(
"Program Details"));
238 menuPopup->AddButton(tr(
"Upcoming"));
239 menuPopup->AddButton(tr(
"Previously Recorded"));
240 menuPopup->AddButton(tr(
"Custom Edit"));
241 menuPopup->AddButton(tr(
"Program Guide"));
242 menuPopup->AddButton(tr(
"Channel Search"));
257 auto *me =
dynamic_cast<MythEvent *
>(event);
261 const QString& message = me->
Message();
263 if (message ==
"SCHEDULE_CHANGE")
278 QString resultid = dce->GetId();
279 QString resulttext = dce->GetResultText();
281 if (resultid ==
"menu")
283 if (resulttext == tr(
"Clear Search"))
291 else if (resulttext == tr(
"Edit Search"))
296 if (textInput->Create())
298 textInput->SetReturnEvent(
this,
"searchtext");
302 else if (resulttext == tr(
"Toggle Record"))
306 else if (resulttext == tr(
"Program Details"))
310 else if (resulttext == tr(
"Upcoming"))
314 else if (resulttext == tr(
"Previously Recorded"))
318 else if (resulttext == tr(
"Custom Edit"))
322 else if (resulttext == tr(
"Program Guide"))
326 else if (resulttext == tr(
"Channel Search"))
331 else if (resultid ==
"searchtext")
359 "Please select another search."));
367 "then press SELECT or the right arrow."));
379 "When finished return with the left arrow key. "
380 "Press SELECT to schedule a recording."));
395 "this search. Please select another "
414 uint startchanid = 0;
420 if (pginfo !=
nullptr)
454 starttime =
show->GetScheduledStartTime();
461 item->SetText(itemText,
"buttontext", state);
462 item->DisplayState(state,
"status");
464 show->ToMap(infoMap);
465 item->SetTextFromMap(infoMap, state);
491 data = query.
value(0).toString();
505 ShowName::Iterator it;
508 QString tmpProgData = *it;
523 QString querystr =
"WHERE program.title = :TITLE "
524 " AND program.endtime > :ENDTIME "
525 " AND channel.deleted IS NULL "
526 " AND channel.visible > 0 ";
527 bindings[
":TITLE"] = progTitle;
528 bindings[
":ENDTIME"] = progStart.addSecs(50 - progStart.time().second());
540 for (
int charNum = 48; charNum < 91; ++charNum)
556 if (searchChar.isEmpty())
559 if (searchChar.contains(
'@'))
561 where =
"SELECT DISTINCT title FROM program "
562 "LEFT JOIN channel ON program.chanid = channel.chanid "
563 "WHERE channel.deleted IS NULL AND "
564 " channel.visible > 0 AND "
565 "( title NOT REGEXP '^[A-Z0-9]' AND "
566 " title NOT REGEXP '^The [A-Z0-9]' AND "
567 " title NOT REGEXP '^A [A-Z0-9]' AND "
568 " title NOT REGEXP '^An [A-Z0-9]' AND "
569 " starttime > :STARTTIME ) ";
572 where +=
"AND title LIKE :SEARCH ";
576 where +=
"ORDER BY title;";
578 bindings[
":STARTTIME"] =
579 progStart.addSecs(50 - progStart.time().second());
583 QString one = searchChar +
'%';
584 QString two = QString(
"The ") + one;
585 QString three = QString(
"A ") + one;
586 QString four = QString(
"An ") + one;
588 where =
"SELECT DISTINCT title FROM program "
589 "LEFT JOIN channel ON program.chanid = channel.chanid "
590 "WHERE channel.deleted IS NULL "
591 "AND channel.visible > 0 "
592 "AND ( title LIKE :ONE OR title LIKE :TWO "
593 " OR title LIKE :THREE "
594 " OR title LIKE :FOUR ) "
595 "AND starttime > :STARTTIME ";
597 where +=
"AND title LIKE :SEARCH ";
599 where +=
"ORDER BY title;";
601 bindings[
":ONE"] = one;
602 bindings[
":TWO"] = two;
603 bindings[
":THREE"] = three;
604 bindings[
":FOUR"] = four;
605 bindings[
":STARTTIME"] =
606 progStart.addSecs(50 - progStart.time().second());
618 if (searchChar ==
"T")
620 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
624 else if (data.startsWith(
"The T"))
625 data = data.mid(4) +
", The";
626 else if (data.startsWith(
"A T"))
627 data = data.mid(2) +
", A";
634 else if (searchChar ==
"A")
636 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
640 else if (data.startsWith(
"The A"))
641 data = data.mid(4) +
", The";
642 else if (data.startsWith(
"A A"))
643 data = data.mid(2) +
", A";
644 else if (data.startsWith(
"An A"))
645 data = data.mid(3) +
", An";
654 if (data.startsWith(
"The "))
655 data = data.mid(4) +
", The";
656 else if (data.startsWith(
"A "))
657 data = data.mid(2) +
", A";
658 else if (data.startsWith(
"An "))
659 data = data.mid(3) +
", An";
669 if (charNum == 29 || charNum == 10)
671 if ((data.startsWith(
"The T") && charNum == 29) ||
672 (data.startsWith(
"The A") && charNum == 10))
673 data = data.mid(4) +
", The";
674 else if ((data.startsWith(
"A T") && charNum == 29) ||
675 (data.startsWith(
"A A") && charNum == 10))
676 data = data.mid(2) +
", A";
677 else if (data.startsWith(
"An A") && charNum == 10)
678 data = data.mid(3) +
", An";
679 else if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
691 if (data.startsWith(
"The "))
692 data = data.mid(4) +
", The";
693 if (data.startsWith(
"A "))
694 data = data.mid(2) +
", A";
695 if (data.startsWith(
"An "))
696 data = data.mid(3) +
", An";
704 if (data.endsWith(
", The"))
705 data =
"The " + data.left(data.length() - 5);
706 if (data.endsWith(
", A"))
707 data =
"A " + data.left(data.length() - 3);
717 QChar(0x3042), QChar(0x304b), QChar(0x3055), QChar(0x305f),
719 QChar(0x306a), QChar(0x306f), QChar(0x307e), QChar(0x3084),
721 QChar(0x3089), QChar(0x308f), QChar(0x82f1), QChar(0x6570),
741 where =
"SELECT DISTINCT title FROM program "
742 "LEFT JOIN channel ON program.chanid = channel.chanid "
743 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
747 where +=
"AND ( title_pronounce >= 'あ' AND title_pronounce <= 'お') ";
750 where +=
"AND ( title_pronounce >= 'か' AND title_pronounce <= 'ご') ";
753 where +=
"AND ( title_pronounce >= 'さ' AND title_pronounce <= 'そ') ";
756 where +=
"AND ( title_pronounce >= 'た' AND title_pronounce <= 'ど') ";
759 where +=
"AND ( title_pronounce >= 'な' AND title_pronounce <= 'の') ";
762 where +=
"AND ( title_pronounce >= 'は' AND title_pronounce <= 'ぽ') ";
765 where +=
"AND ( title_pronounce >= 'ま' AND title_pronounce <= 'も') ";
768 where +=
"AND ( title_pronounce >= 'や' AND title_pronounce <= 'よ') ";
771 where +=
"AND ( title_pronounce >= 'ら' AND title_pronounce <= 'ろ') ";
774 where +=
"AND ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') ";
777 where +=
"AND ( title_pronounce >= 'A' AND title_pronounce <= 'z') ";
780 where +=
"AND ( title_pronounce >= '0' AND title_pronounce <= '9') ";
784 where +=
"AND starttime > :STARTTIME ";
788 where +=
"AND title_pronounce LIKE :SEARCH ";
792 where +=
"ORDER BY title_pronounce;";
794 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
822 QChar(0x5d0), QChar(0x5d1), QChar(0x5d2), QChar(0x5d3),
824 QChar(0x5d4), QChar(0x5d5), QChar(0x5d6), QChar(0x5d7),
826 QChar(0x5d8), QChar(0x5d9), QChar(0x5db), QChar(0x5dc),
828 QChar(0x5de), QChar(0x5e0), QChar(0x5e1), QChar(0x5e2),
830 QChar(0x5e4), QChar(0x5e6), QChar(0x5e7), QChar(0x5e8),
832 QChar(0x5e9), QChar(0x5ea), QChar(
'E'), QChar(
'#'),
850 if (searchChar.isEmpty())
853 where =
"SELECT DISTINCT title FROM program "
854 "LEFT JOIN channel ON program.chanid = channel.chanid "
855 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
857 if (searchChar.contains(
'E'))
859 where +=
"AND ( title REGEXP '^[A-Z]') ";
861 else if (searchChar.contains(
'#'))
863 where +=
"AND ( title REGEXP '^[0-9]') ";
867 QString one = searchChar +
'%';
868 bindings[
":ONE"] = one;
869 where +=
"AND ( title LIKE :ONE ) ";
872 where +=
"AND starttime > :STARTTIME ";
876 where +=
"AND title LIKE :SEARCH ";
880 where +=
"ORDER BY title;";
882 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
910 QChar(0x410), QChar(0x411), QChar(0x412), QChar(0x413),
912 QChar(0x414), QChar(0x415), QChar(0x401), QChar(0x416),
914 QChar(0x417), QChar(0x418), QChar(0x419), QChar(0x41a),
916 QChar(0x41b), QChar(0x41c), QChar(0x41d), QChar(0x41e),
918 QChar(0x41f), QChar(0x420), QChar(0x421), QChar(0x422),
920 QChar(0x423), QChar(0x424), QChar(0x425), QChar(0x426),
922 QChar(0x427), QChar(0x428), QChar(0x429), QChar(0x42a),
924 QChar(0x42b), QChar(0x44c), QChar(0x42d), QChar(0x42e),
926 QChar(0x42f), QChar(
'0'), QChar(
'1'), QChar(
'2'),
927 QChar(
'3'), QChar(
'4'), QChar(
'5'), QChar(
'6'),
928 QChar(
'7'), QChar(
'8'), QChar(
'9'), QChar(
'@'),
929 QChar(
'A'), QChar(
'B'), QChar(
'C'), QChar(
'D'),
930 QChar(
'E'), QChar(
'F'), QChar(
'G'), QChar(
'H'),
931 QChar(
'I'), QChar(
'J'), QChar(
'K'), QChar(
'L'),
932 QChar(
'M'), QChar(
'N'), QChar(
'O'), QChar(
'P'),
933 QChar(
'Q'), QChar(
'R'), QChar(
'S'), QChar(
'T'),
934 QChar(
'U'), QChar(
'V'), QChar(
'W'), QChar(
'X'),
935 QChar(
'Y'), QChar(
'Z')
954 if (searchChar.isEmpty())
958 if (searchChar.contains(
'@'))
960 where =
"SELECT DISTINCT title FROM program "
961 "LEFT JOIN channel ON program.chanid = channel.chanid "
962 "WHERE channel.deleted IS NULL AND "
963 " channel.visible > 0 AND "
965 "title NOT REGEXP '^[A-Z0-9]' AND "
966 "title NOT REGEXP '^The [A-Z0-9]' AND "
967 "title NOT REGEXP '^A [A-Z0-9]' AND "
968 "title NOT REGEXP '^[0-9]' AND "
969 "starttime > :STARTTIME ) ";
972 where +=
"AND title LIKE :SEARCH ";
976 where +=
"ORDER BY title;";
978 bindings[
":STARTTIME"] =
979 progStart.addSecs(50 - progStart.time().second());
983 QString one = searchChar +
'%';
984 QString two = QString(
"The ") + one;
985 QString three = QString(
"A ") + one;
986 QString four = QString(
"An ") + one;
987 QString five = QString(
"\"") + one;
989 where =
"SELECT DISTINCT title FROM program "
990 "LEFT JOIN channel ON program.chanid = channel.chanid "
991 "WHERE channel.deleted IS NULL "
992 "AND channel.visible > 0 "
993 "AND ( title LIKE :ONE OR title LIKE :TWO "
994 " OR title LIKE :THREE "
995 " OR title LIKE :FOUR "
996 " OR title LIKE :FIVE )"
997 "AND starttime > :STARTTIME ";
999 where +=
"AND title LIKE :SEARCH ";
1001 where +=
"ORDER BY title;";
1003 bindings[
":ONE"] = one;
1004 bindings[
":TWO"] = two;
1005 bindings[
":THREE"] = three;
1006 bindings[
":FOUR"] = four;
1007 bindings[
":FIVE"] = five;
1008 bindings[
":STARTTIME"] =
1009 progStart.addSecs(50 - progStart.time().second());
1059 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 Type MythEventMessage
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
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.
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)