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")
229 menu->AddItem(tr(
"Clear Search"));
230 menu->AddItem(tr(
"Edit Search"));
233 auto *sortGroupMenu =
new MythMenu(tr(
"Sort/Group Options"),
this,
236 menu->AddItem(tr(
"Sort/Group"),
nullptr, sortGroupMenu);
237 menu->AddItem(tr(
"Toggle Record"));
238 menu->AddItem(tr(
"Program Details"));
239 menu->AddItem(tr(
"Upcoming"));
240 menu->AddItem(tr(
"Previously Recorded"));
241 menu->AddItem(tr(
"Custom Edit"));
242 menu->AddItem(tr(
"Program Guide"));
243 menu->AddItem(tr(
"Channel Search"));
249 if (!menuPopup->Create())
262 auto *me =
dynamic_cast<MythEvent *
>(event);
266 const QString& message = me->
Message();
268 if (message ==
"SCHEDULE_CHANGE"
269 || message ==
"GROUPBY_CHANGE")
284 QString resultid = dce->GetId();
285 QString resulttext = dce->GetResultText();
287 if (resultid ==
"menu")
289 if (resulttext == tr(
"Clear Search"))
297 else if (resulttext == tr(
"Edit Search"))
302 if (textInput->Create())
304 textInput->SetReturnEvent(
this,
"searchtext");
308 else if (resulttext == tr(
"Toggle Record"))
312 else if (resulttext == tr(
"Program Details"))
316 else if (resulttext == tr(
"Upcoming"))
320 else if (resulttext == tr(
"Previously Recorded"))
324 else if (resulttext == tr(
"Custom Edit"))
328 else if (resulttext == tr(
"Program Guide"))
332 else if (resulttext == tr(
"Channel Search"))
337 else if (resultid ==
"searchtext")
367 "Please select another search."));
375 "then press SELECT or the right arrow."));
387 "When finished return with the left arrow key. "
388 "Press SELECT to schedule a recording."));
403 "this search. Please select another "
422 uint startchanid = 0;
428 if (pginfo !=
nullptr)
462 starttime =
show->GetScheduledStartTime();
469 item->SetText(itemText,
"buttontext", state);
470 item->DisplayState(state,
"status");
472 show->ToMap(infoMap);
473 item->SetTextFromMap(infoMap, state);
499 data = query.
value(0).toString();
513 ShowName::Iterator it;
516 QString tmpProgData = *it;
533 QString querystr =
"WHERE program.title = :TITLE "
534 " AND program.endtime > :ENDTIME "
535 " AND channel.deleted IS NULL "
536 " AND channel.visible > 0 ";
537 bindings[
":TITLE"] = progTitle;
538 bindings[
":ENDTIME"] = progStart.addSecs(50 - progStart.time().second());
550 for (
int charNum = 48; charNum < 91; ++charNum)
566 if (searchChar.isEmpty())
569 if (searchChar.contains(
'@'))
571 where =
"SELECT DISTINCT title FROM program "
572 "LEFT JOIN channel ON program.chanid = channel.chanid "
573 "WHERE channel.deleted IS NULL AND "
574 " channel.visible > 0 AND "
575 "( title NOT REGEXP '^[A-Z0-9]' AND "
576 " title NOT REGEXP '^The [A-Z0-9]' AND "
577 " title NOT REGEXP '^A [A-Z0-9]' AND "
578 " title NOT REGEXP '^An [A-Z0-9]' AND "
579 " starttime > :STARTTIME ) ";
582 where +=
"AND title LIKE :SEARCH ";
586 where +=
"ORDER BY title;";
588 bindings[
":STARTTIME"] =
589 progStart.addSecs(50 - progStart.time().second());
593 QString one = searchChar +
'%';
594 QString two = QString(
"The ") + one;
595 QString three = QString(
"A ") + one;
596 QString four = QString(
"An ") + one;
598 where =
"SELECT DISTINCT title FROM program "
599 "LEFT JOIN channel ON program.chanid = channel.chanid "
600 "WHERE channel.deleted IS NULL "
601 "AND channel.visible > 0 "
602 "AND ( title LIKE :ONE OR title LIKE :TWO "
603 " OR title LIKE :THREE "
604 " OR title LIKE :FOUR ) "
605 "AND starttime > :STARTTIME ";
607 where +=
"AND title LIKE :SEARCH ";
609 where +=
"ORDER BY title;";
611 bindings[
":ONE"] = one;
612 bindings[
":TWO"] = two;
613 bindings[
":THREE"] = three;
614 bindings[
":FOUR"] = four;
615 bindings[
":STARTTIME"] =
616 progStart.addSecs(50 - progStart.time().second());
628 if (searchChar ==
"T")
630 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
634 else if (data.startsWith(
"The T"))
636 data = data.mid(4) +
", The";
638 else if (data.startsWith(
"A T"))
640 data = data.mid(2) +
", A";
648 else if (searchChar ==
"A")
650 if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
654 else if (data.startsWith(
"The A"))
656 data = data.mid(4) +
", The";
658 else if (data.startsWith(
"A A"))
660 data = data.mid(2) +
", A";
662 else if (data.startsWith(
"An A"))
664 data = data.mid(3) +
", An";
674 if (data.startsWith(
"The "))
675 data = data.mid(4) +
", The";
676 else if (data.startsWith(
"A "))
677 data = data.mid(2) +
", A";
678 else if (data.startsWith(
"An "))
679 data = data.mid(3) +
", An";
689 if (charNum == 29 || charNum == 10)
691 if ((data.startsWith(
"The T") && charNum == 29) ||
692 (data.startsWith(
"The A") && charNum == 10))
693 data = data.mid(4) +
", The";
694 else if ((data.startsWith(
"A T") && charNum == 29) ||
695 (data.startsWith(
"A A") && charNum == 10))
696 data = data.mid(2) +
", A";
697 else if (data.startsWith(
"An A") && charNum == 10)
698 data = data.mid(3) +
", An";
699 else if (!data.startsWith(
"The ") && !data.startsWith(
"A "))
711 if (data.startsWith(
"The "))
712 data = data.mid(4) +
", The";
713 if (data.startsWith(
"A "))
714 data = data.mid(2) +
", A";
715 if (data.startsWith(
"An "))
716 data = data.mid(3) +
", An";
724 if (data.endsWith(
", The"))
725 data =
"The " + data.left(data.length() - 5);
726 if (data.endsWith(
", A"))
727 data =
"A " + data.left(data.length() - 3);
737 QChar(0x3042), QChar(0x304b), QChar(0x3055), QChar(0x305f),
739 QChar(0x306a), QChar(0x306f), QChar(0x307e), QChar(0x3084),
741 QChar(0x3089), QChar(0x308f), QChar(0x82f1), QChar(0x6570),
761 where =
"SELECT DISTINCT title FROM program "
762 "LEFT JOIN channel ON program.chanid = channel.chanid "
763 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
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 >= 'ら' AND title_pronounce <= 'ろ') ";
794 where +=
"AND ( title_pronounce >= 'わ' AND title_pronounce <= 'ん') ";
797 where +=
"AND ( title_pronounce >= 'A' AND title_pronounce <= 'z') ";
800 where +=
"AND ( title_pronounce >= '0' AND title_pronounce <= '9') ";
804 where +=
"AND starttime > :STARTTIME ";
808 where +=
"AND title_pronounce LIKE :SEARCH ";
812 where +=
"ORDER BY title_pronounce;";
814 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
824 [[maybe_unused]]
int charNum)
839 QChar(0x5d0), QChar(0x5d1), QChar(0x5d2), QChar(0x5d3),
841 QChar(0x5d4), QChar(0x5d5), QChar(0x5d6), QChar(0x5d7),
843 QChar(0x5d8), QChar(0x5d9), QChar(0x5db), QChar(0x5dc),
845 QChar(0x5de), QChar(0x5e0), QChar(0x5e1), QChar(0x5e2),
847 QChar(0x5e4), QChar(0x5e6), QChar(0x5e7), QChar(0x5e8),
849 QChar(0x5e9), QChar(0x5ea), QChar(
'E'), QChar(
'#'),
867 if (searchChar.isEmpty())
870 where =
"SELECT DISTINCT title FROM program "
871 "LEFT JOIN channel ON program.chanid = channel.chanid "
872 "WHERE channel.deleted IS NULL AND channel.visible > 0 ";
874 if (searchChar.contains(
'E'))
876 where +=
"AND ( title REGEXP '^[A-Z]') ";
878 else if (searchChar.contains(
'#'))
880 where +=
"AND ( title REGEXP '^[0-9]') ";
884 QString one = searchChar +
'%';
885 bindings[
":ONE"] = one;
886 where +=
"AND ( title LIKE :ONE ) ";
889 where +=
"AND starttime > :STARTTIME ";
893 where +=
"AND title LIKE :SEARCH ";
897 where +=
"ORDER BY title;";
899 bindings[
":STARTTIME"] = progStart.addSecs(50 - progStart.time().second());
908 [[maybe_unused]]
int charNum)
924 QChar(0x410), QChar(0x411), QChar(0x412), QChar(0x413),
926 QChar(0x414), QChar(0x415), QChar(0x401), QChar(0x416),
928 QChar(0x417), QChar(0x418), QChar(0x419), QChar(0x41a),
930 QChar(0x41b), QChar(0x41c), QChar(0x41d), QChar(0x41e),
932 QChar(0x41f), QChar(0x420), QChar(0x421), QChar(0x422),
934 QChar(0x423), QChar(0x424), QChar(0x425), QChar(0x426),
936 QChar(0x427), QChar(0x428), QChar(0x429), QChar(0x42a),
938 QChar(0x42b), QChar(0x44c), QChar(0x42d), QChar(0x42e),
940 QChar(0x42f), QChar(
'0'), QChar(
'1'), QChar(
'2'),
941 QChar(
'3'), QChar(
'4'), QChar(
'5'), QChar(
'6'),
942 QChar(
'7'), QChar(
'8'), QChar(
'9'), QChar(
'@'),
943 QChar(
'A'), QChar(
'B'), QChar(
'C'), QChar(
'D'),
944 QChar(
'E'), QChar(
'F'), QChar(
'G'), QChar(
'H'),
945 QChar(
'I'), QChar(
'J'), QChar(
'K'), QChar(
'L'),
946 QChar(
'M'), QChar(
'N'), QChar(
'O'), QChar(
'P'),
947 QChar(
'Q'), QChar(
'R'), QChar(
'S'), QChar(
'T'),
948 QChar(
'U'), QChar(
'V'), QChar(
'W'), QChar(
'X'),
949 QChar(
'Y'), QChar(
'Z')
968 if (searchChar.isEmpty())
972 if (searchChar.contains(
'@'))
974 where =
"SELECT DISTINCT title FROM program "
975 "LEFT JOIN channel ON program.chanid = channel.chanid "
976 "WHERE channel.deleted IS NULL AND "
977 " channel.visible > 0 AND "
979 "title NOT REGEXP '^[A-Z0-9]' AND "
980 "title NOT REGEXP '^The [A-Z0-9]' AND "
981 "title NOT REGEXP '^A [A-Z0-9]' AND "
982 "title NOT REGEXP '^[0-9]' AND "
983 "starttime > :STARTTIME ) ";
986 where +=
"AND title LIKE :SEARCH ";
990 where +=
"ORDER BY title;";
992 bindings[
":STARTTIME"] =
993 progStart.addSecs(50 - progStart.time().second());
997 QString one = searchChar +
'%';
998 QString two = QString(
"The ") + one;
999 QString three = QString(
"A ") + one;
1000 QString four = QString(
"An ") + one;
1001 QString five = QString(
"\"") + one;
1003 where =
"SELECT DISTINCT title FROM program "
1004 "LEFT JOIN channel ON program.chanid = channel.chanid "
1005 "WHERE channel.deleted IS NULL "
1006 "AND channel.visible > 0 "
1007 "AND ( title LIKE :ONE OR title LIKE :TWO "
1008 " OR title LIKE :THREE "
1009 " OR title LIKE :FOUR "
1010 " OR title LIKE :FIVE )"
1011 "AND starttime > :STARTTIME ";
1013 where +=
"AND title LIKE :SEARCH ";
1015 where +=
"ORDER BY title;";
1017 bindings[
":ONE"] = one;
1018 bindings[
":TWO"] = two;
1019 bindings[
":THREE"] = three;
1020 bindings[
":FOUR"] = four;
1021 bindings[
":FIVE"] = five;
1022 bindings[
":STARTTIME"] =
1023 progStart.addSecs(50 - progStart.time().second());
1036 [[maybe_unused]]
int charNum)
1070 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
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