Go to the documentation of this file.
6 #include <QCoreApplication>
31 #define LOC QString("ProgFinder: ")
32 #define LOC_ERR QString("ProgFinder, Error: ")
33 #define LOC_WARN QString("ProgFinder, Warning: ")
41 programFind =
new JaProgFinder(mainStack, allowEPG, player, embedVideo);
43 programFind =
new HeProgFinder(mainStack, allowEPG, player, embedVideo);
45 programFind =
new RuProgFinder(mainStack, allowEPG, player, embedVideo);
47 programFind =
new ProgFinder(mainStack, allowEPG, player, embedVideo);
50 mainStack->
AddScreen(programFind, (player ==
nullptr));
56 TV *player,
bool embedVideo)
59 m_embedVideo(embedVideo),
82 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'programfind'");
183 for (
int i = 0; i < actions.size() && !handled; ++i)
185 QString
action = actions[i];
190 else if (
action ==
"CUSTOMEDIT")
192 else if (
action ==
"UPCOMING")
194 else if (
action ==
"PREVRECORDED")
198 else if (
action ==
"TOGGLERECORD")
204 else if (
action ==
"ESCAPE")
226 QString label = tr(
"Options");
229 auto *menuPopup =
new MythDialogBox(label, popupStack,
"menuPopup");
231 if (menuPopup->Create())
233 menuPopup->SetReturnEvent(
this,
"menu");
236 menuPopup->AddButton(tr(
"Clear Search"));
237 menuPopup->AddButton(tr(
"Edit Search"));
240 menuPopup->AddButton(tr(
"Toggle Record"));
241 menuPopup->AddButton(tr(
"Program Details"));
242 menuPopup->AddButton(tr(
"Upcoming"));
243 menuPopup->AddButton(tr(
"Previously Recorded"));
244 menuPopup->AddButton(tr(
"Custom Edit"));
245 menuPopup->AddButton(tr(
"Program Guide"));
246 menuPopup->AddButton(tr(
"Channel Search"));
261 auto *me =
dynamic_cast<MythEvent *
>(event);
265 const QString& message = me->
Message();
267 if (message ==
"SCHEDULE_CHANGE")
282 QString resultid = dce->GetId();
283 QString resulttext = dce->GetResultText();
285 if (resultid ==
"menu")
287 if (resulttext == tr(
"Clear Search"))
295 else if (resulttext == tr(
"Edit Search"))
300 if (textInput->Create())
302 textInput->SetReturnEvent(
this,
"searchtext");
306 else if (resulttext == tr(
"Toggle Record"))
310 else if (resulttext == tr(
"Program Details"))
314 else if (resulttext == tr(
"Upcoming"))
318 else if (resulttext == tr(
"Previously Recorded"))
322 else if (resulttext == tr(
"Custom Edit"))
326 else if (resulttext == tr(
"Program Guide"))
330 else if (resulttext == tr(
"Channel Search"))
335 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);
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"))
629 data = data.mid(4) +
", The";
630 else if (data.startsWith(
"A T"))
631 data = data.mid(2) +
", A";
638 else if (searchChar ==
"A")
640 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
644 else if (data.startsWith(
"The A"))
645 data = data.mid(4) +
", The";
646 else if (data.startsWith(
"A A"))
647 data = data.mid(2) +
", A";
648 else if (data.startsWith(
"An A"))
649 data = data.mid(3) +
", An";
658 if (data.startsWith(
"The "))
659 data = data.mid(4) +
", The";
660 else if (data.startsWith(
"A "))
661 data = data.mid(2) +
", A";
662 else if (data.startsWith(
"An "))
663 data = data.mid(3) +
", An";
673 if (charNum == 29 || charNum == 10)
675 if ((data.startsWith(
"The T") && charNum == 29) ||
676 (data.startsWith(
"The A") && charNum == 10))
677 data = data.mid(4) +
", The";
678 else if ((data.startsWith(
"A T") && charNum == 29) ||
679 (data.startsWith(
"A A") && charNum == 10))
680 data = data.mid(2) +
", A";
681 else if (data.startsWith(
"An A") && charNum == 10)
682 data = data.mid(3) +
", An";
683 else if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
695 if (data.startsWith(
"The "))
696 data = data.mid(4) +
", The";
697 if (data.startsWith(
"A "))
698 data = data.mid(2) +
", A";
699 if (data.startsWith(
"An "))
700 data = data.mid(3) +
", An";
708 if (data.endsWith(
", The"))
709 data =
"The " + data.left(data.length() - 5);
710 if (data.endsWith(
", A"))
711 data =
"A " + data.left(data.length() - 3);
721 QChar(0x3042), QChar(0x304b), QChar(0x3055), QChar(0x305f),
723 QChar(0x306a), QChar(0x306f), QChar(0x307e), QChar(0x3084),
725 QChar(0x3089), QChar(0x308f), QChar(0x82f1), QChar(0x6570),
745 where =
"SELECT DISTINCT title FROM program "
746 "LEFT JOIN channel ON program.chanid = channel.chanid "
747 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
751 where +=
"AND ( title_pronounce >= 'あ' AND title_pronounce <= 'お') ";
754 where +=
"AND ( title_pronounce >= 'か' AND title_pronounce <= 'ご') ";
757 where +=
"AND ( title_pronounce >= 'さ' AND title_pronounce <= 'そ') ";
760 where +=
"AND ( title_pronounce >= 'た' AND title_pronounce <= 'ど') ";
763 where +=
"AND ( title_pronounce >= 'な' AND title_pronounce <= 'の') ";
766 where +=
"AND ( title_pronounce >= 'は' AND title_pronounce <= 'ぽ') ";
769 where +=
"AND ( title_pronounce >= 'ま' AND title_pronounce <= 'も') ";
772 where +=
"AND ( title_pronounce >= 'や' AND title_pronounce <= 'よ') ";
775 where +=
"AND ( title_pronounce >= 'ら' AND title_pronounce <= 'ろ') ";
778 where +=
"AND ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') ";
781 where +=
"AND ( title_pronounce >= 'A' AND title_pronounce <= 'z') ";
784 where +=
"AND ( title_pronounce >= '0' AND title_pronounce <= '9') ";
788 where +=
"AND starttime > :STARTTIME ";
792 where +=
"AND title_pronounce LIKE :SEARCH ";
796 where +=
"ORDER BY title_pronounce;";
798 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
826 QChar(0x5d0), QChar(0x5d1), QChar(0x5d2), QChar(0x5d3),
828 QChar(0x5d4), QChar(0x5d5), QChar(0x5d6), QChar(0x5d7),
830 QChar(0x5d8), QChar(0x5d9), QChar(0x5db), QChar(0x5dc),
832 QChar(0x5de), QChar(0x5e0), QChar(0x5e1), QChar(0x5e2),
834 QChar(0x5e4), QChar(0x5e6), QChar(0x5e7), QChar(0x5e8),
836 QChar(0x5e9), QChar(0x5ea), QChar(
'E'), QChar(
'#'),
854 if (searchChar.isEmpty())
857 where =
"SELECT DISTINCT title FROM program "
858 "LEFT JOIN channel ON program.chanid = channel.chanid "
859 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
861 if (searchChar.contains(
'E'))
863 where +=
"AND ( title REGEXP '^[A-Z]') ";
865 else if (searchChar.contains(
'#'))
867 where +=
"AND ( title REGEXP '^[0-9]') ";
871 QString one = searchChar +
'%';
872 bindings[
":ONE"] = one;
873 where +=
"AND ( title LIKE :ONE ) ";
876 where +=
"AND starttime > :STARTTIME ";
880 where +=
"AND title LIKE :SEARCH ";
884 where +=
"ORDER BY title;";
886 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
914 QChar(0x410), QChar(0x411), QChar(0x412), QChar(0x413),
916 QChar(0x414), QChar(0x415), QChar(0x401), QChar(0x416),
918 QChar(0x417), QChar(0x418), QChar(0x419), QChar(0x41a),
920 QChar(0x41b), QChar(0x41c), QChar(0x41d), QChar(0x41e),
922 QChar(0x41f), QChar(0x420), QChar(0x421), QChar(0x422),
924 QChar(0x423), QChar(0x424), QChar(0x425), QChar(0x426),
926 QChar(0x427), QChar(0x428), QChar(0x429), QChar(0x42a),
928 QChar(0x42b), QChar(0x44c), QChar(0x42d), QChar(0x42e),
930 QChar(0x42f), QChar(
'0'), QChar(
'1'), QChar(
'2'),
931 QChar(
'3'), QChar(
'4'), QChar(
'5'), QChar(
'6'),
932 QChar(
'7'), QChar(
'8'), QChar(
'9'), QChar(
'@'),
933 QChar(
'A'), QChar(
'B'), QChar(
'C'), QChar(
'D'),
934 QChar(
'E'), QChar(
'F'), QChar(
'G'), QChar(
'H'),
935 QChar(
'I'), QChar(
'J'), QChar(
'K'), QChar(
'L'),
936 QChar(
'M'), QChar(
'N'), QChar(
'O'), QChar(
'P'),
937 QChar(
'Q'), QChar(
'R'), QChar(
'S'), QChar(
'T'),
938 QChar(
'U'), QChar(
'V'), QChar(
'W'), QChar(
'X'),
939 QChar(
'Y'), QChar(
'Z')
958 if (searchChar.isEmpty())
962 if (searchChar.contains(
'@'))
964 where =
"SELECT DISTINCT title FROM program "
965 "LEFT JOIN channel ON program.chanid = channel.chanid "
966 "WHERE channel.deleted IS NULL AND "
967 " channel.visible > 0 AND "
969 "title NOT REGEXP '^[A-Z0-9]' AND "
970 "title NOT REGEXP '^The [A-Z0-9]' AND "
971 "title NOT REGEXP '^A [A-Z0-9]' AND "
972 "title NOT REGEXP '^[0-9]' AND "
973 "starttime > :STARTTIME ) ";
976 where +=
"AND title LIKE :SEARCH ";
980 where +=
"ORDER BY title;";
982 bindings[
":STARTTIME"] =
983 progStart.addSecs(50 - progStart.time().second());
987 QString one = searchChar +
'%';
988 QString two = QString(
"The ") + one;
989 QString three = QString(
"A ") + one;
990 QString four = QString(
"An ") + one;
991 QString five = QString(
"\"") + one;
993 where =
"SELECT DISTINCT title FROM program "
994 "LEFT JOIN channel ON program.chanid = channel.chanid "
995 "WHERE channel.deleted IS NULL "
996 "AND channel.visible > 0 "
997 "AND ( title LIKE :ONE OR title LIKE :TWO "
998 " OR title LIKE :THREE "
999 " OR title LIKE :FOUR "
1000 " OR title LIKE :FIVE )"
1001 "AND starttime > :STARTTIME ";
1003 where +=
"AND title LIKE :SEARCH ";
1005 where +=
"ORDER BY title;";
1007 bindings[
":ONE"] = one;
1008 bindings[
":TWO"] = two;
1009 bindings[
":THREE"] = three;
1010 bindings[
":FOUR"] = four;
1011 bindings[
":FIVE"] = five;
1012 bindings[
":STARTTIME"] =
1013 progStart.addSecs(50 - progStart.time().second());
1063 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={})
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)
static QString toUIState(Type recstatus)
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)
MSqlQuery query(MSqlQuery::InitCon())
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)