/*
SPDX-FileCopyrightText: 2007 Paolo Capriotti
SPDX-FileCopyrightText: 2022 Fushan Wen
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "imagelistmodel.h"
#include
#include
#include
#include
#include
#include
#include "../finder/imagefinder.h"
#include "../finder/suffixcheck.h"
ImageListModel::ImageListModel(const QSize &targetSize, QObject *parent)
: AbstractImageListModel(targetSize, parent)
{
}
int ImageListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_data.size();
}
QVariant ImageListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
const int row = index.row();
switch (role) {
case Qt::DisplayRole:
return QFileInfo(m_data.at(row)).completeBaseName();
case ScreenshotRole: {
QPixmap *cachedPreview = m_imageCache.object({m_data.at(row)});
if (cachedPreview) {
return *cachedPreview;
}
asyncGetPreview({m_data.at(row)}, QPersistentModelIndex(index));
return QVariant();
}
case AuthorRole:
// No author for an image file?
return QString();
case ResolutionRole: {
QSize *size = m_imageSizeCache.object(m_data.at(row));
if (size && size->isValid()) {
return QStringLiteral("%1x%2").arg(size->width()).arg(size->height());
}
asyncGetImageSize(m_data.at(row), QPersistentModelIndex(index));
return QString();
}
case PathRole:
return QUrl::fromLocalFile(m_data.at(row));
case PackageNameRole:
return m_data.at(row);
case RemovableRole: {
const QString &path = m_data.at(row);
return path.startsWith(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/wallpapers/"))
|| m_removableWallpapers.contains(path);
}
case PendingDeletionRole:
return m_pendingDeletion.value(m_data.at(row), false);
}
Q_UNREACHABLE();
}
bool ImageListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid()) {
return false;
}
if (role == PendingDeletionRole) {
m_pendingDeletion[m_data.at(index.row())] = value.toBool();
Q_EMIT dataChanged(index, index, {PendingDeletionRole});
return true;
}
return false;
}
int ImageListModel::indexOf(const QString &_path) const
{
QString path = _path;
if (path.startsWith(QLatin1String("file://"))) {
path.remove(0, 7);
}
const auto it = std::find_if(m_data.cbegin(), m_data.cend(), [&path](const QString &p) {
return path == p;
});
if (it == m_data.cend()) {
return -1;
}
return std::distance(m_data.cbegin(), it);
}
void ImageListModel::load(const QStringList &customPaths)
{
if (m_loading || customPaths.empty()) {
return;
}
m_customPaths = customPaths;
m_customPaths.removeDuplicates();
ImageFinder *finder = new ImageFinder(m_customPaths);
connect(finder, &ImageFinder::imageFound, this, &ImageListModel::slotHandleImageFound);
QThreadPool::globalInstance()->start(finder);
m_loading = true;
}
void ImageListModel::slotHandleImageFound(const QStringList &paths)
{
beginResetModel();
m_data = paths;
m_imageCache.clear();
m_imageSizeCache.clear();
endResetModel();
m_loading = false;
Q_EMIT loaded(this);
}
QStringList ImageListModel::addBackground(const QString &path)
{
if (path.isEmpty() || !QFile::exists(path) || m_data.contains(path)) {
return {};
}
if (QFileInfo info(path); info.isHidden() || !isAcceptableSuffix(info.suffix())) {
// Skip hidden files or Format not supported
return {};
}
beginInsertRows(QModelIndex(), 0, 0);
m_data.prepend(path);
m_removableWallpapers.prepend(path);
endInsertRows();
return {path};
}
QStringList ImageListModel::removeBackground(const QString &path)
{
QStringList results;
if (path.isEmpty()) {
return results;
}
const int idx = indexOf(path);
if (idx < 0) {
return results;
}
beginRemoveRows(QModelIndex(), idx, idx);
m_pendingDeletion.remove(m_data.at(idx));
m_removableWallpapers.removeOne(m_data.at(idx));
results.append(m_data.takeAt(idx));
// Remove local wallpaper
if (path.startsWith(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/wallpapers/"))) {
QFile f(path);
if (f.exists()) {
f.remove();
}
}
endRemoveRows();
return results;
}