1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the QtCore module of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU Lesser General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
22 | ** packaging of this file. Please review the following information to |
23 | ** ensure the GNU Lesser General Public License version 3 requirements |
24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
25 | ** |
26 | ** GNU General Public License Usage |
27 | ** Alternatively, this file may be used under the terms of the GNU |
28 | ** General Public License version 2.0 or (at your option) the GNU General |
29 | ** Public license version 3 or any later version approved by the KDE Free |
30 | ** Qt Foundation. The licenses are as published by the Free Software |
31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
32 | ** included in the packaging of this file. Please review the following |
33 | ** information to ensure the GNU General Public License requirements will |
34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
36 | ** |
37 | ** $QT_END_LICENSE$ |
38 | ** |
39 | ****************************************************************************/ |
40 | |
41 | #include "qmimetype.h" |
42 | |
43 | #include "qmimetype_p.h" |
44 | #include "qmimedatabase_p.h" |
45 | #include "qmimeprovider_p.h" |
46 | |
47 | #include "qmimeglobpattern_p.h" |
48 | |
49 | #include <QtCore/QDebug> |
50 | #include <QtCore/QLocale> |
51 | #include <QtCore/QHashFunctions> |
52 | |
53 | #include <memory> |
54 | |
55 | QT_BEGIN_NAMESPACE |
56 | |
57 | QMimeTypePrivate::QMimeTypePrivate() |
58 | : loaded(false), fromCache(false) |
59 | {} |
60 | |
61 | QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other) |
62 | : loaded(other.d->loaded), |
63 | name(other.d->name), |
64 | localeComments(other.d->localeComments), |
65 | genericIconName(other.d->genericIconName), |
66 | iconName(other.d->iconName), |
67 | globPatterns(other.d->globPatterns) |
68 | {} |
69 | |
70 | void QMimeTypePrivate::clear() |
71 | { |
72 | name.clear(); |
73 | localeComments.clear(); |
74 | genericIconName.clear(); |
75 | iconName.clear(); |
76 | globPatterns.clear(); |
77 | } |
78 | |
79 | void QMimeTypePrivate::addGlobPattern(const QString &pattern) |
80 | { |
81 | globPatterns.append(t: pattern); |
82 | } |
83 | |
84 | /*! |
85 | \class QMimeType |
86 | \inmodule QtCore |
87 | \ingroup shared |
88 | \brief The QMimeType class describes types of file or data, represented by a MIME type string. |
89 | |
90 | \since 5.0 |
91 | |
92 | For instance a file named "readme.txt" has the MIME type "text/plain". |
93 | The MIME type can be determined from the file name, or from the file |
94 | contents, or from both. MIME type determination can also be done on |
95 | buffers of data not coming from files. |
96 | |
97 | Determining the MIME type of a file can be useful to make sure your |
98 | application supports it. It is also useful in file-manager-like applications |
99 | or widgets, in order to display an appropriate \l {QMimeType::iconName}{icon} for the file, or even |
100 | the descriptive \l {QMimeType::comment()}{comment} in detailed views. |
101 | |
102 | To check if a file has the expected MIME type, you should use inherits() |
103 | rather than a simple string comparison based on the name(). This is because |
104 | MIME types can inherit from each other: for instance a C source file is |
105 | a specific type of plain text file, so text/x-csrc inherits text/plain. |
106 | |
107 | \sa QMimeDatabase, {MIME Type Browser Example} |
108 | */ |
109 | |
110 | /*! |
111 | \fn QMimeType &QMimeType::operator=(QMimeType &&other) |
112 | |
113 | Move-assigns \a other to this QMimeType instance. |
114 | |
115 | \since 5.2 |
116 | */ |
117 | |
118 | /*! |
119 | \fn QMimeType::QMimeType(); |
120 | Constructs this QMimeType object initialized with default property values that indicate an invalid MIME type. |
121 | */ |
122 | QMimeType::QMimeType() : |
123 | d(new QMimeTypePrivate()) |
124 | { |
125 | } |
126 | |
127 | /*! |
128 | \fn QMimeType::QMimeType(const QMimeType &other); |
129 | Constructs this QMimeType object as a copy of \a other. |
130 | */ |
131 | QMimeType::QMimeType(const QMimeType &other) : |
132 | d(other.d) |
133 | { |
134 | } |
135 | |
136 | /*! |
137 | \fn QMimeType &QMimeType::operator=(const QMimeType &other); |
138 | Assigns the data of \a other to this QMimeType object, and returns a reference to this object. |
139 | */ |
140 | QMimeType &QMimeType::operator=(const QMimeType &other) |
141 | { |
142 | if (d != other.d) |
143 | d = other.d; |
144 | return *this; |
145 | } |
146 | |
147 | /*! |
148 | \fn QMimeType::QMimeType(const QMimeTypePrivate &dd); |
149 | Assigns the data of the QMimeTypePrivate \a dd to this QMimeType object, and returns a reference to this object. |
150 | \internal |
151 | */ |
152 | QMimeType::QMimeType(const QMimeTypePrivate &dd) : |
153 | d(new QMimeTypePrivate(dd)) |
154 | { |
155 | } |
156 | |
157 | /*! |
158 | \fn void QMimeType::swap(QMimeType &other); |
159 | Swaps QMimeType \a other with this QMimeType object. |
160 | |
161 | This operation is very fast and never fails. |
162 | |
163 | The swap() method helps with the implementation of assignment |
164 | operators in an exception-safe way. For more information consult |
165 | \l {http://en.wikibooks.org/wiki/More_C++_Idioms/Copy-and-swap} |
166 | {More C++ Idioms - Copy-and-swap}. |
167 | */ |
168 | |
169 | /*! |
170 | \fn QMimeType::~QMimeType(); |
171 | Destroys the QMimeType object, and releases the d pointer. |
172 | */ |
173 | QMimeType::~QMimeType() |
174 | { |
175 | } |
176 | |
177 | /*! |
178 | \fn bool QMimeType::operator==(const QMimeType &other) const; |
179 | Returns \c true if \a other equals this QMimeType object, otherwise returns \c false. |
180 | The name is the unique identifier for a mimetype, so two mimetypes with |
181 | the same name, are equal. |
182 | */ |
183 | bool QMimeType::operator==(const QMimeType &other) const |
184 | { |
185 | return d == other.d || d->name == other.d->name; |
186 | } |
187 | |
188 | /*! |
189 | \since 5.6 |
190 | \relates QMimeType |
191 | |
192 | Returns the hash value for \a key, using |
193 | \a seed to seed the calculation. |
194 | */ |
195 | uint qHash(const QMimeType &key, uint seed) noexcept |
196 | { |
197 | return qHash(key: key.d->name, seed); |
198 | } |
199 | |
200 | /*! |
201 | \fn bool QMimeType::operator!=(const QMimeType &other) const; |
202 | Returns \c true if \a other does not equal this QMimeType object, otherwise returns \c false. |
203 | */ |
204 | |
205 | /*! |
206 | \property QMimeType::valid |
207 | \brief \c true if the QMimeType object contains valid data, \c false otherwise |
208 | |
209 | A valid MIME type has a non-empty name(). |
210 | The invalid MIME type is the default-constructed QMimeType. |
211 | |
212 | While this property was introduced in 5.10, the |
213 | corresponding accessor method has always been there. |
214 | */ |
215 | bool QMimeType::isValid() const |
216 | { |
217 | return !d->name.isEmpty(); |
218 | } |
219 | |
220 | /*! |
221 | \property QMimeType::isDefault |
222 | \brief \c true if this MIME type is the default MIME type which |
223 | applies to all files: application/octet-stream. |
224 | |
225 | While this property was introduced in 5.10, the |
226 | corresponding accessor method has always been there. |
227 | */ |
228 | bool QMimeType::isDefault() const |
229 | { |
230 | return d->name == QMimeDatabasePrivate::instance()->defaultMimeType(); |
231 | } |
232 | |
233 | /*! |
234 | \property QMimeType::name |
235 | \brief the name of the MIME type |
236 | |
237 | While this property was introduced in 5.10, the |
238 | corresponding accessor method has always been there. |
239 | */ |
240 | QString QMimeType::name() const |
241 | { |
242 | return d->name; |
243 | } |
244 | |
245 | /*! |
246 | \property QMimeType::comment |
247 | \brief the description of the MIME type to be displayed on user interfaces |
248 | |
249 | The default language (QLocale().name()) is used to select the appropriate translation. |
250 | |
251 | While this property was introduced in 5.10, the |
252 | corresponding accessor method has always been there. |
253 | */ |
254 | QString QMimeType::comment() const |
255 | { |
256 | QMimeDatabasePrivate::instance()->loadMimeTypePrivate(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
257 | |
258 | QStringList languageList; |
259 | languageList << QLocale().name(); |
260 | languageList << QLocale().uiLanguages(); |
261 | languageList << QLatin1String("default"); // use the default locale if possible. |
262 | for (const QString &language : qAsConst(t&: languageList)) { |
263 | const QString lang = language == QLatin1String("C") ? QLatin1String( "en_US") : language; |
264 | const QString comm = d->localeComments.value(akey: lang); |
265 | if (!comm.isEmpty()) |
266 | return comm; |
267 | const int pos = lang.indexOf(c: QLatin1Char('_')); |
268 | if (pos != -1) { |
269 | // "pt_BR" not found? try just "pt" |
270 | const QString shortLang = lang.left(n: pos); |
271 | const QString commShort = d->localeComments.value(akey: shortLang); |
272 | if (!commShort.isEmpty()) |
273 | return commShort; |
274 | } |
275 | } |
276 | |
277 | // Use the mimetype name as fallback |
278 | return d->name; |
279 | } |
280 | |
281 | /*! |
282 | \property QMimeType::genericIconName |
283 | \brief the file name of a generic icon that represents the MIME type |
284 | |
285 | This should be used if the icon returned by iconName() cannot be found on |
286 | the system. It is used for categories of similar types (like spreadsheets |
287 | or archives) that can use a common icon. |
288 | The freedesktop.org Icon Naming Specification lists a set of such icon names. |
289 | |
290 | The icon name can be given to QIcon::fromTheme() in order to load the icon. |
291 | |
292 | While this property was introduced in 5.10, the |
293 | corresponding accessor method has always been there. |
294 | */ |
295 | QString QMimeType::genericIconName() const |
296 | { |
297 | QMimeDatabasePrivate::instance()->loadGenericIcon(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
298 | if (d->genericIconName.isEmpty()) { |
299 | // From the spec: |
300 | // If the generic icon name is empty (not specified by the mimetype definition) |
301 | // then the mimetype is used to generate the generic icon by using the top-level |
302 | // media type (e.g. "video" in "video/ogg") and appending "-x-generic" |
303 | // (i.e. "video-x-generic" in the previous example). |
304 | const QString group = name(); |
305 | QStringRef groupRef(&group); |
306 | const int slashindex = groupRef.indexOf(ch: QLatin1Char('/')); |
307 | if (slashindex != -1) |
308 | groupRef = groupRef.left(n: slashindex); |
309 | return groupRef + QLatin1String("-x-generic"); |
310 | } |
311 | return d->genericIconName; |
312 | } |
313 | |
314 | static QString make_default_icon_name_from_mimetype_name(QString iconName) |
315 | { |
316 | const int slashindex = iconName.indexOf(c: QLatin1Char('/')); |
317 | if (slashindex != -1) |
318 | iconName[slashindex] = QLatin1Char('-'); |
319 | return iconName; |
320 | } |
321 | |
322 | /*! |
323 | \property QMimeType::iconName |
324 | \brief the file name of an icon image that represents the MIME type |
325 | |
326 | The icon name can be given to QIcon::fromTheme() in order to load the icon. |
327 | |
328 | While this property was introduced in 5.10, the |
329 | corresponding accessor method has always been there. |
330 | */ |
331 | QString QMimeType::iconName() const |
332 | { |
333 | QMimeDatabasePrivate::instance()->loadIcon(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
334 | if (d->iconName.isEmpty()) { |
335 | return make_default_icon_name_from_mimetype_name(iconName: name()); |
336 | } |
337 | return d->iconName; |
338 | } |
339 | |
340 | /*! |
341 | \property QMimeType::globPatterns |
342 | \brief the list of glob matching patterns |
343 | |
344 | While this property was introduced in 5.10, the |
345 | corresponding accessor method has always been there. |
346 | */ |
347 | QStringList QMimeType::globPatterns() const |
348 | { |
349 | QMimeDatabasePrivate::instance()->loadMimeTypePrivate(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
350 | return d->globPatterns; |
351 | } |
352 | |
353 | /*! |
354 | \property QMimeType::parentMimeTypes |
355 | \brief the names of parent MIME types |
356 | |
357 | A type is a subclass of another type if any instance of the first type is |
358 | also an instance of the second. For example, all image/svg+xml files are also |
359 | text/xml, text/plain and application/octet-stream files. Subclassing is about |
360 | the format, rather than the category of the data (for example, there is no |
361 | 'generic spreadsheet' class that all spreadsheets inherit from). |
362 | Conversely, the parent mimetype of image/svg+xml is text/xml. |
363 | |
364 | A mimetype can have multiple parents. For instance application/x-perl |
365 | has two parents: application/x-executable and text/plain. This makes |
366 | it possible to both execute perl scripts, and to open them in text editors. |
367 | |
368 | While this property was introduced in 5.10, the |
369 | corresponding accessor method has always been there. |
370 | */ |
371 | QStringList QMimeType::parentMimeTypes() const |
372 | { |
373 | return QMimeDatabasePrivate::instance()->mimeParents(mimeName: d->name); |
374 | } |
375 | |
376 | static void collectParentMimeTypes(const QString &mime, QStringList &allParents) |
377 | { |
378 | const QStringList parents = QMimeDatabasePrivate::instance()->mimeParents(mimeName: mime); |
379 | for (const QString &parent : parents) { |
380 | // I would use QSet, but since order matters I better not |
381 | if (!allParents.contains(str: parent)) |
382 | allParents.append(t: parent); |
383 | } |
384 | // We want a breadth-first search, so that the least-specific parent (octet-stream) is last |
385 | // This means iterating twice, unfortunately. |
386 | for (const QString &parent : parents) |
387 | collectParentMimeTypes(mime: parent, allParents); |
388 | } |
389 | |
390 | /*! |
391 | \property QMimeType::allAncestors |
392 | \brief the names of direct and indirect parent MIME types |
393 | |
394 | Return all the parent mimetypes of this mimetype, direct and indirect. |
395 | This includes the parent(s) of its parent(s), etc. |
396 | |
397 | For instance, for image/svg+xml the list would be: |
398 | application/xml, text/plain, application/octet-stream. |
399 | |
400 | Note that application/octet-stream is the ultimate parent for all types |
401 | of files (but not directories). |
402 | |
403 | While this property was introduced in 5.10, the |
404 | corresponding accessor method has always been there. |
405 | */ |
406 | QStringList QMimeType::allAncestors() const |
407 | { |
408 | QStringList allParents; |
409 | collectParentMimeTypes(mime: d->name, allParents); |
410 | return allParents; |
411 | } |
412 | |
413 | /*! |
414 | \property QMimeType::aliases |
415 | \brief the list of aliases of this mimetype |
416 | |
417 | For instance, for text/csv, the returned list would be: |
418 | text/x-csv, text/x-comma-separated-values. |
419 | |
420 | Note that all QMimeType instances refer to proper mimetypes, |
421 | never to aliases directly. |
422 | |
423 | The order of the aliases in the list is undefined. |
424 | |
425 | While this property was introduced in 5.10, the |
426 | corresponding accessor method has always been there. |
427 | */ |
428 | QStringList QMimeType::aliases() const |
429 | { |
430 | return QMimeDatabasePrivate::instance()->listAliases(mimeName: d->name); |
431 | } |
432 | |
433 | /*! |
434 | \property QMimeType::suffixes |
435 | \brief the known suffixes for the MIME type |
436 | |
437 | No leading dot is included, so for instance this would return "jpg", "jpeg" for image/jpeg. |
438 | |
439 | While this property was introduced in 5.10, the |
440 | corresponding accessor method has always been there. |
441 | */ |
442 | QStringList QMimeType::suffixes() const |
443 | { |
444 | QMimeDatabasePrivate::instance()->loadMimeTypePrivate(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
445 | |
446 | QStringList result; |
447 | for (const QString &pattern : qAsConst(t&: d->globPatterns)) { |
448 | // Not a simple suffix if it looks like: README or *. or *.* or *.JP*G or *.JP? |
449 | if (pattern.startsWith(s: QLatin1String("*.")) && |
450 | pattern.length() > 2 && |
451 | pattern.indexOf(c: QLatin1Char('*'), from: 2) < 0 && pattern.indexOf(c: QLatin1Char('?'), from: 2) < 0) { |
452 | const QString suffix = pattern.mid(position: 2); |
453 | result.append(t: suffix); |
454 | } |
455 | } |
456 | |
457 | return result; |
458 | } |
459 | |
460 | /*! |
461 | \property QMimeType::preferredSuffix |
462 | \brief the preferred suffix for the MIME type |
463 | |
464 | No leading dot is included, so for instance this would return "pdf" for application/pdf. |
465 | The return value can be empty, for mime types which do not have any suffixes associated. |
466 | |
467 | While this property was introduced in 5.10, the |
468 | corresponding accessor method has always been there. |
469 | */ |
470 | QString QMimeType::preferredSuffix() const |
471 | { |
472 | if (isDefault()) // workaround for unwanted *.bin suffix for octet-stream, https://bugs.freedesktop.org/show_bug.cgi?id=101667, fixed upstream in 1.10 |
473 | return QString(); |
474 | const QStringList suffixList = suffixes(); |
475 | return suffixList.isEmpty() ? QString() : suffixList.at(i: 0); |
476 | } |
477 | |
478 | /*! |
479 | \property QMimeType::filterString |
480 | \brief a filter string usable for a file dialog |
481 | |
482 | While this property was introduced in 5.10, the |
483 | corresponding accessor method has always been there. |
484 | */ |
485 | QString QMimeType::filterString() const |
486 | { |
487 | QMimeDatabasePrivate::instance()->loadMimeTypePrivate(mimePrivate&: const_cast<QMimeTypePrivate&>(*d)); |
488 | QString filter; |
489 | |
490 | if (!d->globPatterns.empty()) { |
491 | filter += comment() + QLatin1String(" ("); |
492 | for (int i = 0; i < d->globPatterns.size(); ++i) { |
493 | if (i != 0) |
494 | filter += QLatin1Char(' '); |
495 | filter += d->globPatterns.at(i); |
496 | } |
497 | filter += QLatin1Char(')'); |
498 | } |
499 | |
500 | return filter; |
501 | } |
502 | |
503 | /*! |
504 | \fn bool QMimeType::inherits(const QString &mimeTypeName) const; |
505 | Returns \c true if this mimetype is \a mimeTypeName, |
506 | or inherits \a mimeTypeName (see parentMimeTypes()), |
507 | or \a mimeTypeName is an alias for this mimetype. |
508 | |
509 | This method has been made invokable from QML since 5.10. |
510 | */ |
511 | bool QMimeType::inherits(const QString &mimeTypeName) const |
512 | { |
513 | if (d->name == mimeTypeName) |
514 | return true; |
515 | return QMimeDatabasePrivate::instance()->mimeInherits(mime: d->name, parent: mimeTypeName); |
516 | } |
517 | |
518 | #ifndef QT_NO_DEBUG_STREAM |
519 | QDebug operator<<(QDebug debug, const QMimeType &mime) |
520 | { |
521 | QDebugStateSaver saver(debug); |
522 | if (!mime.isValid()) { |
523 | debug.nospace() << "QMimeType(invalid)"; |
524 | } else { |
525 | debug.nospace() << "QMimeType("<< mime.name() << ")"; |
526 | } |
527 | return debug; |
528 | } |
529 | #endif |
530 | |
531 | QT_END_NAMESPACE |
532 | |
533 | #include "moc_qmimetype.cpp" |
534 |
Definitions
- QMimeTypePrivate
- QMimeTypePrivate
- clear
- addGlobPattern
- QMimeType
- QMimeType
- operator=
- QMimeType
- ~QMimeType
- operator==
- qHash
- isValid
- isDefault
- name
- comment
- genericIconName
- make_default_icon_name_from_mimetype_name
- iconName
- globPatterns
- parentMimeTypes
- collectParentMimeTypes
- allAncestors
- aliases
- suffixes
- preferredSuffix
- filterString
- inherits
Learn to use CMake with our Intro Training
Find out more