1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qmediastoragelocation_p.h" |
41 | |
42 | #include <QStandardPaths> |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | |
46 | QMediaStorageLocation::QMediaStorageLocation() |
47 | { |
48 | } |
49 | |
50 | void QMediaStorageLocation::addStorageLocation(MediaType type, const QString &location) |
51 | { |
52 | m_customLocations[type].append(t: location); |
53 | } |
54 | |
55 | QDir QMediaStorageLocation::defaultLocation(MediaType type) const |
56 | { |
57 | QStringList dirCandidates; |
58 | |
59 | dirCandidates << m_customLocations.value(akey: type); |
60 | |
61 | switch (type) { |
62 | case Movies: |
63 | dirCandidates << QStandardPaths::writableLocation(type: QStandardPaths::MoviesLocation); |
64 | break; |
65 | case Music: |
66 | dirCandidates << QStandardPaths::writableLocation(type: QStandardPaths::MusicLocation); |
67 | break; |
68 | case Pictures: |
69 | dirCandidates << QStandardPaths::writableLocation(type: QStandardPaths::PicturesLocation); |
70 | default: |
71 | break; |
72 | } |
73 | |
74 | dirCandidates << QDir::homePath(); |
75 | dirCandidates << QDir::currentPath(); |
76 | dirCandidates << QDir::tempPath(); |
77 | |
78 | for (const QString &path : qAsConst(t&: dirCandidates)) { |
79 | if (QFileInfo(path).isWritable()) |
80 | return QDir(path); |
81 | } |
82 | |
83 | return QDir(); |
84 | } |
85 | |
86 | QString QMediaStorageLocation::generateFileName(const QString &requestedName, |
87 | MediaType type, |
88 | const QString &prefix, |
89 | const QString &extension) const |
90 | { |
91 | if (requestedName.isEmpty()) |
92 | return generateFileName(prefix, dir: defaultLocation(type), extension); |
93 | |
94 | QString path = requestedName; |
95 | |
96 | if (QFileInfo(path).isRelative()) |
97 | path = defaultLocation(type).absoluteFilePath(fileName: path); |
98 | |
99 | if (QFileInfo(path).isDir()) |
100 | return generateFileName(prefix, dir: QDir(path), extension); |
101 | |
102 | if (!path.endsWith(s: extension)) |
103 | path.append(s: QString(QLatin1String(".%1" )).arg(a: extension)); |
104 | |
105 | return path; |
106 | } |
107 | |
108 | QString QMediaStorageLocation::generateFileName(const QString &prefix, |
109 | const QDir &dir, |
110 | const QString &extension) const |
111 | { |
112 | QMutexLocker lock(&m_mutex); |
113 | |
114 | const QString lastMediaKey = dir.absolutePath() + QLatin1Char(' ') + prefix + QLatin1Char(' ') + extension; |
115 | qint64 lastMediaIndex = m_lastUsedIndex.value(akey: lastMediaKey, adefaultValue: 0); |
116 | |
117 | if (lastMediaIndex == 0) { |
118 | // first run, find the maximum media number during the fist capture |
119 | const auto list = dir.entryList(nameFilters: QStringList() << QString(QLatin1String("%1*.%2" )).arg(a: prefix).arg(a: extension)); |
120 | for (const QString &fileName : list) { |
121 | const qint64 mediaIndex = fileName.midRef(position: prefix.length(), n: fileName.size() - prefix.length() - extension.length() - 1).toInt(); |
122 | lastMediaIndex = qMax(a: lastMediaIndex, b: mediaIndex); |
123 | } |
124 | } |
125 | |
126 | // don't just rely on cached lastMediaIndex value, |
127 | // someone else may create a file after camera started |
128 | while (true) { |
129 | const QString name = QString(QLatin1String("%1%2.%3" )).arg(a: prefix) |
130 | .arg(a: lastMediaIndex + 1, fieldwidth: 8, base: 10, fillChar: QLatin1Char('0')) |
131 | .arg(a: extension); |
132 | |
133 | const QString path = dir.absoluteFilePath(fileName: name); |
134 | if (!QFileInfo::exists(file: path)) { |
135 | m_lastUsedIndex[lastMediaKey] = lastMediaIndex + 1; |
136 | return path; |
137 | } |
138 | |
139 | lastMediaIndex++; |
140 | } |
141 | |
142 | return QString(); |
143 | } |
144 | |
145 | QT_END_NAMESPACE |
146 | |