Warning, file /utilities/krename/src/krenamemodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // SPDX-License-Identifier: GPL-2.0-or-later 0002 // SPDX-FileCopyrightText: 2007 Dominik Seichter <domseichter@web.de> 0003 0004 #include "krenamemodel.h" 0005 #include "threadedlister.h" 0006 0007 #include <QMimeData> 0008 #include <QPixmap> 0009 #include <QApplication> 0010 0011 #include <KLocalizedString> 0012 #include <krun.h> 0013 #include <kio/previewjob.h> 0014 0015 KRenameModel::KRenameModel(KRenameFile::List *vector) 0016 : QAbstractListModel(), 0017 m_vector(vector), 0018 m_preview(false), 0019 m_text(false), 0020 m_maxDots(0), 0021 m_mimeType("text/uri-list"), 0022 m_eSortMode(eSortMode_Unsorted), 0023 m_customSortToken("creationdate;yyyyMMddHHmm"), 0024 m_eCustomSortMode(KRenameTokenSorter::eSimpleSortMode_Ascending) 0025 { 0026 0027 } 0028 0029 KRenameModel::~KRenameModel() 0030 { 0031 0032 } 0033 0034 int KRenameModel::rowCount(const QModelIndex &index) const 0035 { 0036 if (!index.isValid()) { 0037 return m_vector->size(); 0038 } 0039 0040 return 0; 0041 } 0042 0043 QVariant KRenameModel::data(const QModelIndex &index, int role) const 0044 { 0045 if (!index.isValid()) { 0046 return QVariant(); 0047 } 0048 0049 if (index.row() >= m_vector->size()) { 0050 return QVariant(); 0051 } 0052 0053 if (role == Qt::DisplayRole) { 0054 if (!m_preview) { 0055 // Only return path 0056 return m_vector->at(index.row()).toString(); 0057 } else if (m_preview && m_text) { 0058 // Short filename as first line in bold 0059 // Path as second line 0060 const KRenameFile &file = m_vector->at(index.row()); 0061 QString filename = file.srcFilename(); 0062 if (!file.srcExtension().isEmpty()) { 0063 filename = filename + '.' + file.srcExtension(); 0064 } 0065 0066 const QString &prettyUrl = file.toString(); 0067 return "<qt><b>" + filename + "</b><br/>" + 0068 prettyUrl + "</qt>"; 0069 } 0070 } else if (role == Qt::DecorationRole && m_preview) { 0071 return m_vector->at(index.row()).icon(); 0072 } else if (role == Qt::UserRole) { 0073 return m_vector->at(index.row()).toString(); 0074 } 0075 0076 return QVariant(); 0077 } 0078 0079 Qt::ItemFlags KRenameModel::flags(const QModelIndex &index) const 0080 { 0081 if (!index.isValid()) { 0082 return Qt::ItemIsDropEnabled; 0083 } 0084 0085 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDropEnabled; 0086 } 0087 0088 Qt::DropActions KRenameModel::supportedDropActions() const 0089 { 0090 return Qt::CopyAction | Qt::MoveAction; 0091 } 0092 0093 QStringList KRenameModel::mimeTypes() const 0094 { 0095 QStringList types; 0096 types << m_mimeType; 0097 return types; 0098 } 0099 0100 bool KRenameModel::dropMimeData(const QMimeData *data, 0101 Qt::DropAction action, 0102 int, int, 0103 const QModelIndex &) 0104 { 0105 if (action == Qt::IgnoreAction) { 0106 return true; 0107 } 0108 0109 if (!data->hasFormat(m_mimeType)) { 0110 return false; 0111 } 0112 0113 QList<QUrl> dirs; 0114 KRenameFile::List files; 0115 QList<QUrl> urls = data->urls(); 0116 QList<QUrl>::const_iterator it = urls.constBegin(); 0117 0118 QApplication::setOverrideCursor(Qt::BusyCursor); 0119 0120 while (it != urls.constEnd()) { 0121 if ((*it).isValid()) { 0122 KRenameFile file(*it, m_eSplitMode, m_dot); 0123 0124 if (file.isValid() && !file.isDirectory()) { 0125 files.append(file); 0126 } else if (file.isValid() && file.isDirectory()) 0127 // Add directories recursively 0128 { 0129 dirs.append(*it); 0130 } 0131 } 0132 0133 ++it; 0134 } 0135 0136 this->addFiles(files); 0137 if (dirs.count()) { 0138 QList<QUrl>::const_iterator it = dirs.constBegin(); 0139 0140 while (it != dirs.constEnd()) { 0141 ThreadedLister *thl = new ThreadedLister(*it, nullptr, this); 0142 connect(thl, &ThreadedLister::listerDone, 0143 this, &KRenameModel::slotListerDone); 0144 0145 thl->setListDirnamesOnly(false); 0146 thl->setListHidden(false); 0147 thl->setListRecursively(true); 0148 thl->setListDirnames(false); 0149 0150 thl->start(); 0151 0152 ++it; 0153 } 0154 } else { 0155 QApplication::restoreOverrideCursor(); 0156 Q_EMIT filesDropped(); 0157 } 0158 0159 return true; 0160 } 0161 0162 void KRenameModel::slotListerDone(ThreadedLister *lister) 0163 { 0164 // Delete the listener 0165 delete lister; 0166 0167 // restore cursor 0168 QApplication::restoreOverrideCursor(); 0169 0170 Q_EMIT filesDropped(); 0171 } 0172 0173 bool KRenameModel::setData(const QModelIndex &index, 0174 const QVariant &, int role) 0175 { 0176 if (index.isValid() && role == Qt::EditRole) { 0177 0178 //stringList.replace(index.row(), value.toString()); 0179 Q_EMIT dataChanged(index, index); 0180 return true; 0181 } 0182 0183 return false; 0184 } 0185 0186 void KRenameModel::addFiles(const KRenameFile::List &files) 0187 { 0188 if (files.count()) { 0189 int oldMaxDots = m_maxDots; 0190 m_vector->reserve(m_vector->count() + files.count()); 0191 0192 this->beginInsertRows(QModelIndex(), m_vector->size(), m_vector->size() + files.count() - 1); 0193 0194 KRenameFile::List::const_iterator it = files.begin(); 0195 while (it != files.end()) { 0196 m_vector->push_back(*it); 0197 0198 int dots = (*it).dots(); 0199 if (dots > m_maxDots) { 0200 m_maxDots = dots; 0201 } 0202 0203 ++it; 0204 } 0205 this->endInsertRows(); 0206 0207 if (m_maxDots > oldMaxDots) { 0208 Q_EMIT maxDotsChanged(m_maxDots); 0209 } 0210 0211 // Update sorting 0212 this->sortFiles(m_eSortMode, m_customSortToken, m_eCustomSortMode); 0213 0214 // Generate previews if necessary 0215 if (m_preview) { 0216 // Construct a list of KFileItems 0217 // Only do this is necessary, 0218 // as this might create new KFileItems which is slow. 0219 KFileItemList fileItems; 0220 it = files.begin(); 0221 while (it != files.end()) { 0222 fileItems << (*it).fileItem(); 0223 0224 ++it; 0225 } 0226 0227 // TODO: Enable this job, it currently crashes for me 0228 0229 // Start a job to create the real file previews 0230 KIO::PreviewJob *job = KIO::filePreview(fileItems, QSize(KRenameFile::iconSize(), KRenameFile::iconSize())); 0231 0232 connect(job, &KIO::PreviewJob::gotPreview, 0233 this, &KRenameModel::gotPreview); 0234 job->start(); 0235 } 0236 } 0237 } 0238 0239 void KRenameModel::gotPreview(const KFileItem &item, const QPixmap &preview) 0240 { 0241 /* 0242 const KRenameFile* file = 0243 static_cast<const KRenameFile*>(item.extraData(KRenameFile::EXTRA_DATA_KEY)); 0244 */ 0245 0246 KRenameFile *file = nullptr; 0247 // TODO: Find a more optimal "search algorithm" .... 0248 KRenameFile::List::iterator it = m_vector->begin(); 0249 while (it != m_vector->end()) { 0250 if ((*it).srcUrl() == item.url()) { 0251 file = &(*it); 0252 break; 0253 } 0254 0255 ++it; 0256 } 0257 0258 //it = find( m_vector->begin(), m_vector->end(), item ); 0259 if (file != nullptr) { // && file->fileItem() == item ) 0260 file->setIcon(preview); 0261 } 0262 } 0263 0264 void KRenameModel::removeFiles(const QList<int> &remove) 0265 { 0266 int offset = 0; 0267 0268 QList<int> copy(remove); 0269 std::sort(copy.begin(), copy.end()); 0270 0271 QList<int>::const_iterator it = copy.constBegin(); 0272 this->beginRemoveRows(QModelIndex(), *it, copy.back()); 0273 while (it != copy.constEnd()) { 0274 m_vector->erase(m_vector->begin() + *it - offset); 0275 0276 ++offset; 0277 ++it; 0278 } 0279 0280 this->endRemoveRows(); 0281 } 0282 0283 void KRenameModel::sortFiles(ESortMode mode, const QString &customSortToken, KRenameTokenSorter::ESimpleSortMode customSortMode) 0284 { 0285 beginResetModel(); 0286 const QString dateSortToken = "creationdate;yyyyMMddHHmm"; 0287 0288 m_eSortMode = mode; 0289 m_customSortToken = customSortToken; 0290 m_eCustomSortMode = customSortMode; 0291 0292 if (mode == eSortMode_Ascending) { 0293 std::sort(m_vector->begin(), m_vector->end(), ascendingKRenameFileLessThan); 0294 } else if (mode == eSortMode_Descending) { 0295 std::sort(m_vector->begin(), m_vector->end(), descendingKRenameFileLessThan); 0296 } else if (mode == eSortMode_Numeric) { 0297 std::sort(m_vector->begin(), m_vector->end(), numericKRenameFileLessThan); 0298 } else if (mode == eSortMode_Random) { 0299 std::sort(m_vector->begin(), m_vector->end(), randomKRenameFileLessThan); 0300 } else if (mode == eSortMode_AscendingDate) { 0301 KRenameTokenSorter sorter(m_renamer, dateSortToken, *m_vector, 0302 KRenameTokenSorter::eSimpleSortMode_Ascending); 0303 std::sort(m_vector->begin(), m_vector->end(), sorter); 0304 } else if (mode == eSortMode_DescendingDate) { 0305 KRenameTokenSorter sorter(m_renamer, dateSortToken, *m_vector, 0306 KRenameTokenSorter::eSimpleSortMode_Descending); 0307 std::sort(m_vector->begin(), m_vector->end(), sorter); 0308 } else if (mode == eSortMode_Token) { 0309 KRenameTokenSorter sorter(m_renamer, customSortToken, *m_vector, 0310 customSortMode); 0311 std::sort(m_vector->begin(), m_vector->end(), sorter); 0312 } 0313 0314 endResetModel(); 0315 } 0316 0317 void KRenameModel::run(const QModelIndex &index, QWidget *window) const 0318 { 0319 KRenameFile file = m_vector->at(index.row()); 0320 new KRun(file.srcUrl(), window); 0321 } 0322 0323 const QModelIndex KRenameModel::createIndex(int row) const 0324 { 0325 return QAbstractItemModel::createIndex(row, 0); 0326 } 0327 0328 void KRenameModel::moveFilesUp(const QList<int> &files) 0329 { 0330 int index; 0331 KRenameFile tmp; 0332 0333 QList<int> copy(files); 0334 std::sort(copy.begin(), copy.end()); 0335 0336 beginResetModel(); 0337 QList<int>::const_iterator it = copy.constBegin(); 0338 while (it != copy.constEnd()) { 0339 index = *it; 0340 if (index <= 0) { // cannot swap top item 0341 ++it; 0342 continue; 0343 } 0344 0345 // swap items 0346 tmp = m_vector->at(index); 0347 (*m_vector)[index] = KRenameFile(m_vector->at(index - 1)); 0348 (*m_vector)[index - 1] = tmp; 0349 0350 ++it; 0351 } 0352 0353 endResetModel(); 0354 } 0355 0356 void KRenameModel::moveFilesDown(const QList<int> &files) 0357 { 0358 int index; 0359 KRenameFile tmp; 0360 0361 QList<int> copy(files); 0362 // sort the list in reverse order 0363 std::sort(copy.begin(), copy.end(), std::greater<int>()); 0364 0365 beginResetModel(); 0366 QList<int>::const_iterator it = copy.constBegin(); 0367 while (it != copy.constEnd()) { 0368 index = *it; 0369 if (index + 1 >= m_vector->size()) { // cannot swap bottom item 0370 ++it; 0371 continue; 0372 } 0373 0374 // swap items 0375 tmp = m_vector->at(index); 0376 (*m_vector)[index] = KRenameFile(m_vector->at(index + 1)); 0377 (*m_vector)[index + 1] = tmp; 0378 0379 ++it; 0380 } 0381 0382 endResetModel(); 0383 } 0384 0385 ////////////////////////////////////////////////////////////// 0386 // Preview model starts below 0387 ////////////////////////////////////////////////////////////// 0388 KRenamePreviewModel::KRenamePreviewModel(KRenameFile::List *vector) 0389 : m_vector(vector) 0390 { 0391 0392 } 0393 0394 KRenamePreviewModel::~KRenamePreviewModel() 0395 { 0396 0397 } 0398 0399 int KRenamePreviewModel::rowCount(const QModelIndex &parent) const 0400 { 0401 if (!parent.isValid()) { 0402 return m_vector->size(); 0403 } 0404 0405 return 0; 0406 } 0407 0408 int KRenamePreviewModel::columnCount(const QModelIndex &) const 0409 { 0410 return 2; 0411 } 0412 0413 QVariant KRenamePreviewModel::headerData(int section, Qt::Orientation orientation, int role) const 0414 { 0415 if (orientation != Qt::Horizontal || section > 1 || role != Qt::DisplayRole) { 0416 return QVariant(); 0417 } 0418 0419 return (section == 0) ? i18n("Origin") : i18n("Renamed"); 0420 } 0421 0422 QVariant KRenamePreviewModel::data(const QModelIndex &index, int role) const 0423 { 0424 if (!index.isValid()) { 0425 return QVariant(); 0426 } 0427 0428 if (index.row() >= m_vector->size()) { 0429 return QVariant(); 0430 } 0431 0432 if (index.column() >= 2) { 0433 return QVariant(); 0434 } 0435 0436 if (role == Qt::DisplayRole) { 0437 const KRenameFile &file = m_vector->at(index.row()); 0438 QString filename; 0439 QString extension; 0440 QString manual; 0441 0442 if (index.column()) { 0443 manual = file.manualChanges(); 0444 if (manual.isNull()) { 0445 filename = file.dstFilename(); 0446 extension = file.dstExtension(); 0447 } else { 0448 filename = manual; 0449 } 0450 } else { 0451 filename = file.srcFilename(); 0452 extension = file.srcExtension(); 0453 } 0454 0455 if (!extension.isEmpty()) { 0456 filename += '.'; 0457 filename += extension; 0458 } 0459 0460 if (file.isDirectory()) { 0461 filename = (index.column() ? file.dstDirectory() : file.srcDirectory()) + '/' + filename; 0462 } 0463 0464 return filename; 0465 } else if (role == Qt::ForegroundRole) { 0466 const KRenameFile &file = m_vector->at(index.row()); 0467 if (!file.manualChanges().isNull()) { 0468 return QVariant(QColor(Qt::blue)); 0469 } 0470 } 0471 /* 0472 Icons are to large, so this is disabled 0473 else if( role == Qt::DecorationRole && index.column() == 0 ) 0474 { 0475 return m_vector->at(index.row()).icon(); 0476 } 0477 */ 0478 0479 return QVariant(); 0480 0481 } 0482 0483 QModelIndex KRenamePreviewModel::parent(const QModelIndex &) const 0484 { 0485 return QModelIndex(); 0486 } 0487 0488 QModelIndex KRenamePreviewModel::sibling(int, int, const QModelIndex &) const 0489 { 0490 return QModelIndex(); 0491 } 0492 0493 void KRenamePreviewModel::refresh() 0494 { 0495 beginResetModel(); 0496 endResetModel(); 0497 }