MythTV master
channelrecpriority.cpp
Go to the documentation of this file.
1// C++
2#include <algorithm> // For std::sort()
3#include <vector> // For std::vector
4
5// MythTV
11#include "libmythtv/tv.h"
18
19// MythFrontend
20#include "channelrecpriority.h"
21#include "proglist.h"
22
24{
26 int m_cnt;
27};
28
30{
31 public:
33 {
34 if (a.m_chan->m_chanNum.toInt() == b.m_chan->m_chanNum.toInt())
35 return(a.m_chan->m_sourceId > b.m_chan->m_sourceId);
36 return(a.m_chan->m_chanNum.toInt() > b.m_chan->m_chanNum.toInt());
37 }
38};
39
41{
42 public:
44 {
46 return (a.m_chan->m_chanNum.toInt() > b.m_chan->m_chanNum.toInt());
48 }
49};
50
52 : MythScreenType(parent, "ChannelRecPriority")
53{
54 m_sortType = (SortType)gCoreContext->GetNumSetting("ChannelRecPrioritySorting",
55 (int)byChannel);
56
58}
59
61{
63 gCoreContext->SaveSetting("ChannelRecPrioritySorting",
64 (int)m_sortType);
66}
67
69{
70 if (!LoadWindowFromXML("schedule-ui.xml", "channelrecpriority", this))
71 return false;
72
73 m_channelList = dynamic_cast<MythUIButtonList *> (GetChild("channels"));
74
75 m_chanstringText = dynamic_cast<MythUIText *> (GetChild("chanstring")); // Deprecated, use mapped text
76 m_priorityText = dynamic_cast<MythUIText *> (GetChild("priority"));
77
78 m_iconImage = dynamic_cast<MythUIImage *> (GetChild("icon"));
79
80 if (!m_channelList)
81 {
82 LOG(VB_GENERAL, LOG_ERR, "Theme is missing critical theme elements.");
83 return false;
84 }
85
88
89 FillList();
90
92
93 return true;
94}
95
97{
98 if (GetFocusWidget()->keyPressEvent(event))
99 return true;
100
101 QStringList actions;
102 bool handled = GetMythMainWindow()->TranslateKeyPress("TV Frontend", event, actions);
103
104 for (int i = 0; i < actions.size() && !handled; i++)
105 {
106 const QString& action = actions[i];
107 handled = true;
108
109 if (action == "UPCOMING")
110 upcoming();
111 else if (action == "RANKINC")
113 else if (action == "RANKDEC")
115 else if (action == "1")
116 {
117 if (m_sortType != byChannel)
118 {
120 SortList();
121 }
122 }
123 else if (action == "2")
124 {
126 {
128 SortList();
129 }
130 }
131 else if (action == "PREVVIEW" || action == "NEXTVIEW")
132 {
133 if (m_sortType == byChannel)
135 else
137 SortList();
138 }
139 else
140 {
141 handled = false;
142 }
143 }
144
145 if (!handled && MythScreenType::keyPressEvent(event))
146 handled = true;
147
148 return handled;
149}
150
152{
154
155 if (!item)
156 return;
157
158 QString label = tr("Channel Options");
159
160 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
161
162 auto *menuPopup = new MythDialogBox(label, popupStack, "chanrecmenupopup");
163
164 if (!menuPopup->Create())
165 {
166 delete menuPopup;
167 menuPopup = nullptr;
168 return;
169 }
170
171 menuPopup->SetReturnEvent(this, "options");
172
173 menuPopup->AddButton(tr("Program List"));
174 //menuPopup->AddButton(tr("Reset All Priorities"));
175
176 popupStack->AddScreen(menuPopup);
177}
178
180{
182
183 if (!item)
184 return;
185
186 auto *chanInfo = item->GetData().value<ChannelInfo *>();
187 if (chanInfo == nullptr)
188 return;
189
190 // inc/dec recording priority
191 int tempRecPriority = chanInfo->m_recPriority + howMuch;
192 if (tempRecPriority > -100 && tempRecPriority < 100)
193 {
194 chanInfo->m_recPriority = tempRecPriority;
195
196 // order may change if sorting by recoring priority, so resort
198 SortList();
199 else
200 {
201 item->SetText(QString::number(chanInfo->m_recPriority), "priority");
202 updateInfo(item);
203 }
204 }
205}
206
208 const QString &newrecpriority)
209{
211 query.prepare("UPDATE channel SET recpriority = :RECPRI "
212 "WHERE chanid = :CHANID ;");
213 query.bindValue(":RECPRI", newrecpriority);
214 query.bindValue(":CHANID", chanid);
215
216 if (!query.exec() || !query.isActive())
217 MythDB::DBError("Save recpriority update", query);
218}
219
221{
222 QMap<QString, ChannelInfo>::Iterator it;
223
224 for (it = m_channelData.begin(); it != m_channelData.end(); ++it)
225 {
226 ChannelInfo *chanInfo = &(*it);
227 QString key = QString::number(chanInfo->m_chanId);
228
229 // if this channel's recording priority changed from when we entered
230 // save new value out to db
231 if (QString::number(chanInfo->m_recPriority) != m_origRecPriorityData[key])
232 applyChannelRecPriorityChange(QString::number(chanInfo->m_chanId),
233 QString::number(chanInfo->m_recPriority));
234 }
235 ScheduledRecording::ReschedulePlace("SaveChannelPriority");
236}
237
239{
240 QMap<int, QString> srcMap;
241
242 m_channelData.clear();
243 m_sortedChannel.clear();
244
246 result.prepare("SELECT sourceid, name FROM videosource;");
247
248 if (result.exec())
249 {
250 while (result.next())
251 {
252 srcMap[result.value(0).toInt()] = result.value(1).toString();
253 }
254 }
255 result.prepare("SELECT chanid, channum, sourceid, callsign, "
256 "icon, recpriority, name FROM channel "
257 "WHERE deleted IS NULL AND visible > 0");
258
259 if (result.exec())
260 {
261 int cnt = 999;
262 while (result.next())
263 {
264 auto *chaninfo = new ChannelInfo;
265 chaninfo->m_chanId = result.value(0).toInt();
266 chaninfo->m_chanNum = result.value(1).toString();
267 chaninfo->m_sourceId = result.value(2).toInt();
268 chaninfo->m_callSign = result.value(3).toString();
269 QString iconurl = result.value(4).toString();
270 if (!iconurl.isEmpty())
271 iconurl = gCoreContext->GetMasterHostPrefix( "ChannelIcons", iconurl);
272 chaninfo->m_icon = iconurl;
273 chaninfo->m_recPriority = result.value(5).toInt();
274 chaninfo->m_name = result.value(6).toString();
275
276 chaninfo->SetSourceName(srcMap[chaninfo->m_sourceId]);
277
278 m_channelData[QString::number(cnt)] = *chaninfo;
279
280 // save recording priority value in map so we don't have to save
281 // all channel's recording priority values when we exit
282 m_origRecPriorityData[QString::number(chaninfo->m_chanId)] =
283 QString::number(chaninfo->m_recPriority);
284
285 cnt--;
286 }
287 }
288 else if (!result.isActive())
289 {
290 MythDB::DBError("Get channel recording priorities query", result);
291 }
292
293 SortList();
294}
295
297{
299
300 QMap<QString, ChannelInfo*>::Iterator it;
301 for (it = m_sortedChannel.begin(); it != m_sortedChannel.end(); ++it)
302 {
303 ChannelInfo *chanInfo = *it;
304
305 auto *item = new MythUIButtonListItem(m_channelList, "",
306 QVariant::fromValue(chanInfo));
307
308 QString fontState = "default";
309
310 item->SetText(chanInfo->GetFormatted(ChannelInfo::kChannelLong),
311 fontState);
312
313 InfoMap infomap;
314 chanInfo->ToMap(infomap);
315 item->SetTextFromMap(infomap, fontState);
316
317 item->DisplayState("normal", "status");
318
319 if (!chanInfo->m_icon.isEmpty())
320 {
321 QString iconUrl = gCoreContext->GetMasterHostPrefix("ChannelIcons",
322 chanInfo->m_icon);
323 item->SetImage(iconUrl, "icon");
324 item->SetImage(iconUrl);
325 }
326
327 item->SetText(QString::number(chanInfo->m_recPriority), "priority", fontState);
328
329 if (m_currentItem == chanInfo)
331 }
332
333 // this textarea name is depreciated use 'nochannels_warning' instead
334 MythUIText *noChannelsText = dynamic_cast<MythUIText*>(GetChild("norecordings_info"));
335
336 if (!noChannelsText)
337 noChannelsText = dynamic_cast<MythUIText*>(GetChild("nochannels_warning"));
338
339 if (noChannelsText)
340 noChannelsText->SetVisible(m_channelData.isEmpty());
341}
342
343
345{
347
348 if (item)
349 {
350 auto *channelItem = item->GetData().value<ChannelInfo *>();
351 m_currentItem = channelItem;
352 }
353
354 int i = 0;
355 int j = 0;
356 std::vector<RecPriorityInfo> sortingList;
357 QMap<QString, ChannelInfo>::iterator pit;
358 std::vector<RecPriorityInfo>::iterator sit;
359
360 // copy m_channelData into sortingList
361 for (i = 0, pit = m_channelData.begin(); pit != m_channelData.end();
362 ++pit, ++i)
363 {
364 ChannelInfo *chanInfo = &(*pit);
365 RecPriorityInfo tmp = {chanInfo, i};
366 sortingList.push_back(tmp);
367 }
368
369 switch(m_sortType)
370 {
371 case byRecPriority:
372 std::sort(sortingList.begin(), sortingList.end(),
374 break;
375 case byChannel:
376 default:
377 std::sort(sortingList.begin(), sortingList.end(),
378 channelSort());
379 break;
380 }
381
382 m_sortedChannel.clear();
383
384 // rebuild m_channelData in sortingList order from m_sortedChannel
385 for (i = 0, sit = sortingList.begin(); sit != sortingList.end(); i++, ++sit)
386 {
387 RecPriorityInfo *recPriorityInfo = &(*sit);
388
389 // find recPriorityInfo[i] in m_sortedChannel
390 for (j = 0, pit = m_channelData.begin(); j !=recPriorityInfo->m_cnt; j++, ++pit);
391
392 m_sortedChannel[QString::number(999-i)] = &(*pit);
393 }
394
395 updateList();
396}
397
399{
400 if (!item)
401 return;
402
403 auto *channelItem = item->GetData().value<ChannelInfo *>();
404 if (!m_channelData.isEmpty() && channelItem)
405 {
406 if (m_iconImage)
407 {
408 QString iconUrl = gCoreContext->GetMasterHostPrefix("ChannelIcons", channelItem->m_icon);
409 m_iconImage->SetFilename(iconUrl);
410 m_iconImage->Load();
411 }
412
413 InfoMap chanmap;
414 channelItem->ToMap(chanmap);
415 SetTextFromMap(chanmap);
416
418 m_chanstringText->SetText(channelItem->GetFormatted(ChannelInfo::kChannelLong));
419 }
420
421 MythUIText *norecordingText = dynamic_cast<MythUIText*>
422 (GetChild("norecordings_info"));
423
424 if (norecordingText)
425 norecordingText->SetVisible(m_channelData.isEmpty());
426}
427
429{
431
432 if (!item)
433 return;
434
435 auto *chanInfo = item->GetData().value<ChannelInfo *>();
436
437 if (!chanInfo || chanInfo->m_chanId < 1)
438 return;
439
440 QString chanID = QString("%1").arg(chanInfo->m_chanId);
442 auto *pl = new ProgLister(mainStack, plChannel, chanID, "");
443 if (pl->Create())
444 mainStack->AddScreen(pl);
445 else
446 delete pl;
447}
448
449
451{
452 if (event->type() == DialogCompletionEvent::kEventType)
453 {
454 auto *dce = (DialogCompletionEvent*)(event);
455
456 QString resultid = dce->GetId();
457 int buttonnum = dce->GetResult();
458
459 if (resultid == "options")
460 {
461 switch (buttonnum)
462 {
463 case 0:
464 upcoming();
465 break;
466 }
467 }
468 }
469}
QString m_chanNum
Definition: channelinfo.h:86
uint m_chanId
Definition: channelinfo.h:85
QString m_icon
Definition: channelinfo.h:93
void ToMap(InfoMap &infoMap)
int m_recPriority
Definition: channelinfo.h:98
uint m_sourceId
Definition: channelinfo.h:89
QString GetFormatted(ChannelFormat format) const
void customEvent(QEvent *event) override
MythUIButtonList * m_channelList
bool Create(void) override
QMap< QString, ChannelInfo > m_channelData
ChannelRecPriority(MythScreenStack *parent)
ChannelInfo * m_currentItem
void ShowMenu(void) override
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
MythUIText * m_chanstringText
MythUIImage * m_iconImage
void changeRecPriority(int howMuch)
static void applyChannelRecPriorityChange(const QString &chanid, const QString &newrecpriority)
QMap< QString, ChannelInfo * > m_sortedChannel
QMap< QString, QString > m_origRecPriorityData
MythUIText * m_priorityText
void updateInfo(MythUIButtonListItem *item)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
static const Type kEventType
Definition: mythdialogbox.h:56
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 isActive(void) const
Definition: mythdbcon.h:215
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
void SaveSetting(const QString &key, int newValue)
QString GetMasterHostPrefix(const QString &storageGroup=QString(), const QString &path=QString())
int GetNumSetting(const QString &key, int defaultval=0)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
Basic menu dialog, message and a list of options.
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 AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void SetText(const QString &text, const QString &name="", const QString &state="")
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
MythUIButtonListItem * GetItemCurrent() const
void SetItemCurrent(MythUIButtonListItem *item)
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
void itemSelected(MythUIButtonListItem *item)
virtual void SetTextFromMap(const InfoMap &infoMap)
Image widget, displays a single image or multiple images in sequence.
Definition: mythuiimage.h:98
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
All purpose text widget, displays a text string.
Definition: mythuitext.h:29
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
virtual void SetVisible(bool visible)
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
static void ReschedulePlace(const QString &why)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
bool operator()(const RecPriorityInfo a, const RecPriorityInfo b)
static guint32 * tmp
Definition: goom_core.cpp:26
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
@ plChannel
Definition: proglist.h:28
ChannelInfo * m_chan