MythTV master
proglist_helpers.cpp
Go to the documentation of this file.
1// MythTV
12
13// MythFrontend
14#include "proglist.h"
15#include "proglist_helpers.h"
16#include "scheduleeditor.h"
17
19{
20 if (!LoadWindowFromXML("schedule-ui.xml", "phrasepopup", this))
21 return false;
22
23 bool err = false;
24 UIUtilE::Assign(this, m_titleText, "title_text", &err);
25 UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
26 UIUtilE::Assign(this, m_phraseEdit, "phrase_edit", &err);
27 UIUtilE::Assign(this, m_okButton, "ok_button", &err);
28 UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
29 UIUtilE::Assign(this, m_recordButton, "record_button", &err);
30
31 if (err)
32 {
33 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'phrasepopup'");
34 return false;
35 }
36
38 {
39 m_titleText->SetText(tr("Select Search"));
40 new MythUIButtonListItem(m_phraseList, tr("<New Search>"), nullptr, false);
41 m_okButton->SetText(tr("Edit"));
42 }
43 else
44 {
45 m_titleText->SetText(tr("Phrase"));
46 new MythUIButtonListItem(m_phraseList, tr("<New Phrase>"), nullptr, false);
47 }
48
49 for (const QString& item : std::as_const(m_list))
50 {
51 new MythUIButtonListItem(m_phraseList, item, nullptr, false);
52 }
53
58
59
61
62 m_deleteButton->SetText(tr("Delete"));
63 m_recordButton->SetText(tr("Record"));
64
68
70
72
74
75 return true;
76}
77
79{
80 m_okButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
82 (m_list.indexOf(m_phraseEdit->GetText().trimmed()) != -1));
83 m_recordButton->SetEnabled(!m_phraseEdit->GetText().trimmed().isEmpty());
84}
85
87{
88 if (!item)
89 return;
90
91 int pos = m_phraseList->GetCurrentPos();
92
93 if (pos == 0)
95 else
96 okClicked();
97}
98
100{
101 if (!item)
102 return;
103
104 if (m_phraseList->GetCurrentPos() == 0)
106 else
107 m_phraseEdit->SetText(item->GetText());
108
112}
113
115{
116 if (m_phraseEdit->GetText().trimmed().isEmpty())
117 return;
118
119 // check to see if we need to save the phrase
122
123// emit haveResult(m_phraseList->GetCurrentPos());
125
126 Close();
127}
128
130{
131 int view = m_phraseList->GetCurrentPos() - 1;
132
133 if (view < 0)
134 return;
135
136 QString text = m_list[view];
137 const QString& qphrase = text;
138
140 query.prepare("DELETE FROM keyword "
141 "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
142 query.bindValue(":PHRASE", qphrase);
143 query.bindValue(":TYPE", m_searchType);
144 if (!query.exec())
145 MythDB::DBError("PhrasePopup::deleteClicked", query);
146
148
149 m_parent->m_viewList.removeAll(text);
150 m_parent->m_viewTextList.removeAll(text);
151
152 if (view < m_parent->m_curView)
154 else if (view == m_parent->m_curView)
155 m_parent->m_curView = -1;
156
157 if (m_parent->m_viewList.count() < 1)
159 else
161}
162
164{
165 QString text = m_phraseEdit->GetText();
166 QString what = text;
167 QString fromgenre;
168
169 if (text.trimmed().isEmpty())
170 return;
171
172 if (m_searchType == kNoSearch)
173 {
174 LOG(VB_GENERAL, LOG_ERR, "Unknown search in ProgLister");
175 return;
176 }
177
179 {
180 if (text == ":::::")
181 return;
182
183 MSqlBindings bindings;
184 if (ProgLister::PowerStringToSQL(text, what, bindings))
185 {
186 fromgenre = QString("LEFT JOIN programgenres ON "
187 "program.chanid = programgenres.chanid AND "
188 "program.starttime = programgenres.starttime ");
189 }
190
191 if (what.isEmpty())
192 return;
193
194 MSqlEscapeAsAQuery(what, bindings);
195 }
196
197 auto *record = new RecordingRule();
198
199 record->LoadBySearch(m_searchType, text, what, fromgenre);
200
202 auto *schededit = new ScheduleEditor(mainStack, record);
203 if (schededit->Create())
204 {
205 mainStack->AddScreen(schededit);
206 okClicked();
207 }
208 else
209 {
210 delete schededit;
211 }
212}
213
215
217{
218 if (!LoadWindowFromXML("schedule-ui.xml", "powersearchpopup", this))
219 return false;
220
221 bool err = false;
222 UIUtilE::Assign(this, m_titleText, "title_text", &err);
223 UIUtilE::Assign(this, m_phraseList, "phrase_list", &err);
224 UIUtilE::Assign(this, m_editButton, "edit_button", &err);
225 UIUtilE::Assign(this, m_deleteButton, "delete_button", &err);
226 UIUtilE::Assign(this, m_recordButton, "record_button", &err);
227
228 if (err)
229 {
230 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'powersearchpopup'");
231 return false;
232 }
233
234 m_titleText->SetText(tr("Select Search"));
235 new MythUIButtonListItem(m_phraseList, tr("<New Search>"), nullptr, false);
236
237 for (const QString &item : std::as_const(m_list))
238 {
239 new MythUIButtonListItem(m_phraseList, item, nullptr, false);
240 }
241
246
247
249
250 m_editButton->SetText(tr("Edit"));
251 m_deleteButton->SetText(tr("Delete"));
252 m_recordButton->SetText(tr("Record"));
253
257
259
261
262 return true;
263}
264
266{
267 if (!item)
268 return;
269
270 int pos = m_phraseList->GetCurrentPos();
271
272 if (pos == 0)
273 editClicked();
274 else
275 {
277 Close();
278 }
279}
280
282{
283 if (!item)
284 return;
285
289}
290
292{
293 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
294
295 QString currentItem = ":::::";
296
297 if (m_phraseList->GetCurrentPos() != 0)
298 currentItem = m_phraseList->GetValue();
299
300 auto *popup = new EditPowerSearchPopup(popupStack, m_parent, currentItem);
301
302 if (!popup->Create())
303 {
304 delete popup;
305 return;
306 }
307
308 popupStack->AddScreen(popup);
309
310 Close();
311}
312
314{
315 int view = m_phraseList->GetCurrentPos() - 1;
316
317 if (view < 0)
318 return;
319
320 QString text = m_list[view];
321 const QString& qphrase = text;
322
324 query.prepare("DELETE FROM keyword "
325 "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
326 query.bindValue(":PHRASE", qphrase);
327 query.bindValue(":TYPE", m_searchType);
328 if (!query.exec())
329 MythDB::DBError("PowerSearchPopup::deleteClicked", query);
330
332
333 m_parent->m_viewList.removeAll(text);
334 m_parent->m_viewTextList.removeAll(text);
335
336 if (view < m_parent->m_curView)
338 else if (view == m_parent->m_curView)
339 m_parent->m_curView = -1;
340
341 if (m_parent->m_viewList.count() < 1)
343 else
345}
346
348{
349 QString text = m_phraseList->GetValue();
350 QString what = text;
351 QString fromgenre;
352
353 if (text.trimmed().isEmpty())
354 return;
355
356 if (m_searchType == kNoSearch)
357 {
358 LOG(VB_GENERAL, LOG_ERR, "Unknown search in ProgLister");
359 return;
360 }
361
363 {
364 if (text == ":::::")
365 return;
366
367 MSqlBindings bindings;
368 if (ProgLister::PowerStringToSQL(text, what, bindings))
369 {
370 fromgenre = QString(
371 "LEFT JOIN programgenres ON "
372 "program.chanid = programgenres.chanid AND "
373 "program.starttime = programgenres.starttime ");
374 }
375
376 if (what.isEmpty())
377 return;
378
379 MSqlEscapeAsAQuery(what, bindings);
380 }
381
382 auto *record = new RecordingRule();
383
384 record->LoadBySearch(m_searchType, text, what, fromgenre);
385
387 auto *schededit = new ScheduleEditor(mainStack, record);
388 if (schededit->Create())
389 {
390 mainStack->AddScreen(schededit);
392 Close();
393 }
394 else
395 {
396 delete schededit;
397 }
398}
399
401
403 ProgLister *parent,
404 QString &currentValue)
405 : MythScreenType(parentStack, "phrasepopup"),
406 m_parent(parent),
407 m_currentValue(std::move(currentValue))
408{
409 //sanity check currentvalue
410 QStringList field = m_currentValue.split(':');
411 if (field.count() != 6)
412 {
413 LOG(VB_GENERAL, LOG_ERR, QString("Error. PowerSearch %1 has %2 fields")
414 .arg(m_currentValue).arg(field.count()));
415 m_currentValue = ":::::";
416 }
417}
418
420{
421 if (!LoadWindowFromXML("schedule-ui.xml", "editpowersearchpopup", this))
422 return false;
423
424 bool err = false;
425 UIUtilE::Assign(this, m_titleEdit, "title_edit", &err);
426 UIUtilE::Assign(this, m_subtitleEdit, "subtitle_edit", &err);
427 UIUtilE::Assign(this, m_descEdit, "desc_edit", &err);
428 UIUtilE::Assign(this, m_categoryList, "category_list", &err);
429 UIUtilE::Assign(this, m_genreList, "genre_list", &err);
430 UIUtilE::Assign(this, m_channelList, "channel_list", &err);
431 UIUtilE::Assign(this, m_okButton, "ok_button", &err);
432
433 if (err)
434 {
435 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'editpowersearchpopup'");
436 return false;
437 }
438
439 QStringList field = m_currentValue.split(':');
440
441 m_titleEdit->SetText(field[0]);
442 m_subtitleEdit->SetText(field[1]);
443 m_descEdit->SetText(field[2]);
444
445 initLists();
446
448
450
452
453 return true;
454}
455
457{
458 QString text;
459 text = m_titleEdit->GetText().replace(':','%').replace('*','%') + ':';
460 text += m_subtitleEdit->GetText().replace(':','%').replace('*','%') + ':';
461 text += m_descEdit->GetText().replace(':','%').replace('*','%') + ':';
462
463 if (m_categoryList->GetCurrentPos() > 0)
465 text += ':';
466 if (m_genreList->GetCurrentPos() > 0)
468 text += ':';
469 if (m_channelList->GetCurrentPos() > 0)
471
472 if (text == ":::::")
473 return;
474
476 m_parent->FillViewList(text);
478
479 Close();
480}
481
483{
484 QStringList field = m_currentValue.split(':');
485
486 // category type
487 m_categories.clear();
489 m_categoryList, tr("(Any Program Type)"), nullptr, false);
490 m_categories << "";
491 new MythUIButtonListItem(m_categoryList, tr("Movies"), nullptr, false);
492 m_categories << "movie";
493 new MythUIButtonListItem(m_categoryList, tr("Series"), nullptr, false);
494 m_categories << "series";
495 new MythUIButtonListItem(m_categoryList, tr("Show"), nullptr, false);
496 m_categories << "libmythtv/tvshow";
497 new MythUIButtonListItem(m_categoryList, tr("Sports"), nullptr, false);
498 m_categories << "sports";
499 m_categoryList->SetItemCurrent(m_categories.indexOf(field[3]));
500
501 // genre
502 m_genres.clear();
503 new MythUIButtonListItem(m_genreList, tr("(Any Genre)"), nullptr, false);
504 m_genres << "";
505
507
508 query.prepare("SELECT genre FROM programgenres GROUP BY genre;");
509
510 if (query.exec())
511 {
512 while (query.next())
513 {
514 QString category = query.value(0).toString();
515 if (category.isEmpty() || category.trimmed().isEmpty())
516 continue;
517 category = query.value(0).toString();
518 new MythUIButtonListItem(m_genreList, category, nullptr, false);
519 m_genres << category;
520 if (category == field[4])
522 }
523 }
524
525 // channel
526 QString channelOrdering = gCoreContext->GetSetting(
527 "ChannelOrdering", "channum");
528
529 m_channels.clear();
530 new MythUIButtonListItem(m_channelList, tr("(Any Channel)"), nullptr, false);
531 m_channels << "";
532
533 ChannelInfoList channels = ChannelUtil::GetChannels(0, true, "callsign");
534 ChannelUtil::SortChannels(channels, channelOrdering, true);
535
536 for (auto & channel : channels)
537 {
538 QString chantext = channel.GetFormatted(ChannelInfo::kChannelShort);
539
540 m_parent->m_viewList << QString::number(channel.m_chanId);
541 m_parent->m_viewTextList << chantext;
542
543 auto *item = new MythUIButtonListItem(m_channelList, chantext,
544 nullptr, false);
545
546 InfoMap chanmap;
547 channel.ToMap(chanmap);
548 item->SetTextFromMap(chanmap);
549
550 m_channels << channel.m_callSign;
551 if (channel.m_callSign == field[5])
553 }
554}
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:131
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:251
MythUIButtonList * m_genreList
MythUITextEdit * m_subtitleEdit
EditPowerSearchPopup(MythScreenStack *parentStack, ProgLister *parent, QString &currentValue)
MythUITextEdit * m_descEdit
MythUIButton * m_okButton
MythUIButtonList * m_categoryList
MythUIButtonList * m_channelList
MythUITextEdit * m_titleEdit
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
QVariant value(int i) const
Definition: mythdbcon.h:204
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
MythScreenStack * GetMainStack()
MythScreenStack * GetStack(const QString &Stackname)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
bool SetFocusWidget(MythUIType *widget=nullptr)
virtual void Close()
QString GetText(const QString &name="") const
virtual QString GetValue() const
MythUIButtonListItem * GetItemCurrent() const
void SetItemCurrent(MythUIButtonListItem *item)
void RemoveItem(MythUIButtonListItem *item)
int GetCurrentPos() const
void itemClicked(MythUIButtonListItem *item)
bool MoveToNamedPosition(const QString &position_name)
void itemSelected(MythUIButtonListItem *item)
void SetText(const QString &msg)
void Clicked()
QString GetText(void) const
void SetText(const QString &text, bool moveCursor=true)
void valueChanged()
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)
Definition: mythuitext.cpp:115
void SetEnabled(bool enable)
void haveResult(QString item)
void okClicked(void)
void editChanged(void)
RecSearchType m_searchType
MythUIText * m_titleText
void phraseClicked(MythUIButtonListItem *item)
MythUITextEdit * m_phraseEdit
void recordClicked(void)
void phraseSelected(MythUIButtonListItem *item)
bool Create() override
ProgLister * m_parent
MythUIButton * m_okButton
void deleteClicked(void)
MythUIButton * m_deleteButton
MythUIButtonList * m_phraseList
QString m_currentValue
MythUIButton * m_recordButton
QStringList m_list
MythUIButtonList * m_phraseList
bool Create() override
void phraseClicked(MythUIButtonListItem *item)
void haveResult(QString item)
MythUIButton * m_deleteButton
MythUIButton * m_recordButton
MythUIButton * m_editButton
ProgLister * m_parent
RecSearchType m_searchType
QStringList m_list
void phraseSelected(MythUIButtonListItem *item)
MythUIText * m_titleText
MythUITextEdit * m_phraseEdit
QStringList m_viewTextList
Definition: proglist.h:121
void SetViewFromList(const QString &item)
Definition: proglist.cpp:606
void FillViewList(const QString &view)
Definition: proglist.cpp:811
static bool PowerStringToSQL(const QString &qphrase, QString &output, MSqlBindings &bindings)
Definition: proglist.cpp:613
int m_curView
Definition: proglist.h:119
QStringList m_viewList
Definition: proglist.h:120
void UpdateKeywordInDB(const QString &text, const QString &oldValue)
Definition: proglist.cpp:445
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:30
Construct a recording schedule.
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void MSqlEscapeAsAQuery(QString &query, const MSqlBindings &bindings)
Given a partial query string and a bindings object, escape the string.
Definition: mythdbcon.cpp:1004
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:100
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
STL namespace.
@ kPowerSearch
@ kNoSearch
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27