2#include <QCoreApplication>
28#define LOC QString("ProgFinder: ")
29#define LOC_ERR QString("ProgFinder, Error: ")
30#define LOC_WARN QString("ProgFinder, Warning: ")
38 programFind =
new JaProgFinder(mainStack, allowEPG, player, embedVideo);
40 programFind =
new HeProgFinder(mainStack, allowEPG, player, embedVideo);
42 programFind =
new RuProgFinder(mainStack, allowEPG, player, embedVideo);
44 programFind =
new ProgFinder(mainStack, allowEPG, player, embedVideo);
47 mainStack->
AddScreen(programFind, (player ==
nullptr));
53 TV *player,
bool embedVideo)
56 m_embedVideo(embedVideo),
80 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'programfind'");
181 for (
int i = 0; i < actions.size() && !handled; ++i)
183 const QString&
action = actions[i];
188 }
else if (
action ==
"CUSTOMEDIT") {
190 }
else if (
action ==
"UPCOMING") {
192 }
else if (
action ==
"PREVRECORDED") {
196 }
else if (
action ==
"TOGGLERECORD") {
202 }
else if (
action ==
"ESCAPE") {
226 menu->AddItem(tr(
"Clear Search"));
227 menu->AddItem(tr(
"Edit Search"));
230 auto *sortGroupMenu =
new MythMenu(tr(
"Sort/Group Options"),
this,
233 menu->AddItem(tr(
"Sort/Group"),
nullptr, sortGroupMenu);
234 menu->AddItem(tr(
"Toggle Record"));
235 menu->AddItem(tr(
"Program Details"));
236 menu->AddItem(tr(
"Upcoming"));
237 menu->AddItem(tr(
"Previously Recorded"));
238 menu->AddItem(tr(
"Custom Edit"));
239 menu->AddItem(tr(
"Program Guide"));
240 menu->AddItem(tr(
"Channel Search"));
246 if (!menuPopup->Create())
259 auto *me =
dynamic_cast<MythEvent *
>(event);
263 const QString& message = me->
Message();
265 if (message ==
"SCHEDULE_CHANGE"
266 || message ==
"GROUPBY_CHANGE")
281 QString resultid = dce->GetId();
282 QString resulttext = dce->GetResultText();
284 if (resultid ==
"menu")
286 if (resulttext == tr(
"Clear Search"))
294 else if (resulttext == tr(
"Edit Search"))
299 if (textInput->Create())
301 textInput->SetReturnEvent(
this,
"searchtext");
305 else if (resulttext == tr(
"Toggle Record"))
309 else if (resulttext == tr(
"Program Details"))
313 else if (resulttext == tr(
"Upcoming"))
317 else if (resulttext == tr(
"Previously Recorded"))
321 else if (resulttext == tr(
"Custom Edit"))
325 else if (resulttext == tr(
"Program Guide"))
329 else if (resulttext == tr(
"Channel Search"))
334 else if (resultid ==
"searchtext")
364 "Please select another search."));
372 "then press SELECT or the right arrow."));
384 "When finished return with the left arrow key. "
385 "Press SELECT to schedule a recording."));
400 "this search. Please select another "
419 uint startchanid = 0;
425 if (pginfo !=
nullptr)
459 starttime =
show->GetScheduledStartTime();
466 item->SetText(itemText,
"buttontext", state);
467 item->DisplayState(state,
"status");
469 show->ToMap(infoMap);
470 item->SetTextFromMap(infoMap, state);
496 data = query.
value(0).toString();
510 ShowName::Iterator it;
513 QString tmpProgData = *it;
530 QString querystr =
"WHERE program.title = :TITLE "
531 " AND program.endtime > :ENDTIME "
532 " AND channel.deleted IS NULL "
533 " AND channel.visible > 0 ";
534 bindings[
":TITLE"] = progTitle;
535 bindings[
":ENDTIME"] = progStart.addSecs(50 - progStart.time().second());
547 for (
int charNum = 48; charNum < 91; ++charNum)
563 if (searchChar.isEmpty())
566 if (searchChar.contains(
'@'))
568 where =
"SELECT DISTINCT title FROM program "
569 "LEFT JOIN channel ON program.chanid = channel.chanid "
570 "WHERE channel.deleted IS NULL AND "
571 " channel.visible > 0 AND "
572 "( title NOT REGEXP '^[A-Z0-9]' AND "
573 " title NOT REGEXP '^The [A-Z0-9]' AND "
574 " title NOT REGEXP '^A [A-Z0-9]' AND "
575 " title NOT REGEXP '^An [A-Z0-9]' AND "
576 " starttime > :STARTTIME ) ";
579 where +=
"AND title LIKE :SEARCH ";
583 where +=
"ORDER BY title;";
585 bindings[
":STARTTIME"] =
586 progStart.addSecs(50 - progStart.time().second());
590 QString one = searchChar +
'%';
591 QString two = QString(
"The ") + one;
592 QString three = QString(
"A ") + one;
593 QString four = QString(
"An ") + one;
595 where =
"SELECT DISTINCT title FROM program "
596 "LEFT JOIN channel ON program.chanid = channel.chanid "
597 "WHERE channel.deleted IS NULL "
598 "AND channel.visible > 0 "
599 "AND ( title LIKE :ONE OR title LIKE :TWO "
600 " OR title LIKE :THREE "
601 " OR title LIKE :FOUR ) "
602 "AND starttime > :STARTTIME ";
604 where +=
"AND title LIKE :SEARCH ";
606 where +=
"ORDER BY title;";
608 bindings[
":ONE"] = one;
609 bindings[
":TWO"] = two;
610 bindings[
":THREE"] = three;
611 bindings[
":FOUR"] = four;
612 bindings[
":STARTTIME"] =
613 progStart.addSecs(50 - progStart.time().second());
625 if (searchChar ==
"T")
627 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
631 else if (data.startsWith(
"The T"))
633 data = data.mid(4) +
", The";
635 else if (data.startsWith(
"A T"))
637 data = data.mid(2) +
", A";
645 else if (searchChar ==
"A")
647 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
651 else if (data.startsWith(
"The A"))
653 data = data.mid(4) +
", The";
655 else if (data.startsWith(
"A A"))
657 data = data.mid(2) +
", A";
659 else if (data.startsWith(
"An A"))
661 data = data.mid(3) +
", An";
671 if (data.startsWith(
"The "))
672 data = data.mid(4) +
", The";
673 else if (data.startsWith(
"A "))
674 data = data.mid(2) +
", A";
675 else if (data.startsWith(
"An "))
676 data = data.mid(3) +
", An";
686 if (charNum == 29 || charNum == 10)
688 if ((data.startsWith(
"The T") && charNum == 29) ||
689 (data.startsWith(
"The A") && charNum == 10)) {
690 data = data.mid(4) +
", The";
691 }
else if ((data.startsWith(
"A T") && charNum == 29) ||
692 (data.startsWith(
"A A") && charNum == 10)) {
693 data = data.mid(2) +
", A";
694 }
else if (data.startsWith(
"An A") && charNum == 10) {
695 data = data.mid(3) +
", An";
696 }
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'");
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
static const Type kEventType
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
void initAlphabetList() override
bool formatSelectedData(QString &data) override
static const std::vector< QChar > kSearchChars
void restoreSelectedData(QString &data) override
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
void restoreSelectedData(QString &data) override
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
void initAlphabetList() override
bool formatSelectedData(QString &data) override
static const std::vector< QChar > kSearchChars
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
void bindValues(const MSqlBindings &bindings)
Add all the bindings in the passed in bindings.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetSetting(const QString &key, const QString &defaultval="")
QString GetLanguage(void)
Returns two character ISO-639 language descriptor for UI language.
static void DBError(const QString &where, const MSqlQuery &query)
Basic menu dialog, message and a list of options.
This class is used as a container for messages.
const QString & Message() const
static const Type kMythEventMessage
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void LoadInBackground(const QString &message="")
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
MythScreenStack * GetScreenStack() const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
MythUITextEdit * m_textEdit
virtual void SetTextFromMap(const InfoMap &infoMap)
virtual void ResetMap(const InfoMap &infoMap)
void SetPassword(bool isPassword)
QString GetText(void) const
void SetText(const QString &text, bool moveCursor=true)
void SetFilter(InputFilter filter)
All purpose text widget, displays a text string.
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
virtual void SetText(const QString &text)
MythUIButtonList * m_showList
bool Create(void) override
void ShowGuide() const override
Show the program guide.
MythUIButtonList * m_timesList
void timesListTakeFocus(void)
void timesListLosingFocus(void)
virtual void whereClauseGetSearchData(QString &where, MSqlBindings &bindings)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
ProgramInfo * GetCurrentProgram(void) const override
void selectShowData(QString progTitle, int newCurShow)
MythUIText * m_searchText
virtual void initAlphabetList(void)
void ShowMenu(void) override
ProgFinder(MythScreenStack *parentStack, bool allowEPG=true, TV *player=nullptr, bool embedVideo=false)
virtual bool formatSelectedData(QString &data)
void alphabetListItemSelected(MythUIButtonListItem *item)
void customEvent(QEvent *e) override
virtual void restoreSelectedData(QString &data)
MythUIText * m_groupByText
void showListTakeFocus(void)
MythUIButtonList * m_alphabetList
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
static QString toString(ProgGroupBy::Type groupBy)
Holds information on recordings and videos.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
QString GetTitle(void) const
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
static QString toUIState(RecStatus::Type recstatus)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
void whereClauseGetSearchData(QString &where, MSqlBindings &bindings) override
static const std::vector< QChar > kSearchChars
void restoreSelectedData(QString &data) override
void initAlphabetList() override
bool formatSelectedData(QString &data) override
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
virtual void EditRecording(bool may_watch_now=false)
Creates a dialog for editing the recording status, blocking until user leaves dialog.
static ProgGroupBy::Type GetProgramListGroupBy(void)
virtual void ShowDetails(void) const
Show the Program Details screen.
virtual void AddGroupMenuItems(MythMenu *sortGroupMenu)
void customEvent(QEvent *event) override
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
virtual void QuickRecord(void)
Create a kSingleRecord or bring up recording dialog.
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
virtual void ShowChannelSearch(void) const
Show the channel search.
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
static MythThemedMenu * menu
QHash< QString, QString > InfoMap
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kDateTimeFull
Default local time.
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
void RunProgramFinder(TV *player, bool embedVideo, bool allowEPG)
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, const QString &altTable="", int recordid=-1)
static void show(uint8_t *buf, int length)
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
#define ACTION_CHANNELSEARCH