void Cache::setEntry(const Entry &entry) { QMutableListIterator<Entry> it(m_entries); while (it.hasNext()) { Entry e = it.next(); if (e.url == entry.url) { it.setValue(entry); writeCacheFile(); return; } } m_entries.append(entry); writeCacheFile(); }
QImage NemoThumbnailProvider::generateThumbnail(const QString &id, const QByteArray &hashData, const QSize &requestedSize, bool crop) { QImage img; QSize originalSize; QByteArray format; // image was not in cache thus we read it QImageReader ir(id); if (!ir.canRead()) return img; originalSize = ir.size(); format = ir.format(); if (originalSize != requestedSize && originalSize.isValid()) { if (crop) { // scales arbitrary sized source image to requested size scaling either up or down // keeping aspect ratio of the original image intact by maximizing either width or height // and cropping the rest of the image away QSize scaledSize(originalSize); // now scale it filling the original rectangle by keeping aspect ratio, but expand if needed. scaledSize.scale(requestedSize, Qt::KeepAspectRatioByExpanding); // set the adjusted clipping rectangle in the center of the scaled image QPoint center((scaledSize.width() - 1) / 2, (scaledSize.height() - 1) / 2); QRect cr(0,0,requestedSize.width(), requestedSize.height()); cr.moveCenter(center); ir.setScaledClipRect(cr); // set requested target size of a thumbnail ir.setScaledSize(scaledSize); } else { // Maintains correct aspect ratio without cropping, as such the final image may // be smaller than requested in one dimension. QSize scaledSize(originalSize); scaledSize.scale(requestedSize, Qt::KeepAspectRatio); ir.setScaledSize(scaledSize); } } img = ir.read(); NemoImageMetadata meta(id, format); if (meta.orientation() != NemoImageMetadata::TopLeft) img = rotate(img, meta.orientation()); // write the scaled image to cache if (meta.orientation() != NemoImageMetadata::TopLeft || (originalSize != requestedSize && originalSize.isValid())) { writeCacheFile(hashData, img); } TDEBUG() << Q_FUNC_INFO << "Wrote " << id << " to cache"; return img; }
void Document::cache() { if (m_cache_outdated) { m_cache_outdated = false; DocumentWriter* writer = new DocumentWriter; writer->setType(!m_filename.isEmpty() ? m_filename.section(QLatin1Char('.'), -1) : "odt"); writer->setEncoding(m_encoding); writer->setWriteByteOrderMark(Preferences::instance().writeByteOrderMark()); writer->setDocument(m_text->document()->clone()); emit writeCacheFile(this, writer); } }
void Cache::cleanCache(const QList<QUrl> &in) { // purge entries that don't exist in 'in' { QList<Entry> entriesToRemove; for (const auto entry : m_entries) { if (!in.contains(entry.url)) { // this entry doesn't exist anymore, so remove it entriesToRemove += entry; } } for (auto entry : entriesToRemove) { removeEntry(entry); } } // remove directories, as that's not something we put there for (const QFileInfo &info : m_dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { FS::remove(info); } // remove files that we don't know anything of for (const QFileInfo &info : m_dir.entryInfoList(QStringList() << "*.cache", QDir::Files)) { if (info.fileName() == ".cache.json") { continue; } bool found = false; for (const auto entry : m_entries) { if (absoluteFilename(entry) == info.absoluteFilePath()) { found = true; break; } } // it doesn't exist in the cache metadata, so we remove it if (!found) { FS::remove(info); } } // remove cache entries where the file isn't existing anymore { QMutableListIterator<Entry> it(m_entries); while (it.hasNext()) { if (!QFileInfo(absoluteFilename(it.next())).exists()) { it.remove(); } } } writeCacheFile(); }
QImage FileThumbnailImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { setupCache(); // needed for stupid things like gallery model, which pass us a url if (id.startsWith("file://")) { qWarning() << Q_FUNC_INFO << "Removing file:// prefix, before: " << id; QString &nid = const_cast<QString &>(id); nid = nid.remove(0, 7); } qDebug() << Q_FUNC_INFO << "Requested image: " << id << " with size " << requestedSize; // sourceSize should indicate what size thumbnail you want. i.e. if you want a 120x120px thumbnail, // set sourceSize: Qt.size(120, 120). if (!requestedSize.isValid()) qFatal("You must request a sourceSize whenever you use nemoThumbnail"); if (size) *size = requestedSize; QByteArray hashData = cacheKey(id, requestedSize); QImage img = attemptCachedServe(hashData); if (!img.isNull()) { qDebug() << Q_FUNC_INFO << "Read " << id << " from cache"; return img; } // cache couldn't satisfy us. // step 1: read source image in QImageReader ir(id); img = ir.read(); // don't pollute the cache with false positives if (img.isNull()) return QImage(); if (img.size() == requestedSize) return img; // step 2: scale to target size if (img.height() == img.width()) { // in the case of a squared image, there's no need to crop img = img.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } else if (img.height() >= requestedSize.height() && img.width() >= requestedSize.width()) { // if the image is larger than the desired size (on both dimensions) // then crop, and scale down if (img.width() < img.height()) { int cropPosition = (img.height() - img.width()) / 2; img = img.copy(0, cropPosition, img.width(), img.width()); img = img.scaledToWidth(requestedSize.width(), Qt::SmoothTransformation); } else { int cropPosition = (img.width() - img.height()) / 2; img = img.copy(cropPosition, 0, img.height(), img.height()); img = img.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); } } else if ((img.width() <= requestedSize.width() && img.height() >= requestedSize.height()) || (img.width() >= requestedSize.width() && img.height() <= requestedSize.height())) { // if the image is smaller than the desired size on one dimension, scale it up, // then crop down to thumbnail size. if (img.width() <= requestedSize.width() && img.height() >= requestedSize.height()) { img = img.scaledToWidth(requestedSize.width(), Qt::SmoothTransformation); int cropPosition = (img.height() - img.width()) / 2; img = img.copy(0, cropPosition, img.width(), img.width()); } else { img = img.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); int cropPosition = (img.width() - img.height()) / 2; img = img.copy(cropPosition, 0, img.height(), img.height()); } } else { // if the image is smaller on both dimensions, scale it up, and use the requested // size to do the cropping if (img.width() < img.height()) { img = img.scaledToWidth(requestedSize.width(), Qt::SmoothTransformation); int cropPosition = (img.height() - requestedSize.height()) / 2; img = img.copy(0, cropPosition, img.width(), img.width()); } else { img = img.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); int cropPosition = (img.width() - requestedSize.width()) / 2; img = img.copy(cropPosition, 0, img.height(), img.height()); } } // step 3: write to cache for next time writeCacheFile(hashData, img); qDebug() << Q_FUNC_INFO << "Wrote " << id << " to cache"; return img; }