1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qmediastoragelocation_p.h" |
5 | |
6 | #include <QStandardPaths> |
7 | #include <QUrl> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QDir QMediaStorageLocation::defaultDirectory(QStandardPaths::StandardLocation type) |
12 | { |
13 | QStringList dirCandidates; |
14 | |
15 | #if QT_CONFIG(mmrenderer) |
16 | dirCandidates << QLatin1String("shared/camera" ); |
17 | #endif |
18 | |
19 | dirCandidates << QStandardPaths::writableLocation(type); |
20 | dirCandidates << QStandardPaths::writableLocation(type: QStandardPaths::DocumentsLocation); |
21 | dirCandidates << QDir::homePath(); |
22 | dirCandidates << QDir::currentPath(); |
23 | dirCandidates << QDir::tempPath(); |
24 | |
25 | for (const QString &path : std::as_const(t&: dirCandidates)) { |
26 | QDir dir(path); |
27 | if (dir.exists() && QFileInfo(path).isWritable()) |
28 | return dir; |
29 | } |
30 | |
31 | return QDir(); |
32 | } |
33 | |
34 | static QString generateFileName(const QDir &dir, const QString &prefix, const QString &extension) |
35 | { |
36 | // The extension may be empty if Qt is built without the MIME type feature. |
37 | int lastMediaIndex = 0; |
38 | const QStringView maybeDot = !extension.isEmpty() && !extension.startsWith(c: u'.') ? u"." : u"" ; |
39 | const auto filesList = |
40 | dir.entryList(nameFilters: { QStringView(u"%1*%2%3" ).arg(args: prefix, args: maybeDot, args: extension) }); |
41 | for (const QString &fileName : filesList) { |
42 | const qsizetype mediaIndexSize = |
43 | fileName.size() - prefix.size() - extension.size() - maybeDot.size(); |
44 | const int mediaIndex = QStringView{ fileName }.mid(pos: prefix.size(), n: mediaIndexSize).toInt(); |
45 | lastMediaIndex = qMax(a: lastMediaIndex, b: mediaIndex); |
46 | } |
47 | |
48 | const QString newMediaIndexStr = QStringLiteral("%1" ).arg(a: lastMediaIndex + 1, fieldWidth: 4, base: 10, fillChar: QLatin1Char(u'0')); |
49 | const QString name = prefix + newMediaIndexStr + maybeDot + extension; |
50 | |
51 | return dir.absoluteFilePath(fileName: name); |
52 | } |
53 | |
54 | |
55 | QString QMediaStorageLocation::generateFileName(const QString &requestedName, |
56 | QStandardPaths::StandardLocation type, |
57 | const QString &extension) |
58 | { |
59 | using namespace Qt::StringLiterals; |
60 | |
61 | if (QUrl(requestedName).scheme() == "content"_L1 ) |
62 | return requestedName; |
63 | |
64 | auto prefix = "clip_"_L1 ; |
65 | switch (type) { |
66 | case QStandardPaths::PicturesLocation: prefix = "image_"_L1 ; break; |
67 | case QStandardPaths::MoviesLocation: prefix = "video_"_L1 ; break; |
68 | case QStandardPaths::MusicLocation: prefix = "record_"_L1 ; break; |
69 | default: break; |
70 | } |
71 | |
72 | if (requestedName.isEmpty()) |
73 | return generateFileName(dir: defaultDirectory(type), prefix, extension); |
74 | |
75 | QString path = requestedName; |
76 | |
77 | const QFileInfo fileInfo{ path }; |
78 | |
79 | if (fileInfo.isRelative() && QUrl(path).isRelative()) |
80 | path = defaultDirectory(type).absoluteFilePath(fileName: path); |
81 | |
82 | if (fileInfo.isDir()) |
83 | return generateFileName(dir: QDir(path), prefix, extension); |
84 | |
85 | if (fileInfo.suffix().isEmpty() && !extension.isEmpty()) { |
86 | // File does not have an extension, so add the suggested one |
87 | if (!path.endsWith(c: u'.')) |
88 | path.append(c: u'.'); |
89 | path.append(s: extension); |
90 | } |
91 | return path; |
92 | } |
93 | |
94 | QT_END_NAMESPACE |
95 | |