File indexing completed on 2024-05-05 04:53:18
0001 /* 0002 SPDX-FileCopyrightText: 2023 Julius Künzel <jk.kdedev@smartlab.uber.space> 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #include "documentcheckertreemodel.h" 0007 0008 #include "abstractmodel/treeitem.hpp" 0009 0010 #include <KColorScheme> 0011 0012 DocumentCheckerTreeModel::DocumentCheckerTreeModel(QObject *parent) 0013 : AbstractTreeModel{parent} 0014 , m_resourceItems() 0015 { 0016 } 0017 0018 Qt::ItemFlags DocumentCheckerTreeModel::flags(const QModelIndex &index) const 0019 { 0020 const auto flags = QAbstractItemModel::flags(index); 0021 return flags; 0022 } 0023 0024 std::shared_ptr<DocumentCheckerTreeModel> DocumentCheckerTreeModel::construct(const std::vector<DocumentChecker::DocumentResource> &items, QObject *parent) 0025 { 0026 std::shared_ptr<DocumentCheckerTreeModel> self(new DocumentCheckerTreeModel(parent)); 0027 QList<QVariant> rootData; 0028 rootData << "Type" 0029 << "Status" 0030 << "Original Path" 0031 << "New Path"; 0032 self->rootItem = TreeItem::construct(rootData, self, true); 0033 0034 // auto createCat = [&](const QString &name) { return self->rootItem->appendChild(QList<QVariant>{name}); }; 0035 // std::vector<std::shared_ptr<TreeItem>> cats{}; 0036 0037 QList<QVariant> data; 0038 data.reserve(3); 0039 for (const auto &item : items) { 0040 if (item.type == DocumentChecker::MissingType::Proxy) { 0041 // Skip proxy as they are shown in a different widget 0042 continue; 0043 } 0044 0045 // we create the data list corresponding to this resource 0046 data.clear(); 0047 data << DocumentChecker::readableNameForMissingType(item.type); 0048 data << DocumentChecker::readableNameForMissingStatus(item.status); 0049 data << item.originalFilePath; 0050 data << item.newFilePath; 0051 0052 std::shared_ptr<TreeItem> newItem = self->rootItem->appendChild(data); 0053 self->m_resourceItems.insert(newItem->getId(), item); 0054 } 0055 0056 return self; 0057 } 0058 0059 void DocumentCheckerTreeModel::removeItem(const QModelIndex &ix) 0060 { 0061 int itemId = int(ix.internalId()); 0062 m_resourceItems[itemId].status = DocumentChecker::MissingStatus::Remove; 0063 Q_EMIT dataChanged(index(ix.row(), 0), index(ix.row(), columnCount() - 1)); 0064 } 0065 0066 void DocumentCheckerTreeModel::slotSearchRecursively(const QString &newpath) 0067 { 0068 QDir searchDir(newpath); 0069 QMap<QModelIndex, QString> fixedMap; 0070 QMapIterator<int, DocumentChecker::DocumentResource> i(m_resourceItems); 0071 int counter = 1; 0072 while (i.hasNext()) { 0073 i.next(); 0074 Q_EMIT searchProgress(counter, m_resourceItems.count()); 0075 counter++; 0076 if (i.value().status != DocumentChecker::MissingStatus::Missing && i.value().status != DocumentChecker::MissingStatus::MissingButProxy) { 0077 continue; 0078 } 0079 QString newPath; 0080 if (i.value().type == DocumentChecker::MissingType::Clip) { 0081 ClipType::ProducerType type = i.value().clipType; 0082 if (type == ClipType::SlideShow) { 0083 // Slideshows cannot be found with hash / size 0084 newPath = DocumentChecker::searchDirRecursively(searchDir, i.value().hash, i.value().originalFilePath); 0085 } else { 0086 newPath = DocumentChecker::searchFileRecursively(searchDir, i.value().fileSize, i.value().hash, i.value().originalFilePath); 0087 } 0088 if (newPath.isEmpty()) { 0089 newPath = DocumentChecker::searchPathRecursively(searchDir, QUrl::fromLocalFile(i.value().originalFilePath).fileName(), type); 0090 } 0091 } else if (i.value().type == DocumentChecker::MissingType::Luma) { 0092 newPath = DocumentChecker::searchLuma(searchDir, i.value().originalFilePath); 0093 0094 } else if (i.value().type == DocumentChecker::MissingType::AssetFile) { 0095 newPath = DocumentChecker::searchPathRecursively(searchDir, QFileInfo(i.value().originalFilePath).fileName()); 0096 0097 } else if (i.value().type == DocumentChecker::MissingType::TitleImage) { 0098 newPath = DocumentChecker::searchPathRecursively(searchDir, QFileInfo(i.value().originalFilePath).fileName()); 0099 } 0100 if (!newPath.isEmpty()) { 0101 fixedMap.insert(getIndexFromId(i.key()), newPath); 0102 } 0103 } 0104 QMapIterator<QModelIndex, QString> j(fixedMap); 0105 while (j.hasNext()) { 0106 j.next(); 0107 setItemsNewFilePath(j.key(), j.value(), DocumentChecker::MissingStatus::Fixed, false); 0108 } 0109 Q_EMIT dataChanged(QModelIndex(), QModelIndex()); 0110 Q_EMIT searchDone(); 0111 } 0112 0113 void DocumentCheckerTreeModel::usePlaceholdersForMissing() 0114 { 0115 QMapIterator<int, DocumentChecker::DocumentResource> i(m_resourceItems); 0116 while (i.hasNext()) { 0117 i.next(); 0118 if (i.value().type == DocumentChecker::MissingType::TitleFont) { 0119 continue; 0120 } 0121 if (i.value().status != DocumentChecker::MissingStatus::Missing && i.value().status != DocumentChecker::MissingStatus::MissingButProxy) { 0122 continue; 0123 } 0124 m_resourceItems[i.key()].status = DocumentChecker::MissingStatus::Placeholder; 0125 } 0126 Q_EMIT dataChanged(QModelIndex(), QModelIndex()); 0127 } 0128 0129 void DocumentCheckerTreeModel::setItemsNewFilePath(const QModelIndex &ix, const QString &url, DocumentChecker::MissingStatus status, bool refresh) 0130 { 0131 int itemId = int(ix.internalId()); 0132 m_resourceItems[itemId].status = status; 0133 m_resourceItems[itemId].newFilePath = url; 0134 if (refresh) { 0135 Q_EMIT dataChanged(index(ix.row(), 0), index(ix.row(), columnCount() - 1)); 0136 } 0137 } 0138 0139 void DocumentCheckerTreeModel::setItemsFileHash(const QModelIndex &index, const QString &hash) 0140 { 0141 m_resourceItems[int(index.internalId())].hash = hash; 0142 } 0143 0144 QVariant DocumentCheckerTreeModel::data(const QModelIndex &index, int role) const 0145 { 0146 if (!index.isValid()) { 0147 qDebug() << "Index is not valid" << index; 0148 return QVariant(); 0149 } 0150 0151 if (m_resourceItems.contains(int(index.internalId()))) { 0152 DocumentChecker::DocumentResource resource = m_resourceItems.value(int(index.internalId())); 0153 0154 if (role == Qt::ForegroundRole) { 0155 if (resource.status == DocumentChecker::MissingStatus::Remove) { 0156 KColorScheme scheme(qApp->palette().currentColorGroup(), KColorScheme::Window); 0157 return scheme.foreground(KColorScheme::InactiveText).color(); 0158 } 0159 } 0160 0161 if (role == Qt::BackgroundRole && resource.status == DocumentChecker::MissingStatus::Missing && index.column() == 1) { 0162 KColorScheme scheme(qApp->palette().currentColorGroup(), KColorScheme::Window); 0163 return scheme.background(KColorScheme::NegativeBackground).color(); 0164 } 0165 0166 if (role == Qt::FontRole) { 0167 if (resource.status == DocumentChecker::MissingStatus::Remove && index.column() == 2) { 0168 QFont f = qApp->font(); 0169 f.setStrikeOut(true); 0170 return f; 0171 } 0172 } 0173 0174 if (role == Qt::ToolTipRole) { 0175 if (!resource.originalFilePath.isEmpty()) { 0176 return resource.originalFilePath; 0177 } 0178 } 0179 0180 if (role == Qt::DecorationRole && index.column() == 1) { 0181 if (resource.status == DocumentChecker::MissingStatus::Missing) { 0182 return QIcon::fromTheme(QStringLiteral("dialog-close")); 0183 } 0184 0185 if (resource.status == DocumentChecker::MissingStatus::Fixed) { 0186 return QIcon::fromTheme(QStringLiteral("dialog-ok")); 0187 } 0188 0189 if (resource.status == DocumentChecker::MissingStatus::Placeholder) { 0190 return QIcon::fromTheme(QStringLiteral("view-preview")); 0191 } 0192 0193 if (resource.status == DocumentChecker::MissingStatus::Reload) { 0194 return QIcon::fromTheme(QStringLiteral("dialog-information")); 0195 } 0196 0197 if (resource.status == DocumentChecker::MissingStatus::Remove) { 0198 return QIcon::fromTheme(QStringLiteral("entry-delete")); 0199 } 0200 0201 return QVariant(); 0202 } 0203 if (role != Qt::DisplayRole) { 0204 return QVariant(); 0205 } 0206 switch (index.column()) { 0207 case 0: 0208 return DocumentChecker::readableNameForMissingType(resource.type); 0209 case 1: 0210 return DocumentChecker::readableNameForMissingStatus(resource.status); 0211 case 2: 0212 return resource.originalFilePath; 0213 case 3: 0214 return resource.newFilePath; 0215 default: 0216 return QVariant(); 0217 } 0218 } 0219 return QVariant(); 0220 } 0221 0222 DocumentChecker::DocumentResource DocumentCheckerTreeModel::getDocumentResource(const QModelIndex &index) 0223 { 0224 return m_resourceItems.value(int(index.internalId())); 0225 }