File indexing completed on 2024-04-28 17:06:21

0001 /*
0002     SPDX-FileCopyrightText: 2009 Jan Lepper <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2009-2022 Krusader Krew <https://krusader.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "krpreviewjob.h"
0009 
0010 #include "../FileSystem/fileitem.h"
0011 #include "../defaults.h"
0012 #include "PanelView/krview.h"
0013 #include "PanelView/krviewitem.h"
0014 #include "krpreviews.h"
0015 
0016 #include <stdio.h>
0017 
0018 // QtWidgets
0019 #include <QWidget>
0020 
0021 #define ASSERT(what)                                                                                                                                           \
0022     if (!(what))                                                                                                                                               \
0023         abort();
0024 
0025 // how much items to process by a single job
0026 // view becomes unresponsive during load if set too high
0027 #define MAX_CHUNK_SIZE 50
0028 
0029 KrPreviewJob::KrPreviewJob(KrPreviews *parent)
0030     : _job(nullptr)
0031     , _parent(parent)
0032 {
0033     _timer.setSingleShot(true);
0034     _timer.setInterval(0);
0035     connect(&_timer, &QTimer::timeout, this, &KrPreviewJob::slotStartJob);
0036 }
0037 
0038 KrPreviewJob::~KrPreviewJob()
0039 {
0040     doKill();
0041 }
0042 
0043 void KrPreviewJob::scheduleItem(KrViewItem *item)
0044 {
0045     if (!_scheduled.contains(item)) {
0046         _scheduled.append(item);
0047         setTotalAmount(KJob::Files, totalAmount(KJob::Files) + 1);
0048     }
0049     if (!_job)
0050         _timer.start();
0051 }
0052 
0053 void KrPreviewJob::removeItem(KrViewItem *item)
0054 {
0055     setTotalAmount(KJob::Files, totalAmount(KJob::Files) - _scheduled.removeAll(item));
0056     if (_job) {
0057         doKill();
0058         if (!_scheduled.isEmpty())
0059             _timer.start();
0060     }
0061     if (_scheduled.isEmpty())
0062         emitResult();
0063 }
0064 
0065 void KrPreviewJob::slotFailed(const KFileItem &item)
0066 {
0067     slotGotPreview(item, QPixmap());
0068 }
0069 
0070 void KrPreviewJob::slotGotPreview(const KFileItem &item, const QPixmap &preview)
0071 {
0072     KrViewItem *vi = _hash[item];
0073     ASSERT(vi);
0074 
0075     _scheduled.removeOne(vi);
0076 
0077     const FileItem *file = vi->getFileItem();
0078     _parent->addPreview(file, preview);
0079     vi->redraw();
0080 
0081     setProcessedAmount(KJob::Files, processedAmount(KJob::Files) + 1);
0082     emitPercent(processedAmount(KJob::Files), totalAmount(KJob::Files));
0083 }
0084 
0085 void KrPreviewJob::slotStartJob()
0086 {
0087     ASSERT(_job == nullptr);
0088     ASSERT(!_scheduled.isEmpty());
0089 
0090     _hash.clear();
0091     sort();
0092 
0093     int size = _parent->_view->fileIconSize();
0094 
0095     KFileItemList list;
0096     for (int i = 0; i < _scheduled.count() && i < MAX_CHUNK_SIZE; i++) {
0097         KFileItem fi(_scheduled[i]->getFileItem()->getUrl(), nullptr, 0);
0098         list.append(fi);
0099         _hash.insert(fi, _scheduled[i]);
0100     }
0101     QStringList allPlugins = KIO::PreviewJob::availablePlugins();
0102     _job = new KIO::PreviewJob(list, QSize(size, size), &allPlugins);
0103     _job->setOverlayIconAlpha(0);
0104     _job->setOverlayIconSize(0);
0105     _job->setScaleType(KIO::PreviewJob::ScaledAndCached);
0106     connect(_job, &KIO::PreviewJob::gotPreview, this, &KrPreviewJob::slotGotPreview);
0107     connect(_job, &KIO::PreviewJob::failed, this, &KrPreviewJob::slotFailed);
0108     connect(_job, &KIO::PreviewJob::result, this, &KrPreviewJob::slotJobResult);
0109 }
0110 
0111 void KrPreviewJob::slotJobResult(KJob *job)
0112 {
0113     (void)job;
0114 
0115     if (!disconnect(_job, nullptr, this, nullptr))
0116         abort();
0117 
0118     _job = nullptr;
0119     _hash.clear();
0120 
0121     if (_scheduled.isEmpty())
0122         emitResult();
0123     else
0124         _timer.start();
0125 }
0126 
0127 // move currently visible items to beginning of the list
0128 void KrPreviewJob::sort()
0129 {
0130     for (int i = 0, visible_end = 0; i < _scheduled.count(); i++) {
0131         KrViewItem *item = _scheduled[i];
0132         if (_parent->_view->widget()->rect().intersects(item->itemRect())) {
0133             if (i != visible_end)
0134                 _scheduled.move(i, visible_end);
0135             visible_end++;
0136         }
0137     }
0138 }
0139 
0140 bool KrPreviewJob::doKill()
0141 {
0142     _timer.stop();
0143     if (_job) {
0144         if (!disconnect(_job, nullptr, this, nullptr))
0145             abort();
0146         if (!_job->kill())
0147             abort();
0148         _job = nullptr;
0149     }
0150     _hash.clear();
0151     return true;
0152 }