1 /*
2  * Copyright (c) 2016 Boudewijn Rempt <boud@valdyas.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include "KisMimeDatabase.h"
20 
21 #include <QMimeDatabase>
22 #include <QMimeType>
23 #include <QFileInfo>
24 #include <KritaPluginDebug.h>
25 
26 #include <klocalizedstring.h>
27 
28 QList<KisMimeDatabase::KisMimeType> KisMimeDatabase::s_mimeDatabase;
29 
sanitizeSuffix(const QString & suffix)30 static QString sanitizeSuffix(const QString &suffix)
31 {
32     return suffix.split(QLatin1Char(' ')).first();
33 }
34 
mimeTypeForFile(const QString & file,bool checkExistingFiles)35 QString KisMimeDatabase::mimeTypeForFile(const QString &file, bool checkExistingFiles)
36 {
37     fillMimeData();
38 
39     QFileInfo fi(file);
40     QString suffix = fi.suffix().toLower();
41 
42 #ifdef Q_OS_ANDROID
43     // HACK: on Android we can save as .kra with no extension or as something like:
44     // "untitled.kra (1)", (1) being added by the SAF because we can't overwrite the duplicate.
45     // So, we need to be able to remove that number and get extension. If there is no extension,
46     // perhaps try "kra"
47     suffix = sanitizeSuffix(suffix);
48     if (suffix.isEmpty())
49         suffix = "kra";
50 #endif
51 
52     Q_FOREACH(const KisMimeDatabase::KisMimeType &mimeType, s_mimeDatabase) {
53         if (mimeType.suffixes.contains(suffix)) {
54             debugPlugin << "mimeTypeForFile(). KisMimeDatabase returned" << mimeType.mimeType << "for" << file;
55             return mimeType.mimeType;
56         }
57     }
58 
59     QMimeDatabase db;
60     QMimeType mime;
61     if (checkExistingFiles && fi.size() > 0) {
62         mime = db.mimeTypeForFile(file, QMimeDatabase::MatchContent);
63         if (mime.name() != "application/octet-stream" && mime.name() != "application/zip") {
64             debugPlugin << "mimeTypeForFile(). QMimeDatabase returned" << mime.name() << "for" << file;
65             return mime.name();
66         }
67     }
68 
69 #ifdef Q_OS_ANDROID
70     QString basename = fi.baseName();
71     // HACK: because we use sanitzed suffix
72     mime = db.mimeTypeForFile(basename + "." + suffix);
73 #else
74     mime = db.mimeTypeForFile(file);
75 #endif
76     if (mime.name() != "application/octet-stream") {
77         debugPlugin << "mimeTypeForFile(). QMimeDatabase returned" << mime.name() << "for" << file;
78         return mime.name();
79     }
80     return "";
81 }
82 
mimeTypeForSuffix(const QString & suffix)83 QString KisMimeDatabase::mimeTypeForSuffix(const QString &suffix)
84 {
85     fillMimeData();
86     QMimeDatabase db;
87 
88     QString s = suffix.toLower();
89 
90     Q_FOREACH(const KisMimeDatabase::KisMimeType &mimeType, s_mimeDatabase) {
91         if (mimeType.suffixes.contains(s)) {
92             debugPlugin << "mimeTypeForSuffix(). KisMimeDatabase returned" << mimeType.mimeType << "for" << s;
93             return mimeType.mimeType;
94         }
95     }
96 
97 
98     // make the file look like a file so Qt would recognize it
99     s = "file." + s;
100 
101     return mimeTypeForFile(s);
102 }
103 
mimeTypeForData(const QByteArray ba)104 QString KisMimeDatabase::mimeTypeForData(const QByteArray ba)
105 {
106     QMimeDatabase db;
107     QMimeType mtp = db.mimeTypeForData(ba);
108     debugPlugin << "mimeTypeForData(). QMimeDatabase returned" << mtp.name();
109     return mtp.name();
110 }
111 
descriptionForMimeType(const QString & mimeType)112 QString KisMimeDatabase::descriptionForMimeType(const QString &mimeType)
113 {
114     fillMimeData();
115 
116     Q_FOREACH(const KisMimeDatabase::KisMimeType &m, s_mimeDatabase) {
117         if (m.mimeType == mimeType) {
118             debugPlugin << "descriptionForMimeType. KisMimeDatabase returned" << m.description << "for" << mimeType;
119             return m.description;
120         }
121     }
122 
123     QMimeDatabase db;
124     QMimeType mime = db.mimeTypeForName(mimeType);
125     if (mime.name() != "application/octet-stream") {
126         debugPlugin  << "descriptionForMimeType. QMimeDatabase returned" << mime.comment() << "for" << mimeType;
127         return mime.comment();
128     }
129 
130     return mimeType;
131 }
132 
suffixesForMimeType(const QString & mimeType)133 QStringList KisMimeDatabase::suffixesForMimeType(const QString &mimeType)
134 {
135     fillMimeData();
136     Q_FOREACH(const KisMimeDatabase::KisMimeType &m, s_mimeDatabase) {
137         if (m.mimeType == mimeType) {
138             debugPlugin << "suffixesForMimeType. KisMimeDatabase returned" << m.suffixes;
139             return m.suffixes;
140         }
141     }
142 
143     QMimeDatabase db;
144     QMimeType mime = db.mimeTypeForName(mimeType);
145     if (mime.name() != "application/octet-stream" && !mime.suffixes().isEmpty()) {
146         QString preferredSuffix = mime.preferredSuffix();
147         if (mimeType == "image/x-tga") {
148             preferredSuffix = "tga";
149         }
150         if (mimeType == "image/jpeg") {
151             preferredSuffix = "jpg";
152         }
153         QStringList suffixes = mime.suffixes();
154         if (preferredSuffix != suffixes.first()) {
155             suffixes.removeAll(preferredSuffix);
156             suffixes.prepend(preferredSuffix);
157 
158         }
159         debugPlugin << "suffixesForMimeType. QMimeDatabase returned" << suffixes;
160         return suffixes;
161     }
162     return QStringList();
163 }
164 
iconNameForMimeType(const QString & mimeType)165 QString KisMimeDatabase::iconNameForMimeType(const QString &mimeType)
166 {
167     QMimeDatabase db;
168     QMimeType mime = db.mimeTypeForName(mimeType);
169     debugPlugin << "iconNameForMimeType" << mime.iconName();
170     return mime.iconName();
171 }
172 
fillMimeData()173 void KisMimeDatabase::fillMimeData()
174 {
175     // This should come from the import/export plugins, but the json files aren't translated,
176     // which is bad for the description field
177     if (s_mimeDatabase.isEmpty()) {
178 
179         KisMimeType mimeType;
180 
181         mimeType.mimeType = "image/x-gimp-brush";
182         mimeType.description = i18nc("description of a file type", "Gimp Brush");
183         mimeType.suffixes = QStringList() << "gbr" << "vbr";
184         s_mimeDatabase << mimeType;
185 
186         mimeType.mimeType = "image/x-gimp-brush-animated";
187         mimeType.description = i18nc("description of a file type", "Gimp Image Hose Brush");
188         mimeType.suffixes = QStringList() << "gih";
189         s_mimeDatabase << mimeType;
190 
191         mimeType.mimeType = "image/x-adobe-brushlibrary";
192         mimeType.description = i18nc("description of a file type", "Adobe Brush Library");
193         mimeType.suffixes = QStringList() << "abr";
194         s_mimeDatabase << mimeType;
195 
196         mimeType.mimeType = "application/x-krita-paintoppreset";
197         mimeType.description = i18nc("description of a file type", "Krita Brush Preset");
198         mimeType.suffixes = QStringList() << "kpp";
199         s_mimeDatabase << mimeType;
200 
201         mimeType.mimeType = "application/x-krita-assistant";
202         mimeType.description = i18nc("description of a file type", "Krita Assistant");
203         mimeType.suffixes = QStringList() << "paintingassistant";
204         s_mimeDatabase << mimeType;
205 
206         mimeType.mimeType = "image/x-r32";
207         mimeType.description = i18nc("description of a file type", "R32 Heightmap");
208         mimeType.suffixes = QStringList() <<  "r32";
209         s_mimeDatabase << mimeType;
210 
211         mimeType.mimeType = "image/x-r16";
212         mimeType.description = i18nc("description of a file type", "R16 Heightmap");
213         mimeType.suffixes = QStringList() <<  "r16";
214         s_mimeDatabase << mimeType;
215 
216         mimeType.mimeType = "image/x-r8";
217         mimeType.description = i18nc("description of a file type", "R8 Heightmap");
218         mimeType.suffixes = QStringList() << "r8";
219         s_mimeDatabase << mimeType;
220 
221         mimeType.mimeType = "application/x-spriter";
222         mimeType.description = i18nc("description of a file type", "Spriter SCML");
223         mimeType.suffixes = QStringList() << "scml";
224         s_mimeDatabase << mimeType;
225 
226         mimeType.mimeType = "image/x-svm";
227         mimeType.description = i18nc("description of a file type", "Starview Metafile");
228         mimeType.suffixes = QStringList() << "svm";
229         s_mimeDatabase << mimeType;
230 
231         mimeType.mimeType = "image/openraster";
232         mimeType.description = i18nc("description of a file type", "OpenRaster Image");
233         mimeType.suffixes = QStringList() << "ora";
234         s_mimeDatabase << mimeType;
235 
236         mimeType.mimeType = "application/x-photoshop-style-library";
237         mimeType.description = i18nc("description of a file type", "Photoshop Layer Style Library");
238         mimeType.suffixes = QStringList() << "asl";
239         s_mimeDatabase << mimeType;
240 
241         mimeType.mimeType = "application/x-gimp-color-palette";
242         mimeType.description = i18nc("description of a file type", "Color Palette");
243         mimeType.suffixes = QStringList() << "gpl" << "pal" << "act" << "aco" << "colors" << "xml" << "sbz";
244         s_mimeDatabase << mimeType;
245 
246         mimeType.mimeType = "krita/x-colorset";
247         mimeType.description = i18nc("description of a file type", "Krita Color Palette");
248         mimeType.suffixes = QStringList() << "kpl";
249         s_mimeDatabase << mimeType;
250 
251         mimeType.mimeType = "application/x-opencolorio-configuration";
252         mimeType.description = i18nc("description of a file type", "OpenColorIO Configuration");
253         mimeType.suffixes = QStringList() << "ocio";
254         s_mimeDatabase << mimeType;
255 
256         mimeType.mimeType = "application/x-gimp-gradient";
257         mimeType.description = i18nc("description of a file type", "GIMP Gradients");
258         mimeType.suffixes = QStringList() << "ggr";
259         s_mimeDatabase << mimeType;
260 
261         mimeType.mimeType = "application/x-gimp-pattern";
262         mimeType.description = i18nc("description of a file type", "GIMP Patterns");
263         mimeType.suffixes = QStringList() << "pat";
264         s_mimeDatabase << mimeType;
265 
266         mimeType.mimeType = "application/x-krita-bundle";
267         mimeType.description = i18nc("description of a file type", "Krita Resource Bundle");
268         mimeType.suffixes = QStringList() << "bundle";
269         s_mimeDatabase << mimeType;
270 
271         mimeType.mimeType = "application/x-krita-workspace";
272         mimeType.description = i18nc("description of a file type", "Krita Workspace");
273         mimeType.suffixes = QStringList() << "kws";
274         s_mimeDatabase << mimeType;
275 
276         mimeType.mimeType = "application/x-krita-taskset";
277         mimeType.description = i18nc("description of a file type", "Krita Taskset");
278         mimeType.suffixes = QStringList() << "kts";
279         s_mimeDatabase << mimeType;
280 
281         mimeType.mimeType = "application/x-krita-reference-images";
282         mimeType.description = i18nc("description of a file type", "Krita Reference Image Collection");
283         mimeType.suffixes = QStringList() << "krf";
284         s_mimeDatabase << mimeType;
285 
286         mimeType.mimeType = "application/x-krita-shortcuts";
287         mimeType.description = i18nc("description of a file type", "Krita Shortcut Scheme");
288         mimeType.suffixes = QStringList() << "shortcuts";
289         s_mimeDatabase << mimeType;
290 
291         mimeType.mimeType = "image/x-krita-raw";
292         mimeType.description = i18nc("description of a file type", "Camera Raw Files");
293         mimeType.suffixes = QStringList() << "bay" << "bmq" << "cr2" << "crw" << "cs1" << "dc2" << "dcr" << "dng" << "erf" << "fff" << "hdr" << "k25" << "kdc" << "mdc" << "mos" << "mrw" << "nef" << "orf" << "pef" << "pxn" << "raf" << "raw" << "rdc" << "sr2" << "srf" << "x3f" << "arw" << "3fr" << "cine" << "ia" << "kc2" << "mef" << "nrw" << "qtk" << "rw2" << "sti" << "rwl" << "srw";
294         s_mimeDatabase << mimeType;
295 
296         mimeType.mimeType = "application/x-extension-exr";
297         mimeType.description = i18nc("description of a file type", "OpenEXR (Extended)");
298         mimeType.suffixes = QStringList() << "exr";
299         s_mimeDatabase << mimeType;
300 
301         mimeType.mimeType = "image/x-psb";
302         mimeType.description = i18nc("description of a file type", "Photoshop Image (Large)");
303         mimeType.suffixes = QStringList() << "psb";
304         s_mimeDatabase << mimeType;
305 
306         mimeType.mimeType = "image/heic";
307         mimeType.description = i18nc("description of a file type", "HEIC/HEIF Image");
308         mimeType.suffixes = QStringList() << "heic" << "heif";
309         s_mimeDatabase << mimeType;
310 
311         mimeType.mimeType = "image/jp2";
312         mimeType.description = i18nc("description of a file type", "JP2 Image");
313         mimeType.suffixes = QStringList() << "jp2" << "j2k";
314         s_mimeDatabase << mimeType;
315 
316         mimeType.mimeType = "application/x-krita-seexpr-script";
317         mimeType.description = i18nc("description of a file type", "SeExpr script package");
318         mimeType.suffixes = QStringList() << "kse";
319         s_mimeDatabase << mimeType;
320 
321         debugPlugin << "Filled mimedatabase with" << s_mimeDatabase.count() << "special mimetypes";
322     }
323 }
324