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 {
274 editClicked();
275 }
276 else
277 {
279 Close();
280 }
281}
282
284{
285 if (!item)
286 return;
287
291}
292
294{
295 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
296
297 QString currentItem = ":::::";
298
299 if (m_phraseList->GetCurrentPos() != 0)
300 currentItem = m_phraseList->GetValue();
301
302 auto *popup = new EditPowerSearchPopup(popupStack, m_parent, currentItem);
303
304 if (!popup->Create())
305 {
306 delete popup;
307 return;
308 }
309
310 popupStack->AddScreen(popup);
311
312 Close();
313}
314
316{
317 int view = m_phraseList->GetCurrentPos() - 1;
318
319 if (view < 0)
320 return;
321
322 QString text = m_list[view];
323 const QString& qphrase = text;
324
326 query.prepare("DELETE FROM keyword "
327 "WHERE phrase = :PHRASE AND searchtype = :TYPE;");
328 query.bindValue(":PHRASE", qphrase);
329 query.bindValue(":TYPE", m_searchType);
330 if (!query.exec())
331 MythDB::DBError("PowerSearchPopup::deleteClicked", query);
332
334
335 m_parent->m_viewList.removeAll(text);
336 m_parent->m_viewTextList.removeAll(text);
337
338 if (view < m_parent->m_curView)
340 else if (view == m_parent->m_curView)
341 m_parent->m_curView = -1;
342
343 if (m_parent->m_viewList.count() < 1)
345 else
347}
348
350{
351 QString text = m_phraseList->GetValue();
352 QString what = text;
353 QString fromgenre;
354
355 if (text.trimmed().isEmpty())
356 return;
357
358 if (m_searchType == kNoSearch)
359 {
360 LOG(VB_GENERAL, LOG_ERR, "Unknown search in ProgLister");
361 return;
362 }
363
365 {
366 if (text == ":::::")
367 return;
368
369 MSqlBindings bindings;
370 if (ProgLister::PowerStringToSQL(text, what, bindings))
371 {
372 fromgenre = QString(
373 "LEFT JOIN programgenres ON "
374 "program.chanid = programgenres.chanid AND "
375 "program.starttime = programgenres.starttime ");
376 }
377
378 if (what.isEmpty())
379 return;
380
381 MSqlEscapeAsAQuery(what, bindings);
382 }
383
384 auto *record = new RecordingRule();
385
386 record->LoadBySearch(m_searchType, text, what, fromgenre);
387
389 auto *schededit = new ScheduleEditor(mainStack, record);
390 if (schededit->Create())
391 {
392 mainStack->AddScreen(schededit);
394 Close();
395 }
396 else
397 {
398 delete schededit;
399 }
400}
401
403
405 ProgLister *parent,
406 QString &currentValue)
407 : MythScreenType(parentStack, "phrasepopup"),
408 m_parent(parent),
409 m_currentValue(std::move(currentValue))
410{
411 //sanity check currentvalue
412 QStringList field = m_currentValue.split(':');
413 if (field.count() != 6)
414 {
415 LOG(VB_GENERAL, LOG_ERR, QString("Error. PowerSearch %1 has %2 fields")
416 .arg(m_currentValue).arg(field.count()));
417 m_currentValue = ":::::";
418 }
419}
420
422{
423 if (!LoadWindowFromXML("schedule-ui.xml", "editpowersearchpopup", this))
424 return false;
425
426 bool err = false;
427 UIUtilE::Assign(this, m_titleEdit, "title_edit", &err);
428 UIUtilE::Assign(this, m_subtitleEdit, "subtitle_edit", &err);
429 UIUtilE::Assign(this, m_descEdit, "desc_edit", &err);
430 UIUtilE::Assign(this, m_categoryList, "category_list", &err);
431 UIUtilE::Assign(this, m_genreList, "genre_list", &err);
432 UIUtilE::Assign(this, m_channelList, "channel_list", &err);
433 UIUtilE::Assign(this, m_okButton, "ok_button", &err);
434
435 if (err)
436 {
437 LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'editpowersearchpopup'");
438 return false;
439 }
440
441 QStringList field = m_currentValue.split(':');
442
443 m_titleEdit->SetText(field[0]);
444 m_subtitleEdit->SetText(field[1]);
445 m_descEdit->SetText(field[2]);
446
447 initLists();
448
450
452
454
455 return true;
456}
457
459{
460 QString text;
461 text = m_titleEdit->GetText().replace(':','%').replace('*','%') + ':';
462 text += m_subtitleEdit->GetText().replace(':','%').replace('*','%') + ':';
463 text += m_descEdit->GetText().replace(':','%').replace('*','%') + ':';
464
465 if (m_categoryList->GetCurrentPos() > 0)
467 text += ':';
468 if (m_genreList->GetCurrentPos() > 0)
470 text += ':';
471 if (m_channelList->GetCurrentPos() > 0)
473
474 if (text == ":::::")
475 return;
476
478 m_parent->FillViewList(text);
480
481 Close();
482}
483
485{
486 QStringList field = m_currentValue.split(':');
487
488 // category type
489 m_categories.clear();
491 m_categoryList, tr("(Any Program Type)"), nullptr, false);
492 m_categories << "";
493 new MythUIButtonListItem(m_categoryList, tr("Movies"), nullptr, false);
494 m_categories << "movie";
495 new MythUIButtonListItem(m_categoryList, tr("Series"), nullptr, false);
496 m_categories << "series";
497 new MythUIButtonListItem(m_categoryList, tr("Show"), nullptr, false);
498 m_categories << "libmythtv/tvshow";
499 new MythUIButtonListItem(m_categoryList, tr("Sports"), nullptr, false);
500 m_categories << "sports";
501 m_categoryList->SetItemCurrent(m_categories.indexOf(field[3]));
502
503 // genre
504 m_genres.clear();
505 new MythUIButtonListItem(m_genreList, tr("(Any Genre)"), nullptr, false);
506 m_genres << "";
507
509
510 query.prepare("SELECT genre FROM programgenres GROUP BY genre;");
511
512 if (query.exec())
513 {
514 while (query.next())
515 {
516 QString category = query.value(0).toString();
517 if (category.isEmpty() || category.trimmed().isEmpty())
518 continue;
519 category = query.value(0).toString();
520 new MythUIButtonListItem(m_genreList, category, nullptr, false);
521 m_genres << category;
522 if (category == field[4])
524 }
525 }
526
527 // channel
528 QString channelOrdering = gCoreContext->GetSetting(
529 "ChannelOrdering", "channum");
530
531 m_channels.clear();
532 new MythUIButtonListItem(m_channelList, tr("(Any Channel)"), nullptr, false);
533 m_channels << "";
534
535 ChannelInfoList channels = ChannelUtil::GetChannels(0, true, "callsign");
536 ChannelUtil::SortChannels(channels, channelOrdering, true);
537
538 for (auto & channel : channels)
539 {
540 QString chantext = channel.GetFormatted(ChannelInfo::kChannelShort);
541
542 m_parent->m_viewList << QString::number(channel.m_chanId);
543 m_parent->m_viewTextList << chantext;
544
545 auto *item = new MythUIButtonListItem(m_channelList, chantext,
546 nullptr, false);
547
548 InfoMap chanmap;
549 channel.ToMap(chanmap);
550 item->SetTextFromMap(chanmap);
551
552 m_channels << channel.m_callSign;
553 if (channel.m_callSign == field[5])
555 }
556}
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:130
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:252
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:838
QVariant value(int i) const
Definition: mythdbcon.h:204
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
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:122
void SetViewFromList(const QString &item)
Definition: proglist.cpp:608
void FillViewList(const QString &view)
Definition: proglist.cpp:813
static bool PowerStringToSQL(const QString &qphrase, QString &output, MSqlBindings &bindings)
Definition: proglist.cpp:615
int m_curView
Definition: proglist.h:120
QStringList m_viewList
Definition: proglist.h:121
void UpdateKeywordInDB(const QString &text, const QString &oldValue)
Definition: proglist.cpp:447
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:1005
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
@ kPowerSearch
@ kNoSearch
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27