MythTV  master
mythuithemecache.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QDir>
3 #include <QDateTime>
4 
5 // MythTV
7 #include "libmythbase/mythdate.h"
8 #include "libmythbase/mythdb.h"
9 #include "libmythbase/mythdirs.h"
12 #include "libmythbase/remotefile.h"
13 
14 #include "mythuithemecache.h"
15 
16 // Std
17 #include <unistd.h>
18 #include <sys/stat.h>
19 
20 // Temp for DEFAULT_UI_THEME, ImageCacheMode etc
21 #include "mythuihelper.h"
22 
23 #define LOC QString("UICache: ")
24 
26  : m_imageThreadPool(new MThreadPool("MythUIHelper"))
27 {
28  m_maxCacheSize.fetchAndStoreRelease(GetMythDB()->GetNumSetting("UIImageCacheSize", 30) * 1024LL * 1024);
29  LOG(VB_GUI, LOG_INFO, LOC + QString("MythUI Image Cache size set to %1 bytes")
30  .arg(m_maxCacheSize.fetchAndAddRelease(0)));
31 }
32 
34 {
37 
38  QMutableMapIterator<QString, MythImage *> i(m_imageCache);
39  while (i.hasNext())
40  {
41  i.next();
42  i.value()->SetIsInCache(false);
43  i.value()->DecrRef();
44  i.remove();
45  }
46  m_cacheTrack.clear();
47 
48  delete m_imageThreadPool;
49 }
50 
52 {
53  m_cacheScreenSize = Size;
54 }
55 
57 {
58  m_themecachedir.clear();
59 }
60 
62 {
63  QMutexLocker locker(&m_cacheLock);
64 
65  QMutableMapIterator<QString, MythImage *> i(m_imageCache);
66 
67  while (i.hasNext())
68  {
69  i.next();
70  i.value()->SetIsInCache(false);
71  i.value()->DecrRef();
72  i.remove();
73  }
74 
75  m_cacheTrack.clear();
76  m_cacheSize.fetchAndStoreOrdered(0);
77 
81 }
82 
84 {
86 
87  QString themecachedir = m_themecachedir;
88 
89  m_themecachedir += '/';
90 
91  QDir dir(GetThemeBaseCacheDir());
92  dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
93  QFileInfoList list = dir.entryInfoList();
94 
95  QMap<QDateTime, QString> dirtimes;
96 
97  for (const auto & fi : std::as_const(list))
98  {
99  if (fi.isDir() && !fi.isSymLink())
100  {
101  if (fi.absoluteFilePath() == themecachedir)
102  continue;
103  dirtimes[fi.lastModified()] = fi.absoluteFilePath();
104  }
105  }
106 
107  // Cache two themes/resolutions to allow sampling other themes without
108  // incurring a penalty. Especially for those writing new themes or testing
109  // changes of an existing theme. The space used is neglible when compared
110  // against the average video
111  while (static_cast<size_t>(dirtimes.size()) >= 2)
112  {
113  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Removing cache dir: %1")
114  .arg(dirtimes.begin().value()));
115 
116  RemoveCacheDir(dirtimes.begin().value());
117  dirtimes.erase(dirtimes.begin());
118  }
119 
120  for (const auto & dirtime : std::as_const(dirtimes))
121  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Keeping cache dir: %1").arg(dirtime));
122 }
123 
124 void MythUIThemeCache::RemoveCacheDir(const QString& Dir)
125 {
126  QString cachedirname = GetThemeBaseCacheDir();
127 
128  if (!Dir.startsWith(cachedirname))
129  return;
130 
131  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Removing stale cache dir: %1").arg(Dir));
132 
133  QDir dir(Dir);
134  if (!dir.exists())
135  return;
136 
137  dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
138  QFileInfoList list = dir.entryInfoList();
139  for (const auto & fi : std::as_const(list))
140  {
141  if (fi.isFile() && !fi.isSymLink())
142  {
143  QFile file(fi.absoluteFilePath());
144  file.remove();
145  }
146  else if (fi.isDir() && !fi.isSymLink())
147  {
148  RemoveCacheDir(fi.absoluteFilePath());
149  }
150  }
151 
152  dir.rmdir(Dir);
153 }
154 
161 void MythUIThemeCache::PruneCacheDir(const QString& dirname)
162 {
163  int days = GetMythDB()->GetNumSetting("UIDiskCacheDays", 7);
164  if (days == -1)
165  {
166  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Pruning cache directory: %1 is disabled")
167  .arg(dirname));
168  return;
169  }
170 
171  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Pruning cache directory: %1").arg(dirname));
172  QDateTime cutoff = MythDate::current().addDays(-days);
173  qint64 cutoffsecs = cutoff.toSecsSinceEpoch();
174 
175  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Removing files not accessed since %1")
176  .arg(cutoff.toLocalTime().toString(Qt::ISODate)));
177 
178  // Trying to save every cycle possible within this loop. The
179  // stat() call seems significantly faster than the fi.fileRead()
180  // method. The documentation for QFileInfo says that the
181  // fi.absoluteFilePath() method has to query the file system, so
182  // use fi.filePath() method here and then add the directory if
183  // needed. Using dir.entryList() and adding the dirname each time
184  // is also slower just using dir.entryInfoList().
185  QDir dir(dirname);
186  dir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
187  dir.setSorting(QDir::NoSort);
188  QFileInfoList entries = dir.entryInfoList();
189  int kept = 0;
190  int deleted = 0;
191  int errors = 0;
192  for (const QFileInfo & fi : std::as_const(entries))
193  {
194  struct stat buf {};
195  QString fullname = fi.filePath();
196  if (not fullname.startsWith('/'))
197  fullname = dirname + "/" + fullname;
198  int rc = stat(fullname.toLocal8Bit(), &buf);
199  if (rc >= 0)
200  {
201  if (buf.st_atime < cutoffsecs)
202  {
203  deleted += 1;
204  LOG(VB_GUI | VB_FILE, LOG_DEBUG, LOC + QString("%1 Delete %2")
205  .arg(fi.lastRead().toLocalTime().toString(Qt::ISODate), fi.fileName()));
206  unlink(qPrintable(fullname));
207  }
208  else
209  {
210  kept += 1;
211  LOG(VB_GUI | VB_FILE, LOG_DEBUG, LOC + QString("%1 Keep %2")
212  .arg(fi.lastRead().toLocalTime().toString(Qt::ISODate), fi.fileName()));
213  }
214  }
215  else
216  {
217  errors += 1;
218  }
219  }
220 
221  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Kept %1 files, deleted %2 files, stat error on %3 files")
222  .arg(kept).arg(deleted).arg(errors));
223 }
224 
226 {
227  static QString s_oldcachedir;
228  QString tmpcachedir = GetThemeBaseCacheDir() + "/" +
229  GetMythDB()->GetSetting("Theme", DEFAULT_UI_THEME) + "." +
230  QString::number(m_cacheScreenSize.width()) + "." +
231  QString::number(m_cacheScreenSize.height());
232 
233  if (tmpcachedir != s_oldcachedir)
234  {
235  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Creating cache dir: %1").arg(tmpcachedir));
236  QDir dir;
237  dir.mkdir(tmpcachedir);
238  s_oldcachedir = tmpcachedir;
239  }
240  return tmpcachedir;
241 }
242 
250 QString MythUIThemeCache::GetCacheDirByUrl(const QString& URL)
251 {
252  if (URL.startsWith("myth:") || URL.startsWith("-"))
253  return GetThumbnailDir();
254  return GetThemeCacheDir();
255 }
256 
257 MythImage* MythUIThemeCache::LoadCacheImage(QString File, const QString& Label,
258  MythPainter *Painter,
259  ImageCacheMode cacheMode)
260 {
261  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
262  QString("LoadCacheImage(%1,%2)").arg(File, Label));
263 
264  if (File.isEmpty() || Label.isEmpty())
265  return nullptr;
266 
267  if (!(kCacheForceStat & cacheMode))
268  {
269  // Some screens include certain images dozens or even hundreds of
270  // times. Even if the image is in the cache, there is still a
271  // stat system call on the original file to see if it has changed.
272  // This code relaxes the original-file check so that the check
273  // isn't repeated if it was already done within kImageCacheTimeout
274  // seconds.
275 
276  // This only applies to the MEMORY cache
277  constexpr std::chrono::seconds kImageCacheTimeout { 60s };
278  SystemTime now = SystemClock::now();
279 
280  QMutexLocker locker(&m_cacheLock);
281 
282  if (m_imageCache.contains(Label) &&
283  m_cacheTrack[Label] + kImageCacheTimeout > now)
284  {
285  m_imageCache[Label]->IncrRef();
286  return m_imageCache[Label];
287  }
288  }
289 
290  MythImage *ret = nullptr;
291 
292  // Check Memory Cache
293  ret = GetImageFromCache(Label);
294 
295  // If the image is in the memory or we are not ignoring the disk cache
296  // then proceed to check whether the source file is newer than our cached
297  // copy
298  if (ret || !(cacheMode & kCacheIgnoreDisk))
299  {
300  // Create url to image in disk cache
301  QString cachefilepath;
302  cachefilepath = GetCacheDirByUrl(Label) + '/' + Label;
303  QFileInfo cacheFileInfo(cachefilepath);
304 
305  // If the file isn't in the disk cache, then we don't want to bother
306  // checking the last modified times of the original
307  if (!cacheFileInfo.exists())
308  return nullptr;
309 
310  // Now compare the time on the source versus our cached copy
311  QDateTime srcLastModified;
312 
313  // For internet images this involves querying the headers of the remote
314  // image. This is slow even without redownloading the whole image
315  if ((File.startsWith("http://")) ||
316  (File.startsWith("https://")) ||
317  (File.startsWith("ftp://")))
318  {
319  // If the image is in the memory cache then skip the last modified
320  // check, since memory cached images are loaded in the foreground
321  // this can cause an intolerable delay. The images won't stay in
322  // the cache forever and so eventually they will be checked.
323  if (ret)
324  srcLastModified = cacheFileInfo.lastModified();
325  else
326  srcLastModified = GetMythDownloadManager()->GetLastModified(File);
327  }
328  else if (File.startsWith("myth://"))
329  {
330  srcLastModified = RemoteFile::LastModified(File);
331  }
332  else
333  {
334  if (!GetMythUI()->FindThemeFile(File))
335  return nullptr;
336 
337  QFileInfo original(File);
338 
339  if (original.exists())
340  srcLastModified = original.lastModified();
341  }
342 
343  // Now compare the timestamps, if the cached image is newer than the
344  // source image we can use it, otherwise we want to remove it from the
345  // cache
346  if (cacheFileInfo.lastModified() >= srcLastModified)
347  {
348  // If we haven't already loaded the image from the memory cache
349  // and we're not ignoring the disk cache, then it's time to load
350  // it from there instead
351  if (!ret && (cacheMode == kCacheNormal))
352  {
353 
354  if (Painter)
355  {
356  ret = Painter->GetFormatImage();
357 
358  // Load file from disk cache to memory cache
359  if (ret->Load(cachefilepath))
360  {
361  // Add to ram cache, and skip saving to disk since that is
362  // where we found this in the first place.
363  CacheImage(Label, ret, true);
364  }
365  else
366  {
367  LOG(VB_GUI | VB_FILE, LOG_WARNING, LOC +
368  QString("LoadCacheImage: Could not load :%1")
369  .arg(cachefilepath));
370 
371  ret->SetIsInCache(false);
372  ret->DecrRef();
373  ret = nullptr;
374  }
375  }
376  }
377  }
378  else
379  {
380  ret = nullptr;
381  // If file has changed on disk, then remove it from the memory
382  // and disk cache
383  RemoveFromCacheByURL(Label);
384  }
385  }
386 
387  return ret;
388 }
389 
391 {
392  QMutexLocker locker(&m_cacheLock);
393 
394  if (m_imageCache.contains(URL))
395  {
396  m_cacheTrack[URL] = SystemClock::now();
397  m_imageCache[URL]->IncrRef();
398  return m_imageCache[URL];
399  }
400 
401  /*
402  if (QFileInfo(URL).exists())
403  {
404  MythImage *im = GetMythPainter()->GetFormatImage();
405  im->Load(URL,false);
406  return im;
407  }
408  */
409 
410  return nullptr;
411 }
412 
413 MythImage *MythUIThemeCache::CacheImage(const QString& URL, MythImage* Image, bool NoDisk)
414 {
415  if (!Image)
416  return nullptr;
417 
418  if (!NoDisk)
419  {
420  QString dstfile = GetCacheDirByUrl(URL) + '/' + URL;
421  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Saved to Cache (%1)").arg(dstfile));
422  // Save to disk cache
423  Image->save(dstfile, "PNG");
424  }
425 
426  // delete the oldest cached images until we fall below threshold.
427  QMutexLocker locker(&m_cacheLock);
428 
429  while ((m_cacheSize.fetchAndAddOrdered(0) + Image->sizeInBytes()) >=
430  m_maxCacheSize.fetchAndAddOrdered(0) && !m_imageCache.empty())
431  {
432  QMap<QString, MythImage *>::iterator it = m_imageCache.begin();
433  auto oldestTime = SystemClock::now();
434  QString oldestKey = it.key();
435 
436  int count = 0;
437 
438  for (; it != m_imageCache.end(); ++it)
439  {
440  if (m_cacheTrack[it.key()] < oldestTime)
441  {
442  if ((2 == it.value()->IncrRef()) && (it.value() != Image))
443  {
444  oldestTime = m_cacheTrack[it.key()];
445  oldestKey = it.key();
446  count++;
447  }
448  it.value()->DecrRef();
449  }
450  }
451 
452  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +QString("%1 images are eligible for expiry").arg(count));
453  if (count > 0)
454  {
455  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("Cache too big (%1), removing :%2:")
456  .arg(m_cacheSize.fetchAndAddOrdered(0) + Image->sizeInBytes())
457  .arg(oldestKey));
458 
459  m_imageCache[oldestKey]->SetIsInCache(false);
460  m_imageCache[oldestKey]->DecrRef();
461  m_imageCache.remove(oldestKey);
462  m_cacheTrack.remove(oldestKey);
463  }
464  else
465  {
466  break;
467  }
468  }
469 
470  QMap<QString, MythImage *>::iterator it = m_imageCache.find(URL);
471 
472  if (it == m_imageCache.end())
473  {
474  Image->IncrRef();
475  m_imageCache[URL] = Image;
476  m_cacheTrack[URL] = SystemClock::now();
477 
478  Image->SetIsInCache(true);
479  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
480  QString("NOT IN RAM CACHE, Adding, and adding to size :%1: :%2:").arg(URL)
481  .arg(Image->sizeInBytes()));
482  }
483 
484  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("MythUIHelper::CacheImage : Cache Count = :%1: size :%2:")
485  .arg(m_imageCache.count()).arg(m_cacheSize.fetchAndAddRelaxed(0)));
486 
487  return m_imageCache[URL];
488 }
489 
491 {
492  QMutexLocker locker(&m_cacheLock);
493  QMap<QString, MythImage *>::iterator it = m_imageCache.find(URL);
494 
495  if (it != m_imageCache.end())
496  {
497  m_imageCache[URL]->SetIsInCache(false);
498  m_imageCache[URL]->DecrRef();
499  m_imageCache.remove(URL);
500  m_cacheTrack.remove(URL);
501  }
502 
503  QString dstfile = GetCacheDirByUrl(URL) + '/' + URL;
504  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC + QString("RemoveFromCacheByURL removed :%1: from cache").arg(dstfile));
505  QFile::remove(dstfile);
506 }
507 
509 {
510  QList<QString>::iterator it;
511 
512  QString partialKey = File;
513  partialKey.replace('/', '-');
514 
515  m_cacheLock.lock();
516  QList<QString> m_imageCacheKeys = m_imageCache.keys();
517  m_cacheLock.unlock();
518 
519  for (it = m_imageCacheKeys.begin(); it != m_imageCacheKeys.end(); ++it)
520  {
521  if ((*it).contains(partialKey))
523  }
524 
525  // Loop through files to cache any that were not caught by
526  // RemoveFromCacheByURL
527  QDir dir(GetThemeCacheDir());
528  QFileInfoList list = dir.entryInfoList();
529 
530  for (const auto & fileInfo : std::as_const(list))
531  {
532  if (fileInfo.fileName().contains(partialKey))
533  {
534  LOG(VB_GUI | VB_FILE, LOG_INFO, LOC +
535  QString("RemoveFromCacheByFile removed: %1: from cache")
536  .arg(fileInfo.fileName()));
537 
538  if (!dir.remove(fileInfo.fileName()))
539  {
540  LOG(VB_GENERAL, LOG_ERR, LOC +
541  QString("Failed to delete %1 from the theme cache")
542  .arg(fileInfo.fileName()));
543  }
544  }
545  }
546 }
547 
548 bool MythUIThemeCache::IsImageInCache(const QString& URL)
549 {
550  QMutexLocker locker(&m_cacheLock);
551  if (m_imageCache.contains(URL))
552  return true;
553  if (QFileInfo::exists(URL))
554  return true;
555  return false;
556 }
557 
559 {
560  if (Image)
561  m_cacheSize.fetchAndAddOrdered(Image->sizeInBytes());
562 }
563 
565 {
566  if (Image)
567  m_cacheSize.fetchAndAddOrdered(-Image->sizeInBytes());
568 }
569 
571 {
572  return m_imageThreadPool;
573 }
574 
RemoteFile::LastModified
QDateTime LastModified(void) const
Definition: remotefile.cpp:1261
MythImage::Load
bool Load(MythImageReader *reader)
Definition: mythimage.cpp:276
mythdb.h
MythUIThemeCache::m_cacheScreenSize
QSize m_cacheScreenSize
Definition: mythuithemecache.h:55
MythUIThemeCache::m_imageCache
QMap< QString, MythImage * > m_imageCache
Definition: mythuithemecache.h:49
SystemTime
std::chrono::time_point< SystemClock > SystemTime
Definition: mythchrono.h:67
MythPainter::GetFormatImage
MythImage * GetFormatImage()
Returns a blank reference counted image in the format required for the Draw functions for this painte...
Definition: mythpainter.cpp:528
MythUIThemeCache::MythUIThemeCache
MythUIThemeCache()
Definition: mythuithemecache.cpp:25
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:50
build_compdb.file
file
Definition: build_compdb.py:55
mythdirs.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
MythUIThemeCache::SetScreenSize
void SetScreenSize(QSize Size)
Definition: mythuithemecache.cpp:51
MythUIThemeCache::m_cacheSize
QAtomicInteger< qint64 > m_cacheSize
Definition: mythuithemecache.h:52
MythImage::SetIsInCache
void SetIsInCache(bool bCached)
Definition: mythimage.cpp:70
MythUIThemeCache::m_themecachedir
QString m_themecachedir
Definition: mythuithemecache.h:54
mythdate.h
MythUIThemeCache::RemoveFromCacheByURL
void RemoveFromCacheByURL(const QString &URL)
Definition: mythuithemecache.cpp:490
mythlogging.h
MythUIThemeCache::IsImageInCache
bool IsImageInCache(const QString &URL)
Definition: mythuithemecache.cpp:548
remotefile.h
ImageCacheMode
ImageCacheMode
Definition: mythuithemecache.h:12
MythUIThemeCache::m_cacheLock
QRecursiveMutex m_cacheLock
Definition: mythuithemecache.h:51
kCacheNormal
@ kCacheNormal
Definition: mythuithemecache.h:14
kCacheForceStat
@ kCacheForceStat
Definition: mythuithemecache.h:17
MythUIThemeCache::PruneCacheDir
static void PruneCacheDir(const QString &Dir)
Remove all files in the cache that haven't been accessed in a user configurable number of days.
Definition: mythuithemecache.cpp:161
MythImage::DecrRef
int DecrRef(void) override
Decrements reference count and deletes on 0.
Definition: mythimage.cpp:52
MythUIThemeCache::RemoveFromCacheByFile
void RemoveFromCacheByFile(const QString &File)
Definition: mythuithemecache.cpp:508
GetThemeBaseCacheDir
QString GetThemeBaseCacheDir(void)
Returns the base directory where all theme related files should be cached.
Definition: mythdirs.cpp:289
MythUIThemeCache::GetThemeCacheDir
QString GetThemeCacheDir()
Definition: mythuithemecache.cpp:225
MythUIThemeCache::RemoveCacheDir
void RemoveCacheDir(const QString &Dir)
Definition: mythuithemecache.cpp:124
MythUIThemeCache::LoadCacheImage
MythImage * LoadCacheImage(QString File, const QString &Label, MythPainter *Painter, ImageCacheMode cacheMode=kCacheNormal)
Definition: mythuithemecache.cpp:257
kCacheIgnoreDisk
@ kCacheIgnoreDisk
Definition: mythuithemecache.h:15
MythUIThemeCache::ClearOldImageCache
void ClearOldImageCache()
Definition: mythuithemecache.cpp:83
MythUIThemeCache::IncludeInCacheSize
void IncludeInCacheSize(MythImage *Image)
Definition: mythuithemecache.cpp:558
MythUIThemeCache::GetCacheDirByUrl
QString GetCacheDirByUrl(const QString &URL)
Look at the url being read and decide whether the cached version should go into the theme cache or th...
Definition: mythuithemecache.cpp:250
mythuithemecache.h
GetThumbnailDir
QString GetThumbnailDir(void)
Returns the directory where all non-theme thumbnail files should be cached.
Definition: mythdirs.cpp:281
MythUIThemeCache::GetImageFromCache
MythImage * GetImageFromCache(const QString &URL)
Definition: mythuithemecache.cpp:390
GetRemoteCacheDir
QString GetRemoteCacheDir(void)
Returns the directory for all files cached from the backend.
Definition: mythdirs.cpp:273
mthreadpool.h
mythuihelper.h
MythImage::IncrRef
int IncrRef(void) override
Increments reference count.
Definition: mythimage.cpp:44
DEFAULT_UI_THEME
static constexpr const char * DEFAULT_UI_THEME
Definition: mythuithemehelper.h:7
std::chrono::days
duration< CHRONO_TYPE, ratio< 86400 > > days
Definition: mythchrono.h:25
MThreadPool
Definition: mthreadpool.h:18
MythPainter
Definition: mythpainter.h:34
MythImage
Definition: mythimage.h:36
MythUIThemeCache::m_maxCacheSize
QAtomicInteger< qint64 > m_maxCacheSize
Definition: mythuithemecache.h:53
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
MythUIThemeCache::ExcludeFromCacheSize
void ExcludeFromCacheSize(MythImage *Image)
Definition: mythuithemecache.cpp:564
LOC
#define LOC
Definition: mythuithemecache.cpp:23
MythUIThemeCache::UpdateImageCache
void UpdateImageCache()
Definition: mythuithemecache.cpp:61
MythDownloadManager::GetLastModified
QDateTime GetLastModified(const QString &url)
Gets the Last Modified timestamp for a URI.
Definition: mythdownloadmanager.cpp:1537
MythUIThemeCache::ClearThemeCacheDir
void ClearThemeCacheDir()
Definition: mythuithemecache.cpp:56
MythUIThemeCache::m_imageThreadPool
MThreadPool * m_imageThreadPool
Definition: mythuithemecache.h:56
mythdownloadmanager.h
MythUIThemeCache::~MythUIThemeCache
~MythUIThemeCache()
Definition: mythuithemecache.cpp:33
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
MythUIThemeCache::m_cacheTrack
QMap< QString, SystemTime > m_cacheTrack
Definition: mythuithemecache.h:50
MythUIThemeCache::GetImageThreadPool
MThreadPool * GetImageThreadPool()
Definition: mythuithemecache.cpp:570
MythUIThemeCache::CacheImage
MythImage * CacheImage(const QString &URL, MythImage *Image, bool NoDisk=false)
Definition: mythuithemecache.cpp:413
GetMythDownloadManager
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
Definition: mythdownloadmanager.cpp:145