MythTV  master
guide.cpp
Go to the documentation of this file.
1 // Program Name: guide.cpp
3 // Created : Mar. 7, 2011
4 //
5 // Copyright (c) 2011 David Blain <dblain@mythtv.org>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //
25 
26 // C++
27 #include <cmath>
28 
29 // MythTV
30 #include "libmythbase/compat.h"
35 #include "libmythtv/channelgroup.h"
36 #include "libmythtv/channelutil.h"
37 
38 // MythBackend
39 #include "autoexpire.h"
40 #include "scheduler.h"
41 #include "guide.h"
42 
43 // Qt6 has made the QFileInfo::QFileInfo(QString) constructor
44 // explicit, which means that it is no longer possible to use an
45 // initializer list to construct a QFileInfo. Disable that clang-tidy
46 // check for this file so it can still be run on the rest of the file
47 // in the project.
48 //
49 // NOLINTBEGIN(modernize-return-braced-init-list)
50 
52 //
54 
55 DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &rawStartTime,
56  const QDateTime &rawEndTime,
57  bool bDetails,
58  int nChannelGroupId,
59  int nStartIndex,
60  int nCount,
61  bool bWithInvisible)
62 {
63  if (!rawStartTime.isValid())
64  throw QString( "StartTime is invalid" );
65 
66  if (!rawEndTime.isValid())
67  throw QString( "EndTime is invalid" );
68 
69  QDateTime dtStartTime = rawStartTime.toUTC();
70  QDateTime dtEndTime = rawEndTime.toUTC();
71 
72  if (dtEndTime < dtStartTime)
73  throw QString( "EndTime is before StartTime");
74 
75  if (nStartIndex <= 0)
76  nStartIndex = 0;
77 
78  if (nCount <= 0)
79  nCount = 20000;
80 
81  // ----------------------------------------------------------------------
82  // Load the channel list
83  // ----------------------------------------------------------------------
84 
85  uint nTotalAvailable = 0;
86  ChannelInfoList chanList = ChannelUtil::LoadChannels(nStartIndex, nCount,
87  nTotalAvailable,
88  !bWithInvisible,
91  0,
92  nChannelGroupId);
93 
94  // ----------------------------------------------------------------------
95  // Build SQL statement for Program Listing
96  // ----------------------------------------------------------------------
97 
98  ProgramList schedList;
99  MSqlBindings bindings;
100 
101  QString sWhere = "program.chanid = :CHANID "
102  "AND program.endtime >= :STARTDATE "
103  "AND program.starttime < :ENDDATE "
104  "AND program.starttime >= :STARTDATELIMIT "
105  "AND program.manualid = 0"; // Omit 'manual' recordings scheds
106 
107 #if 0
108  QString sGroupBy = "program.starttime, channel.channum,"
109  "channel.callsign, program.title";
110 #endif
111 
112  QString sOrderBy = "program.starttime";
113 
114  bindings[":STARTDATE" ] = dtStartTime;
115  bindings[":STARTDATELIMIT"] = dtStartTime.addDays(-1);
116  bindings[":ENDDATE" ] = dtEndTime;
117 
118  // ----------------------------------------------------------------------
119  // Get all Pending Scheduled Programs
120  // ----------------------------------------------------------------------
121 
122  // NOTE: Fetching this information directly from the schedule is
123  // significantly faster than using ProgramInfo::LoadFromScheduler()
124  auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
125  if (scheduler)
126  scheduler->GetAllPending(schedList);
127 
128  // ----------------------------------------------------------------------
129  // Build Response
130  // ----------------------------------------------------------------------
131 
132  auto *pGuide = new DTC::ProgramGuide();
133 
134  ChannelInfoList::iterator chan_it;
135  for (chan_it = chanList.begin(); chan_it != chanList.end(); ++chan_it)
136  {
137  // Create ChannelInfo Object
138  DTC::ChannelInfo *pChannel = pGuide->AddNewChannel();
139  FillChannelInfo( pChannel, (*chan_it), bDetails );
140 
141  // Load the list of programmes for this channel
142  ProgramList progList;
143  bindings[":CHANID"] = (*chan_it).m_chanId;
144  LoadFromProgram( progList, sWhere, sOrderBy, sOrderBy, bindings,
145  schedList );
146 
147  // Create Program objects and add them to the channel object
148  ProgramList::iterator progIt;
149  for( progIt = progList.begin(); progIt != progList.end(); ++progIt)
150  {
151  DTC::Program *pProgram = pChannel->AddNewProgram();
152  FillProgramInfo( pProgram, *progIt, false, bDetails, false ); // No cast info
153  }
154  }
155 
156  // ----------------------------------------------------------------------
157 
158  pGuide->setStartTime ( dtStartTime );
159  pGuide->setEndTime ( dtEndTime );
160  pGuide->setDetails ( bDetails );
161 
162  pGuide->setStartIndex ( nStartIndex );
163  pGuide->setCount ( chanList.size() );
164  pGuide->setTotalAvailable( nTotalAvailable );
165  pGuide->setAsOf ( MythDate::current() );
166 
167  pGuide->setVersion ( MYTH_BINARY_VERSION );
168  pGuide->setProtoVer ( MYTH_PROTO_VERSION );
169 
170  return pGuide;
171 }
172 
174 //
176 
178  int nCount,
179  const QDateTime& rawStartTime,
180  const QDateTime& rawEndTime,
181  int nChanId,
182  const QString& sTitleFilter,
183  const QString& sCategoryFilter,
184  const QString& sPersonFilter,
185  const QString& sKeywordFilter,
186  bool bOnlyNew,
187  bool bDetails,
188  const QString &sSort,
189  bool bDescending,
190  bool bWithInvisible)
191 {
192  if (!rawStartTime.isNull() && !rawStartTime.isValid())
193  throw QString( "StartTime is invalid" );
194 
195  if (!rawEndTime.isNull() && !rawEndTime.isValid())
196  throw QString( "EndTime is invalid" );
197 
198  QDateTime dtStartTime = rawStartTime;
199  const QDateTime& dtEndTime = rawEndTime;
200 
201  if (!rawEndTime.isNull() && dtEndTime < dtStartTime)
202  throw QString( "EndTime is before StartTime");
203 
204  MSqlQuery query(MSqlQuery::InitCon());
205 
206 
207  // ----------------------------------------------------------------------
208  // Build SQL statement for Program Listing
209  // ----------------------------------------------------------------------
210 
211  ProgramList progList;
212  ProgramList schedList;
213  MSqlBindings bindings;
214 
215  QString sSQL;
216 
217  if (!sPersonFilter.isEmpty())
218  {
219  sSQL = ", people, credits " // LEFT JOIN
220  "WHERE people.name LIKE :PersonFilter "
221  "AND credits.person = people.person "
222  "AND program.chanid = credits.chanid "
223  "AND program.starttime = credits.starttime AND ";
224  bindings[":PersonFilter"] = QString("%%1%").arg(sPersonFilter);
225  }
226  else
227  sSQL = "WHERE ";
228 
229  if (bOnlyNew)
230  {
231  sSQL = "LEFT JOIN oldprogram ON oldprogram.oldtitle = program.title "
232  + sSQL
233  + "oldprogram.oldtitle IS NULL AND ";
234  }
235 
236  sSQL += "deleted IS NULL AND ";
237 
238  if (!bWithInvisible)
239  sSQL += "visible > 0 AND ";
240 
241  sSQL += "program.manualid = 0 "; // Exclude programmes created purely for 'manual' recording schedules
242 
243  if (nChanId < 0)
244  nChanId = 0;
245 
246  if (nChanId > 0)
247  {
248  sSQL += "AND program.chanid = :ChanId ";
249  bindings[":ChanId"] = nChanId;
250  }
251 
252  if (dtStartTime.isNull())
253  dtStartTime = QDateTime::currentDateTimeUtc();
254 
255  sSQL += " AND program.endtime >= :StartDate ";
256  bindings[":StartDate"] = dtStartTime;
257 
258  if (!dtEndTime.isNull())
259  {
260  sSQL += "AND program.starttime <= :EndDate ";
261  bindings[":EndDate"] = dtEndTime;
262  }
263 
264  if (!sTitleFilter.isEmpty())
265  {
266  sSQL += "AND program.title LIKE :Title ";
267  bindings[":Title"] = QString("%%1%").arg(sTitleFilter);
268  }
269 
270  if (!sCategoryFilter.isEmpty())
271  {
272  sSQL += "AND program.category LIKE :Category ";
273  bindings[":Category"] = sCategoryFilter;
274  }
275 
276  if (!sKeywordFilter.isEmpty())
277  {
278  sSQL += "AND (program.title LIKE :Keyword1 "
279  "OR program.subtitle LIKE :Keyword2 "
280  "OR program.description LIKE :Keyword3) ";
281 
282  QString filter = QString("%%1%").arg(sKeywordFilter);
283  bindings[":Keyword1"] = filter;
284  bindings[":Keyword2"] = filter;
285  bindings[":Keyword3"] = filter;
286  }
287 
288  if (sSort == "starttime")
289  sSQL += "ORDER BY program.starttime "; // NOLINT(bugprone-branch-clone)
290  else if (sSort == "title")
291  sSQL += "ORDER BY program.title ";
292  else if (sSort == "channel")
293  sSQL += "ORDER BY channel.channum ";
294  else if (sSort == "duration")
295  sSQL += "ORDER BY (program.endtime - program.starttime) ";
296  else
297  sSQL += "ORDER BY program.starttime ";
298 
299  if (bDescending)
300  sSQL += "DESC ";
301  else
302  sSQL += "ASC ";
303 
304  // ----------------------------------------------------------------------
305  // Get all Pending Scheduled Programs
306  // ----------------------------------------------------------------------
307 
308  // NOTE: Fetching this information directly from the schedule is
309  // significantly faster than using ProgramInfo::LoadFromScheduler()
310  auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
311  if (scheduler)
312  scheduler->GetAllPending(schedList);
313 
314  // ----------------------------------------------------------------------
315 
316  uint nTotalAvailable = 0;
317  LoadFromProgram( progList, sSQL, bindings, schedList,
318  (uint)nStartIndex, (uint)nCount, nTotalAvailable);
319 
320  // ----------------------------------------------------------------------
321  // Build Response
322  // ----------------------------------------------------------------------
323 
324  auto *pPrograms = new DTC::ProgramList();
325 
326  nCount = (int)progList.size();
327  int nEndIndex = (int)progList.size();
328 
329  for( int n = 0; n < nEndIndex; n++)
330  {
331  ProgramInfo *pInfo = progList[ n ];
332 
333  DTC::Program *pProgram = pPrograms->AddNewProgram();
334 
335  FillProgramInfo( pProgram, pInfo, true, bDetails, false ); // No cast info, loading this takes far too long
336  }
337 
338  // ----------------------------------------------------------------------
339 
340  pPrograms->setStartIndex ( nStartIndex );
341  pPrograms->setCount ( nCount );
342  pPrograms->setTotalAvailable( nTotalAvailable );
343  pPrograms->setAsOf ( MythDate::current() );
344  pPrograms->setVersion ( MYTH_BINARY_VERSION );
345  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
346 
347  return pPrograms;
348 }
349 
351 //
353 
355  const QDateTime &rawStartTime )
356 
357 {
358  if (!(nChanId > 0))
359  throw QString( "Channel ID is invalid" );
360  if (!rawStartTime.isValid())
361  throw QString( "StartTime is invalid" );
362 
363  QDateTime dtStartTime = rawStartTime.toUTC();
364 
365  // ----------------------------------------------------------------------
366  // -=>TODO: Add support for getting Recorded Program Info
367  // ----------------------------------------------------------------------
368 
369  // Build Response
370 
371  auto *pProgram = new DTC::Program();
372  ProgramInfo *pInfo = LoadProgramFromProgram(nChanId, dtStartTime);
373 
374  FillProgramInfo( pProgram, pInfo, true, true, true );
375 
376  delete pInfo;
377 
378  return pProgram;
379 }
380 
382 //
384 
385 QFileInfo Guide::GetChannelIcon( int nChanId,
386  int nWidth /* = 0 */,
387  int nHeight /* = 0 */ )
388 {
389  // Get Icon file path
390 
391  QString sFileName = ChannelUtil::GetIcon( nChanId );
392 
393  if (sFileName.isEmpty())
394  {
395  LOG(VB_UPNP, LOG_ERR,
396  QString("GetImageFile - ChanId %1 doesn't exist or isn't visible")
397  .arg(nChanId));
398  return {};
399  }
400 
401  // ------------------------------------------------------------------
402  // Search for the filename
403  // ------------------------------------------------------------------
404 
405  StorageGroup storage( "ChannelIcons" );
406  const QString sFullFileName = storage.FindFile( sFileName );
407 
408  if (sFullFileName.isEmpty())
409  {
410  LOG(VB_UPNP, LOG_ERR,
411  QString("GetImageFile - Unable to find %1.").arg(sFileName));
412 
413  return {};
414  }
415 
416  // ----------------------------------------------------------------------
417  // check to see if the file (still) exists
418  // ----------------------------------------------------------------------
419 
420  if ((nWidth == 0) && (nHeight == 0))
421  {
422  if (QFile::exists( sFullFileName ))
423  {
424  return QFileInfo( sFullFileName );
425  }
426 
427  LOG(VB_UPNP, LOG_ERR,
428  QString("GetImageFile - File Does not exist %1.").arg(sFullFileName));
429 
430  return {};
431  }
432  // -------------------------------------------------------------------
433 
434  QString sNewFileName = QString( "%1.%2x%3.png" )
435  .arg( sFullFileName )
436  .arg( nWidth )
437  .arg( nHeight );
438 
439  // ----------------------------------------------------------------------
440  // check to see if image is already created.
441  // ----------------------------------------------------------------------
442 
443  if (QFile::exists( sNewFileName ))
444  return QFileInfo( sNewFileName );
445 
446  // ----------------------------------------------------------------------
447  // We need to create it...
448  // ----------------------------------------------------------------------
449 
450  QString sChannelsDirectory = QFileInfo( sNewFileName ).absolutePath();
451 
452  if (!QFileInfo( sChannelsDirectory ).isWritable())
453  {
454  LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - no write access to: %1")
455  .arg( sChannelsDirectory ));
456  return {};
457  }
458 
459  auto *pImage = new QImage( sFullFileName );
460 
461  if (!pImage)
462  {
463  LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - can't create image: %1")
464  .arg( sFullFileName ));
465  return {};
466  }
467 
468  float fAspect = (float)(pImage->width()) / pImage->height();
469  if (fAspect == 0)
470  {
471  LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - zero aspect"));
472  delete pImage;
473  return {};
474  }
475 
476  if ( nWidth == 0 )
477  nWidth = (int)std::rint(nHeight * fAspect);
478 
479  if ( nHeight == 0 )
480  nHeight = (int)std::rint(nWidth / fAspect);
481 
482  QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio,
483  Qt::SmoothTransformation);
484 
485  if (img.isNull())
486  {
487  LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - unable to scale. "
488  "See if %1 is really an image.").arg( sFullFileName ));
489  delete pImage;
490  return {};
491  }
492 
493  if (!img.save( sNewFileName, "PNG" ))
494  {
495  LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - failed, %1")
496  .arg( sNewFileName ));
497  delete pImage;
498  return {};
499  }
500 
501  delete pImage;
502 
503  return QFileInfo( sNewFileName );
504 }
505 
507 //
509 
511 {
512  ChannelGroupList list = ChannelGroup::GetChannelGroups(bIncludeEmpty);
513  auto *pGroupList = new DTC::ChannelGroupList();
514 
515  ChannelGroupList::iterator it;
516  for (it = list.begin(); it < list.end(); ++it)
517  {
518  DTC::ChannelGroup *pGroup = pGroupList->AddNewChannelGroup();
519  FillChannelGroup(pGroup, (*it));
520  }
521 
522  return pGroupList;
523 }
524 
526 //
528 
529 QStringList Guide::GetCategoryList( ) //int nStartIndex, int nCount)
530 {
531  QStringList catList;
532  MSqlQuery query(MSqlQuery::InitCon());
533 
534  query.prepare("SELECT DISTINCT category FROM program WHERE category != '' "
535  "ORDER BY category");
536 
537  if (!query.exec())
538  return catList;
539 
540  while (query.next())
541  {
542  catList << query.value(0).toString();
543  }
544 
545  return catList;
546 }
547 
549 //
551 
552 QStringList Guide::GetStoredSearches( const QString& sType )
553 {
554  QStringList keywordList;
555  MSqlQuery query(MSqlQuery::InitCon());
556 
557  RecSearchType iType = searchTypeFromString(sType);
558 
559  if (iType == kNoSearch)
560  {
561  //throw QString( "Invalid Type" );
562  return keywordList;
563  }
564 
565  query.prepare("SELECT DISTINCT phrase FROM keyword "
566  "WHERE searchtype = :TYPE "
567  "ORDER BY phrase");
568  query.bindValue(":TYPE", static_cast<int>(iType));
569 
570  if (!query.exec())
571  return keywordList;
572 
573  while (query.next())
574  {
575  keywordList << query.value(0).toString();
576  }
577 
578  return keywordList;
579 }
580 
582 //
584 
585 bool Guide::AddToChannelGroup ( int nChannelGroupId,
586  int nChanId )
587 {
588  bool bResult = false;
589 
590  if (!(nChanId > 0))
591  throw QString( "Channel ID is invalid" );
592 
593  bResult = ChannelGroup::AddChannel(nChanId, nChannelGroupId);
594 
595  return bResult;
596 }
597 
599 //
601 
602 bool Guide::RemoveFromChannelGroup ( int nChannelGroupId,
603  int nChanId )
604 {
605  bool bResult = false;
606 
607  if (!(nChanId > 0))
608  throw QString( "Channel ID is invalid" );
609 
610  bResult = ChannelGroup::DeleteChannel(nChanId, nChannelGroupId);
611 
612  return bResult;
613 }
614 
615 // NOLINTEND(modernize-return-braced-init-list)
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:101
DTC::ChannelInfo::AddNewProgram
Program * AddNewProgram()
Definition: programAndChannel.h:316
Scheduler
Definition: scheduler.h:45
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:807
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
FillProgramInfo
void FillProgramInfo(DTC::Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast)
Definition: serviceUtil.cpp:47
MythCoreContext::GetScheduler
MythScheduler * GetScheduler(void)
Definition: mythcorecontext.cpp:1894
LoadProgramFromProgram
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
Definition: programinfo.cpp:5794
DTC::Program
Definition: programAndChannel.h:145
ChannelUtil::LoadChannels
static ChannelInfoList LoadChannels(uint startIndex, uint count, uint &totalAvailable, bool ignoreHidden=true, OrderBy orderBy=kChanOrderByChanNum, GroupBy groupBy=kChanGroupByChanid, uint sourceID=0, uint channelGroupID=0, bool liveTVOnly=false, const QString &callsign="", const QString &channum="", bool ignoreUntunable=true)
Load channels from database into a list of ChannelInfo objects.
Definition: channelutil.cpp:2410
Guide::GetChannelIcon
QFileInfo GetChannelIcon(int ChanId, int Width, int Height) override
Definition: guide.cpp:385
searchTypeFromString
RecSearchType searchTypeFromString(const QString &type)
Definition: recordingtypes.cpp:329
Guide::GetChannelGroupList
DTC::ChannelGroupList * GetChannelGroupList(bool IncludeEmpty) override
Definition: guide.cpp:510
Guide::RemoveFromChannelGroup
bool RemoveFromChannelGroup(int ChannelGroupId, int ChanId) override
Definition: guide.cpp:602
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:602
FillChannelGroup
void FillChannelGroup(DTC::ChannelGroup *pGroup, const ChannelGroupItem &pGroupItem)
Definition: serviceUtil.cpp:263
ChannelGroup::AddChannel
static bool AddChannel(uint chanid, int changrpid)
Definition: channelgroup.cpp:71
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
FillChannelInfo
bool FillChannelInfo(DTC::ChannelInfo *pChannel, uint nChanID, bool bDetails)
Definition: serviceUtil.cpp:175
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:608
DTC::ChannelGroupList
Definition: channelGroupList.h:16
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
guide.h
ChannelGroup::GetChannelGroups
static ChannelGroupList GetChannelGroups(bool includeEmpty=true)
Definition: channelgroup.cpp:328
scheduler.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
Guide::AddToChannelGroup
bool AddToChannelGroup(int ChannelGroupId, int ChanId) override
Definition: guide.cpp:585
mythversion.h
Guide::GetCategoryList
QStringList GetCategoryList() override
Definition: guide.cpp:529
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
MYTH_PROTO_VERSION
static constexpr const char * MYTH_PROTO_VERSION
Increment this whenever the MythTV network protocol changes.
Definition: mythversion.h:47
autoexpire.h
mythlogging.h
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:540
compat.h
Guide::GetProgramList
DTC::ProgramList * GetProgramList(int StartIndex, int Count, const QDateTime &StartTime, const QDateTime &EndTime, int ChanId, const QString &TitleFilter, const QString &CategoryFilter, const QString &PersonFilter, const QString &KeywordFilter, bool OnlyNew, bool Details, const QString &Sort, bool Descending, bool WithInvisible) override
Definition: guide.cpp:177
RecSearchType
RecSearchType
Definition: recordingtypes.h:78
storagegroup.h
kNoSearch
@ kNoSearch
Definition: recordingtypes.h:80
ChannelGroupList
std::vector< ChannelGroupItem > ChannelGroupList
Definition: channelgroup.h:31
MYTH_BINARY_VERSION
static constexpr const char * MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
uint
unsigned int uint
Definition: compat.h:79
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
AutoDeleteDeque::end
iterator end(void)
Definition: autodeletedeque.h:51
channelutil.h
AutoDeleteDeque< ProgramInfo * >
DTC::ChannelGroup
Definition: channelGroup.h:23
ProgramList
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:31
ChannelUtil::GetIcon
static QString GetIcon(uint chanid)
Definition: channelutil.cpp:1245
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
channelgroup.h
mythcorecontext.h
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:883
LoadFromProgram
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
Definition: programinfo.cpp:5642
ChannelUtil::kChanGroupByCallsignAndChannum
@ kChanGroupByCallsignAndChannum
Definition: channelutil.h:208
StorageGroup
Definition: storagegroup.h:11
Scheduler::GetAllPending
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1741
DTC::ProgramList
Definition: programList.h:26
Guide::GetProgramGuide
DTC::ProgramGuide * GetProgramGuide(const QDateTime &StartTime, const QDateTime &EndTime, bool Details, int ChannelGroupId, int StartIndex, int Count, bool WithInvisible) override
Definition: guide.cpp:55
DTC::ChannelInfo
Definition: programAndChannel.h:30
Guide::GetStoredSearches
QStringList GetStoredSearches(const QString &Type) override
Definition: guide.cpp:552
AutoDeleteDeque< ProgramInfo * >::iterator
typename List::iterator iterator
Definition: autodeletedeque.h:15
DTC::ProgramGuide
Definition: programGuide.h:35
Guide::GetProgramDetails
DTC::Program * GetProgramDetails(int ChanId, const QDateTime &StartTime) override
Definition: guide.cpp:354
AutoDeleteDeque::size
size_t size(void) const
Definition: autodeletedeque.h:67
ChannelUtil::kChanOrderByChanNum
@ kChanOrderByChanNum
Definition: channelutil.h:200
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:832
ChannelInfoList
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:131
ChannelGroup::DeleteChannel
static bool DeleteChannel(uint chanid, int changrpid)
Definition: channelgroup.cpp:150