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