22 #define LOC QString("UICache: ")
25 : m_imageThreadPool(new
MThreadPool(
"MythUIHelper"))
28 LOG(VB_GUI, LOG_INFO,
LOC + QString(
"MythUI Image Cache size set to %1 bytes")
37 QMutableMapIterator<QString, MythImage *> i(
m_imageCache);
41 i.value()->SetIsInCache(
false);
64 QMutableMapIterator<QString, MythImage *> i(
m_imageCache);
69 i.value()->SetIsInCache(
false);
91 dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
92 QFileInfoList list =
dir.entryInfoList();
94 QMap<QDateTime, QString> dirtimes;
96 for (
const auto & fi : qAsConst(list))
98 if (fi.isDir() && !fi.isSymLink())
100 if (fi.absoluteFilePath() == themecachedir)
102 dirtimes[fi.lastModified()] = fi.absoluteFilePath();
110 while (
static_cast<size_t>(dirtimes.size()) >= 2)
112 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Removing cache dir: %1")
113 .
arg(dirtimes.begin().value()));
116 dirtimes.erase(dirtimes.begin());
119 for (
const auto & dirtime : qAsConst(dirtimes))
120 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Keeping cache dir: %1").
arg(dirtime));
127 if (!Dir.startsWith(cachedirname))
130 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Removing stale cache dir: %1").
arg(Dir));
136 dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
137 QFileInfoList list =
dir.entryInfoList();
138 for (
const auto & fi : qAsConst(list))
140 if (fi.isFile() && !fi.isSymLink())
142 QFile
file(fi.absoluteFilePath());
145 else if (fi.isDir() && !fi.isSymLink())
165 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Pruning cache directory: %1 is disabled")
170 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Pruning cache directory: %1").
arg(dirname));
172 qint64 cutoffsecs = cutoff.toSecsSinceEpoch();
174 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Removing files not accessed since %1")
185 dir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
186 dir.setSorting(QDir::NoSort);
187 QFileInfoList entries =
dir.entryInfoList();
191 for (
const QFileInfo & fi : qAsConst(entries))
194 QString fullname = fi.filePath();
195 if (not fullname.startsWith(
'/'))
196 fullname = dirname +
"/" + fullname;
197 int rc = stat(fullname.toLocal8Bit(), &buf);
200 if (buf.st_atime < cutoffsecs)
203 LOG(VB_GUI | VB_FILE, LOG_DEBUG,
LOC + QString(
"%1 Delete %2")
204 .
arg(fi.lastRead().toLocalTime().toString(
Qt::ISODate)).arg(fi.fileName()));
205 unlink(qPrintable(fullname));
210 LOG(VB_GUI | VB_FILE, LOG_DEBUG,
LOC + QString(
"%1 Keep %2")
211 .
arg(fi.lastRead().toLocalTime().toString(
Qt::ISODate)).arg(fi.fileName()));
220 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Kept %1 files, deleted %2 files, stat error on %3 files")
226 static QString s_oldcachedir;
232 if (tmpcachedir != s_oldcachedir)
234 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Creating cache dir: %1").
arg(tmpcachedir));
236 dir.mkdir(tmpcachedir);
237 s_oldcachedir = tmpcachedir;
251 if (URL.startsWith(
"myth:") || URL.startsWith(
"-"))
260 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC +
261 QString(
"LoadCacheImage(%1,%2)").
arg(File).
arg(Label));
263 if (File.isEmpty() || Label.isEmpty())
276 const uint kImageCacheTimeout = 60;
300 QString cachefilepath;
302 QFileInfo cacheFileInfo(cachefilepath);
306 if (!cacheFileInfo.exists())
310 QDateTime srcLastModified;
314 if ((File.startsWith(
"http://")) ||
315 (File.startsWith(
"https://")) ||
316 (File.startsWith(
"ftp://")))
323 srcLastModified = cacheFileInfo.lastModified();
327 else if (File.startsWith(
"myth://"))
336 QFileInfo original(File);
338 if (original.exists())
339 srcLastModified = original.lastModified();
345 if (cacheFileInfo.lastModified() >= srcLastModified)
358 if (ret->
Load(cachefilepath))
366 LOG(VB_GUI | VB_FILE, LOG_WARNING,
LOC +
367 QString(
"LoadCacheImage: Could not load :%1")
368 .
arg(cachefilepath));
420 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Saved to Cache (%1)").
arg(dstfile));
422 Image->save(dstfile,
"PNG");
429 #
if QT_VERSION < QT_VERSION_CHECK(5,10,0)
437 QMap<QString, MythImage *>::iterator it =
m_imageCache.begin();
439 QString oldestKey = it.key();
447 if ((2 == it.value()->IncrRef()) && (it.value() !=
Image))
450 oldestKey = it.key();
453 it.value()->DecrRef();
457 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC +QString(
"%1 images are eligible for expiry").
arg(count));
460 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"Cache too big (%1), removing :%2:")
462 #
if QT_VERSION < QT_VERSION_CHECK(5,10,0)
481 QMap<QString, MythImage *>::iterator it =
m_imageCache.find(URL);
489 Image->SetIsInCache(
true);
490 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC +
491 QString(
"NOT IN RAM CACHE, Adding, and adding to size :%1: :%2:").
arg(URL)
492 #
if QT_VERSION < QT_VERSION_CHECK(5,10,0)
495 .arg(
Image->sizeInBytes())
500 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"MythUIHelper::CacheImage : Cache Count = :%1: size :%2:")
509 QMap<QString, MythImage *>::iterator it =
m_imageCache.find(URL);
520 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC + QString(
"RemoveFromCacheByURL removed :%1: from cache").
arg(dstfile));
521 QFile::remove(dstfile);
526 QList<QString>::iterator it;
528 QString partialKey = File;
529 partialKey.replace(
'/',
'-');
535 for (it = m_imageCacheKeys.begin(); it != m_imageCacheKeys.end(); ++it)
537 if ((*it).contains(partialKey))
544 QFileInfoList list =
dir.entryInfoList();
548 if (
fileInfo.fileName().contains(partialKey))
550 LOG(VB_GUI | VB_FILE, LOG_INFO,
LOC +
551 QString(
"RemoveFromCacheByFile removed: %1: from cache")
556 LOG(VB_GENERAL, LOG_ERR,
LOC +
557 QString(
"Failed to delete %1 from the theme cache")
569 if (QFileInfo::exists(URL))
578 #if QT_VERSION < QT_VERSION_CHECK(5,10,0)
590 #if QT_VERSION < QT_VERSION_CHECK(5,10,0)