1 /*
2     This file is part of the KDE libraries
3 
4     SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
5     SPDX-FileCopyrightText: 2021 Alexander Lohnau <alexander.lohnau@gmx.de>
6 
7     SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "kfileutils.h"
11 
12 #include <QDirIterator>
13 #include <QFileInfo>
14 #include <QMimeDatabase>
15 #include <QRegularExpression>
16 
17 #include <set>
18 
makeSuggestedName(const QString & oldName)19 QString KFileUtils::makeSuggestedName(const QString &oldName)
20 {
21     QString basename;
22 
23     // Extract the original file extension from the filename
24     QMimeDatabase db;
25     QString nameSuffix = db.suffixForFileName(oldName);
26 
27     if (oldName.lastIndexOf(QLatin1Char('.')) == 0) {
28         basename = QStringLiteral(".");
29         nameSuffix = oldName;
30     } else if (nameSuffix.isEmpty()) {
31         const int lastDot = oldName.lastIndexOf(QLatin1Char('.'));
32         if (lastDot == -1) {
33             basename = oldName;
34         } else {
35             basename = oldName.left(lastDot);
36             nameSuffix = oldName.mid(lastDot);
37         }
38     } else {
39         nameSuffix.prepend(QLatin1Char('.'));
40         basename = oldName.left(oldName.length() - nameSuffix.length());
41     }
42 
43     // check if (number) exists at the end of the oldName and increment that number
44     const QRegularExpression re(QStringLiteral("\\((\\d+)\\)"));
45     QRegularExpressionMatch rmatch;
46     oldName.lastIndexOf(re, -1, &rmatch);
47     if (rmatch.hasMatch()) {
48         const int currentNum = rmatch.captured(1).toInt();
49         const QString number = QString::number(currentNum + 1);
50         basename.replace(rmatch.capturedStart(1), rmatch.capturedLength(1), number);
51     } else {
52         // number does not exist, so just append " (1)" to filename
53         basename += QLatin1String(" (1)");
54     }
55 
56     return basename + nameSuffix;
57 }
58 
suggestName(const QUrl & baseURL,const QString & oldName)59 QString KFileUtils::suggestName(const QUrl &baseURL, const QString &oldName)
60 {
61     QString suggestedName = makeSuggestedName(oldName);
62 
63     if (baseURL.isLocalFile()) {
64         const QString basePath = baseURL.toLocalFile() + QLatin1Char('/');
65         while (QFileInfo::exists(basePath + suggestedName)) {
66             suggestedName = makeSuggestedName(suggestedName);
67         }
68     }
69 
70     return suggestedName;
71 }
72 
findAllUniqueFiles(const QStringList & dirs,const QStringList & nameFilters)73 QStringList KFileUtils::findAllUniqueFiles(const QStringList &dirs, const QStringList &nameFilters)
74 {
75     QStringList foundFilePaths;
76     std::set<QString> foundFileNames;
77     for (const QString &dir : dirs) {
78         QDirIterator it(dir, nameFilters, QDir::Files);
79         while (it.hasNext()) {
80             it.next();
81             const auto [iter, isFirstSeen] = foundFileNames.insert(it.fileName());
82             if (isFirstSeen) {
83                 foundFilePaths << it.filePath();
84             }
85         }
86     }
87     return foundFilePaths;
88 }
89