Go to the documentation of this file.
38 m_seSuffix = QString(
" (%1)").arg(tr(
"stored search"));
39 m_exSuffix = QString(
" (%1)").arg(tr(
"stored example"));
71 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'customedit'");
112 quoteTitle.replace(
"\'",
"\'\'");
113 rule.
description = QString(
"program.title = '%1' ").arg(quoteTitle);
117 QVariant::fromValue(rule));
120 result.
prepare(
"SELECT recordid, title, subtitle, description "
121 "FROM record WHERE search = :SEARCH ORDER BY title;");
127 while (result.
next())
129 QString trimTitle = result.
value(1).toString();
130 trimTitle.remove(QRegExp(
" \\(.*\\)$"));
133 rule.
title = trimTitle;
140 QVariant::fromValue(rule));
159 int s0 = clause.indexOf (QRegExp(
"\\{[A-Z]+\\}"), e0);
164 e0 = clause.indexOf (
"}", s0);
166 QString mid = clause.mid(s0 + 1, e0 - s0 - 1);
169 if (mid.compare(
"TITLE") == 0) {
171 repl.replace(
"\'",
"\'\'");
172 }
else if (mid.compare(
"SUBTITLE") == 0) {
174 repl.replace(
"\'",
"\'\'");
175 }
else if (mid.compare(
"DESCR") == 0) {
177 repl.replace(
"\'",
"\'\'");
178 }
else if (mid.compare(
"SERIESID") == 0) {
180 }
else if (mid.compare(
"PROGID") == 0) {
182 }
else if (mid.compare(
"SEASON") == 0) {
184 }
else if (mid.compare(
"EPISODE") == 0) {
186 }
else if (mid.compare(
"CATEGORY") == 0) {
188 }
else if (mid.compare(
"CHANID") == 0) {
190 }
else if (mid.compare(
"CHANNUM") == 0) {
192 }
else if (mid.compare(
"SCHEDID") == 0) {
194 }
else if (mid.compare(
"CHANNAME") == 0) {
196 }
else if (mid.compare(
"DAYNAME") == 0) {
198 }
else if (mid.compare(
"STARTDATE") == 0) {
200 }
else if (mid.compare(
"ENDDATE") == 0) {
202 }
else if (mid.compare(
"STARTTIME") == 0) {
204 }
else if (mid.compare(
"ENDTIME") == 0) {
206 }
else if (mid.compare(
"STARTSEC") == 0) {
208 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
209 QDateTime midnight = QDateTime(date.date());
211 QDateTime midnight = date.date().startOfDay();
213 repl = QString(
"%1").arg(midnight.secsTo(date));
214 }
else if (mid.compare(
"ENDSEC") == 0) {
216 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
217 QDateTime midnight = QDateTime(date.date());
219 QDateTime midnight = date.date().startOfDay();
221 repl = QString(
"%1").arg(midnight.secsTo(date));
224 clause.replace(s0, e0 - s0 + 1, repl);
233 rule.
title = tr(
"Match an exact title");
235 rule.
description = QString(
"program.title = '{TITLE}' ");
239 QVariant::fromValue(rule));
243 rule.
title = tr(
"Match this series");
245 rule.
description = QString(
"program.seriesid = '{SERIESID}' ");
247 QVariant::fromValue(rule));
250 rule.
title = tr(
"Match words in the title");
253 rule.
description = QString(
"program.title LIKE '%{TITLE}%' ");
257 QVariant::fromValue(rule));
259 rule.
title = tr(
"Match words in the subtitle");
262 rule.
description = QString(
"program.subtitle LIKE '%{SUBTITLE}%' ");
264 rule.
description =
"program.subtitle LIKE '%Las Vegas%' ";
266 QVariant::fromValue(rule));
270 rule.
title = tr(
"Match this episode");
272 rule.
description = QString(
"program.programid = '{PROGID}' ");
276 rule.
title = tr(
"Match this episode");
278 rule.
description = QString(
"program.subtitle = '{SUBTITLE}' \n"
279 "AND program.description = '{DESCR}' ");
283 rule.
title = tr(
"Match an exact episode");
285 rule.
description = QString(
"program.title = 'Seinfeld' \n"
286 "AND program.subtitle = 'The Soup' ");
289 QVariant::fromValue(rule));
291 rule.
title = tr(
"Match in any descriptive field");
293 rule.
description = QString(
"(program.title LIKE '%Japan%' \n"
294 " OR program.subtitle LIKE '%Japan%' \n"
295 " OR program.description LIKE '%Japan%') ");
297 QVariant::fromValue(rule));
299 rule.
title = tr(
"New episodes only");
303 QVariant::fromValue(rule));
305 rule.
title = tr(
"Exclude unidentified episodes");
309 QVariant::fromValue(rule));
311 rule.
title = tr(
"First showing of each episode");
315 QVariant::fromValue(rule));
317 rule.
title = tr(
"Last showing of each episode");
321 QVariant::fromValue(rule));
323 rule.
title = tr(
"Anytime on a specific day of the week");
326 "DAYNAME(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) = '{DAYNAME}' ";
328 QVariant::fromValue(rule));
330 rule.
title = tr(
"Only on weekdays (Monday through Friday)");
333 "WEEKDAY(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) < 5 ";
335 QVariant::fromValue(rule));
337 rule.
title = tr(
"Only on weekends");
340 "WEEKDAY(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) >= 5 ";
342 QVariant::fromValue(rule));
344 rule.
title = tr(
"Only in prime time");
347 "HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) >= 19 "
348 "AND HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) < 23 ";
350 QVariant::fromValue(rule));
352 rule.
title = tr(
"Not in prime time");
355 "(HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) < 19 "
356 " OR HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) >= 23) ";
358 QVariant::fromValue(rule));
360 rule.
title = tr(
"Only on a specific station");
363 rule.
description = QString(
"channel.callsign = '{SCHEDID}' ");
367 QVariant::fromValue(rule));
369 rule.
title = tr(
"Exclude one station");
373 QVariant::fromValue(rule));
375 rule.
title = tr(
"Match related callsigns");
377 rule.
description =
"channel.callsign LIKE 'HBO%' ";
379 QVariant::fromValue(rule));
381 rule.
title = tr(
"Only channels from the Favorites group");
382 rule.
subtitle =
", channelgroup cg, channelgroupnames cgn";
384 "AND cg.grpid = cgn.grpid \n"
385 "AND program.chanid = cg.chanid ";
387 QVariant::fromValue(rule));
389 rule.
title = tr(
"Only channels from a specific video source");
393 QVariant::fromValue(rule));
395 rule.
title = tr(
"Only channels marked as commercial free");
397 rule.
description = QString(
"channel.commmethod = %1 ")
400 QVariant::fromValue(rule));
402 rule.
title = tr(
"Only shows marked as HDTV");
406 QVariant::fromValue(rule));
408 rule.
title = tr(
"Only shows marked as widescreen");
410 rule.
description =
"FIND_IN_SET('WIDESCREEN', program.videoprop) > 0 ";
412 QVariant::fromValue(rule));
414 rule.
title = tr(
"Exclude H.264 encoded streams (EIT only)");
416 rule.
description =
"FIND_IN_SET('AVC', program.videoprop) = 0 ";
418 QVariant::fromValue(rule));
420 rule.
title = tr(
"Only shows with in-vision signing");
422 rule.
description =
"FIND_IN_SET('SIGNED', program.subtitletypes) > 0 ";
424 QVariant::fromValue(rule));
426 rule.
title = tr(
"Only shows with in-vision subtitles");
428 rule.
description =
"FIND_IN_SET('ONSCREEN', program.subtitletypes) > 0 ";
430 QVariant::fromValue(rule));
432 rule.
title = tr(
"Limit by category");
435 rule.
description = QString(
"program.category = '{CATEGORY}' ");
437 rule.
description =
"program.category = 'Reality' ";
439 QVariant::fromValue(rule));
441 rule.
title = tr(
"All matches for a genre (Schedules Direct)");
442 rule.
subtitle =
"LEFT JOIN programgenres ON "
443 "program.chanid = programgenres.chanid AND "
444 "program.starttime = programgenres.starttime ";
446 rule.
description = QString(
"programgenres.genre = '{CATEGORY}' ");
448 rule.
description =
"programgenres.genre = 'Reality' ";
450 QVariant::fromValue(rule));
452 rule.
title = tr(
"Limit by MPAA or VCHIP rating (Schedules Direct)");
453 rule.
subtitle =
"LEFT JOIN programrating ON "
454 "program.chanid = programrating.chanid AND "
455 "program.starttime = programrating.starttime ";
456 rule.
description =
"(programrating.rating = 'G' OR programrating.rating "
459 QVariant::fromValue(rule));
461 rule.
title = tr(
"Category type (%1)",
"List of hardcoded category types")
462 .arg(
"'movie', 'series', 'sports', 'tvshow'");
464 rule.
description =
"program.category_type = 'sports' ";
466 QVariant::fromValue(rule));
468 rule.
title = tr(
"Limit movies by the year of release");
470 rule.
description =
"program.category_type = 'movie' AND "
471 "program.airdate >= 2000 ";
473 QVariant::fromValue(rule));
475 rule.
title = tr(
"Minimum star rating (0.0 to 1.0 for movies only)");
479 QVariant::fromValue(rule));
481 rule.
title = tr(
"Person named in the credits (Schedules Direct)");
482 rule.
subtitle =
", people, credits";
484 "AND credits.person = people.person \n"
485 "AND program.chanid = credits.chanid \n"
486 "AND program.starttime = credits.starttime ";
488 QVariant::fromValue(rule));
502 rule.
title = tr(
"Re-record SDTV in HDTV (disable duplicate matching)");
503 rule.
subtitle =
", recordedprogram rp1 LEFT OUTER JOIN recordedprogram rp2"
504 " ON rp1.programid = rp2.programid AND rp2.hdtv = 1";
505 rule.
description =
"program.programid = rp1.programid \n"
506 "AND rp1.hdtv = 0 \n"
507 "AND program.hdtv = 1 \n"
508 "AND rp2.starttime IS NULL ";
510 QVariant::fromValue(rule));
512 rule.
title = tr(
"Multiple sports teams (complete example)");
514 rule.
description =
"program.title = 'NBA Basketball' \n"
515 "AND program.subtitle REGEXP '(Miami|Cavaliers|Lakers)' \n"
516 "AND program.first > 0 \n";
518 QVariant::fromValue(rule));
520 rule.
title = tr(
"Sci-fi B-movies (complete example)");
522 rule.
description =
"program.category_type='movie' \n"
523 "AND program.category='Science fiction' \n"
524 "AND program.stars <= 0.5 AND program.airdate < 1970 ";
526 QVariant::fromValue(rule));
529 tr(
"SportsCenter Overnight (complete example - use FindDaily)");
532 "program.title = 'SportsCenter' \n"
533 "AND HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) >= 2 \n"
534 "AND HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) <= 6 ";
536 QVariant::fromValue(rule));
538 rule.
title = tr(
"Movie of the Week (complete example - use FindWeekly)");
541 "program.category_type='movie' \n"
542 "AND program.stars >= 1.0 AND program.airdate >= 1965 \n"
543 "AND DAYNAME(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) = 'Friday' \n"
544 "AND HOUR(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) >= 12 ";
546 QVariant::fromValue(rule));
548 rule.
title = tr(
"First Episodes (complete example for Schedules Direct)");
551 "AND program.programid LIKE 'EP%0001' \n"
552 "AND program.originalairdate = "
553 "DATE(CONVERT_TZ(program.starttime, 'Etc/UTC', 'SYSTEM')) ";
555 QVariant::fromValue(rule));
560 result.
prepare(
"SELECT rulename,fromclause,whereclause,search "
561 "FROM customexample;");
565 while (result.
next())
567 QString str = result.
value(0).toString();
569 if (result.
value(3).toInt() > 0)
578 QVariant::fromValue(rule));
607 (hastitle && hasdesc));
618 msg.replace(
'\n',
' ');
619 msg.replace(QRegExp(
" [ ]*"),
" ");
620 msg = QString(
"\"%1\"").arg(msg);
627 (hastitle && hasdesc));
640 if (desc.contains(QRegExp(
"\\S")))
692 int cur_recid = rule.
recordid.toInt();
709 if (schededit->Create())
726 bool exampleExists =
false;
729 query.
prepare(
"SELECT rulename,whereclause FROM customexample "
730 "WHERE rulename = :RULE;");
734 exampleExists =
true;
736 QString msg = QString(
"%1: %2\n\n").arg(tr(
"Current Example"))
745 auto *storediag =
new MythDialogBox(msg, mainStack,
"storePopup",
true);
747 storediag->SetReturnEvent(
this,
"storeruledialog");
748 if (storediag->Create())
755 str = tr(
"Replace as a search");
757 str = tr(
"Store as a search");
758 storediag->AddButton(str);
761 str = tr(
"Replace as an example");
763 str = tr(
"Store as an example");
764 storediag->AddButton(str);
770 QString str = QString(
"%1 \"%2\"").arg(tr(
"Delete"))
772 storediag->AddButton(str);
788 if (desc.contains(QRegExp(
"^\\s*AND\\s", Qt::CaseInsensitive)))
790 msg = tr(
"Power Search rules no longer require a leading \"AND\".");
792 else if (desc.contains(
';'))
794 msg = tr(
"Power Search rules cannot include semicolon ( ; ) ");
795 msg += tr(
"statement terminators.");
800 query.
prepare(QString(
"SELECT NULL FROM (program,channel) "
801 "%1 WHERE\n%2").
arg(from).
arg(desc));
809 msg = tr(
"An error was found when checking") +
":\n\n";
811 msg +=
"\n\n" + tr(
"The database error was") +
":\n";
819 GetStack(
"popup stack");
820 auto *checkSyntaxPopup =
823 if (checkSyntaxPopup->Create())
825 checkSyntaxPopup->SetReturnEvent(
this,
"checkSyntaxPopup");
830 delete checkSyntaxPopup;
847 "(rulename,fromclause,whereclause,search) "
848 "VALUES(:RULE,:FROMC,:WHEREC,:SEARCH);");
864 QVariant::fromValue(rule));
878 item->
SetData(QVariant::fromValue(rule));
896 "WHERE rulename = :RULE;");
914 QString resultid = dce->GetId();
915 QString resulttext = dce->GetResultText();
917 if (resultid ==
"storeruledialog")
919 if (resulttext.startsWith(tr(
"Delete")))
923 else if (!resulttext.isEmpty())
925 storeRule(resulttext.contains(tr(
"as a search")),
926 !resulttext.startsWith(tr(
"Replace")));
940 for (
int i = 0; i < actions.size() && !handled; i++)
942 QString
action = actions[i];
952 else if (
action ==
"EDIT")
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 SetMaxLength(int length)
MythUIButtonList * m_ruleList
void storeRule(bool is_search, bool is_new)
void ruleChanged(MythUIButtonListItem *item)
const MythUIButtonListItem * m_currentRuleItem
void clauseChanged(MythUIButtonListItem *item)
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
QVariant value(int i) const
arg(title).arg(filename).arg(doDelete))
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
QString GetCategory(void) const
Internal representation of a recording rule, mirrors the record table.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
~CustomEdit(void) override
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Screen in which all other widgets are contained and rendered.
MythUITextEdit * m_descriptionEdit
void ruleSaved(int ruleId)
QString GetText(void) const
void customEvent(QEvent *event) override
MythUIText * m_clauseText
MythUIType * GetFocusWidget(void) const
MythUITextEdit * m_titleEdit
void addListener(QObject *listener)
Add a listener to the observable.
CustomEdit(MythScreenStack *parent, ProgramInfo *m_pginfo=nullptr)
void SetText(const QString &text, bool moveCursor=true)
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
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
QString GetDescription(void) const
static void DBError(const QString &where, const MSqlQuery &query)
void BuildFocusList(void)
MythUIButton * m_testButton
void SetEnabled(bool enable)
MythUIButton * m_cancelButton
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
QString GetSeriesID(void) const
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
QSqlError lastError(void) const
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
uint GetEpisode(void) const
Holds information on recordings and videos.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Dialog asking for user confirmation. Ok and optional Cancel button.
uint GetSeason(void) const
QString executedQuery(void) const
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythUIButton * m_storeButton
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
void clauseClicked(MythUIButtonListItem *item)
virtual void SetText(const QString &text)
MythMainWindow * GetMythMainWindow(void)
void recordClicked(void)
The user clicked on the 'Record' button in the 'Custom Edit' window.
QString GetProgramID(void) const
uint GetRecordingRuleID(void) const
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
MSqlQuery query(MSqlQuery::InitCon())
Construct a recording schedule.
QString evaluate(QString clause)
void removeListener(QObject *listener)
Remove a listener to the observable.
MythUIButtonList * m_clauseList
MythUITextEdit * m_subtitleEdit
MythUIButton * m_recordButton
void scheduleCreated(int ruleID)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QString GetSubtitle(void) const