|
|
|
|
@ -6,6 +6,7 @@ |
|
|
|
|
|
|
|
|
|
#include "abstractimagelistmodel.h" |
|
|
|
|
|
|
|
|
|
#include <QPainter> |
|
|
|
|
#include <QThreadPool> |
|
|
|
|
|
|
|
|
|
#include <KFileItem> |
|
|
|
|
@ -72,48 +73,95 @@ void AbstractImageListModel::slotHandleImageSizeFound(const QString &path, const |
|
|
|
|
|
|
|
|
|
void AbstractImageListModel::slotHandlePreview(const KFileItem &item, const QPixmap &preview) |
|
|
|
|
{ |
|
|
|
|
auto job = qobject_cast<KIO::PreviewJob *>(sender()); |
|
|
|
|
if (!job) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const QString urlString = item.url().toLocalFile(); |
|
|
|
|
const QPersistentModelIndex pidx = m_previewJobsUrls.take(urlString); |
|
|
|
|
QModelIndex idx; |
|
|
|
|
const QPersistentModelIndex idx = job->property("index").toPersistentModelIndex(); |
|
|
|
|
|
|
|
|
|
if (!pidx.isValid()) { |
|
|
|
|
if (int row = indexOf(urlString); row >= 0) { |
|
|
|
|
idx = index(row, 0); |
|
|
|
|
} else { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
auto it = m_previewJobsUrls.find(idx); |
|
|
|
|
Q_ASSERT(it != m_previewJobsUrls.end()); |
|
|
|
|
it->removeOne(urlString); |
|
|
|
|
|
|
|
|
|
const QStringList paths = job->property("paths").toStringList(); |
|
|
|
|
QPixmap *cachedPreview = m_imageCache.object(paths); |
|
|
|
|
|
|
|
|
|
if (!cachedPreview) { |
|
|
|
|
// Insert full preview
|
|
|
|
|
m_imageCache.insert(paths, new QPixmap(preview), 0); |
|
|
|
|
} else { |
|
|
|
|
idx = pidx; |
|
|
|
|
// Show multiple images side by side
|
|
|
|
|
QPainter p(cachedPreview); |
|
|
|
|
|
|
|
|
|
const int i = paths.indexOf(urlString); |
|
|
|
|
const double start = i / static_cast<double>(paths.size()); |
|
|
|
|
const double end = (i + 1) / static_cast<double>(paths.size()); |
|
|
|
|
// Cropped area
|
|
|
|
|
const QPoint topLeft(start * preview.width(), 0); |
|
|
|
|
const QPoint bottomRight(end * preview.width(), preview.height()); |
|
|
|
|
// Inserted area
|
|
|
|
|
const QPoint topLeft2(start * cachedPreview->width(), 0); |
|
|
|
|
const QPoint bottomRight2(end * cachedPreview->width(), cachedPreview->height()); |
|
|
|
|
|
|
|
|
|
p.drawPixmap(QRect(topLeft2, bottomRight2), preview.copy(QRect(topLeft, bottomRight))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const int cost = preview.width() * preview.height() * preview.depth() / 8; |
|
|
|
|
if (it->empty()) { |
|
|
|
|
// All images in the list have been loaded
|
|
|
|
|
m_previewJobsUrls.erase(it); |
|
|
|
|
|
|
|
|
|
if (m_imageCache.insert(urlString, new QPixmap(preview), cost)) { |
|
|
|
|
Q_EMIT dataChanged(idx, idx, {ScreenshotRole}); |
|
|
|
|
cachedPreview = m_imageCache.object(paths); |
|
|
|
|
auto finalPreview = new QPixmap(*cachedPreview); |
|
|
|
|
|
|
|
|
|
if (m_imageCache.insert(paths, finalPreview, 1)) { |
|
|
|
|
Q_EMIT dataChanged(idx, idx, {ScreenshotRole}); |
|
|
|
|
} else { |
|
|
|
|
delete finalPreview; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AbstractImageListModel::slotHandlePreviewFailed(const KFileItem &item) |
|
|
|
|
{ |
|
|
|
|
m_previewJobsUrls.remove(item.url().toLocalFile()); |
|
|
|
|
auto job = qobject_cast<KIO::PreviewJob *>(sender()); |
|
|
|
|
if (!job) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto it = m_previewJobsUrls.find(job->property("index").toPersistentModelIndex()); |
|
|
|
|
Q_ASSERT(it != m_previewJobsUrls.end()); |
|
|
|
|
|
|
|
|
|
it->removeOne(item.url().toLocalFile()); |
|
|
|
|
if (it->empty()) { |
|
|
|
|
m_previewJobsUrls.erase(it); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AbstractImageListModel::asyncGetPreview(const QString &path, const QPersistentModelIndex &index) const |
|
|
|
|
void AbstractImageListModel::asyncGetPreview(const QStringList &paths, const QPersistentModelIndex &index) const |
|
|
|
|
{ |
|
|
|
|
if (m_previewJobsUrls.contains(path) || path.isEmpty()) { |
|
|
|
|
if (m_previewJobsUrls.contains(index) || paths.isEmpty()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const QUrl url = QUrl::fromLocalFile(path); |
|
|
|
|
const QStringList availablePlugins = KIO::PreviewJob::availablePlugins(); |
|
|
|
|
KFileItemList list; |
|
|
|
|
|
|
|
|
|
for (const QString &path : paths) { |
|
|
|
|
list.append(KFileItem(QUrl::fromLocalFile(path), QString(), 0)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
KIO::PreviewJob *const job = KIO::filePreview(KFileItemList{KFileItem(url, QString(), 0)}, m_screenshotSize, &availablePlugins); |
|
|
|
|
KIO::PreviewJob *const job = KIO::filePreview(list, m_screenshotSize, &availablePlugins); |
|
|
|
|
job->setIgnoreMaximumSize(true); |
|
|
|
|
|
|
|
|
|
job->setProperty("paths", paths); |
|
|
|
|
job->setProperty("index", index); |
|
|
|
|
|
|
|
|
|
connect(job, &KIO::PreviewJob::gotPreview, this, &AbstractImageListModel::slotHandlePreview); |
|
|
|
|
connect(job, &KIO::PreviewJob::failed, this, &AbstractImageListModel::slotHandlePreviewFailed); |
|
|
|
|
|
|
|
|
|
m_previewJobsUrls.insert(path, index); |
|
|
|
|
m_previewJobsUrls.insert(index, paths); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AbstractImageListModel::asyncGetImageSize(const QString &path, const QPersistentModelIndex &index) const |
|
|
|
|
|