File indexing completed on 2024-05-12 15:55:34

0001 // SPDX-FileCopyrightText: 2003-2012 Jesper K. Pedersen <jesper.pedersen@kdab.com>
0002 // SPDX-FileCopyrightText: 2005 Steffen Hansen <hansen@kde.org>
0003 // SPDX-FileCopyrightText: 2006-2009 Tuomas Suutari <tuomas@nepnep.net>
0004 // SPDX-FileCopyrightText: 2007 Dirk Mueller <mueller@kde.org>
0005 // SPDX-FileCopyrightText: 2007 Laurent Montel <montel@kde.org>
0006 // SPDX-FileCopyrightText: 2007-2012 Jan Kundrát <jkt@flaska.net>
0007 // SPDX-FileCopyrightText: 2010 Miika Turkia <miika.turkia@gmail.com>
0008 // SPDX-FileCopyrightText: 2012 Rex Dieter <rdieter@math.unl.edu>
0009 // SPDX-FileCopyrightText: 2013-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0010 // SPDX-FileCopyrightText: 2016 Tobias Leupold <tl@stonemx.de>
0011 // SPDX-FileCopyrightText: 2018 Robert Krawitz <rlk@alum.mit.edu>
0012 
0013 // SPDX-License-Identifier: GPL-2.0-or-later
0014 
0015 #include "FileExtensions.h"
0016 
0017 #include <kpabase/SettingsData.h>
0018 #include <kpabase/config-kpa-kdcraw.h>
0019 #ifdef HAVE_KDCRAW
0020 #include <KDCRAW/RawFiles>
0021 #include <libkdcraw_version.h>
0022 #endif
0023 
0024 #include <QFileInfo>
0025 #include <QSet>
0026 #include <QString>
0027 
0028 namespace
0029 {
0030 void _initializeExtensionLists(QStringList &rawExtensions, QStringList &standardExtensions, QStringList &ignoredExtensions)
0031 {
0032     static QStringList _rawExtensions, _standardExtensions, _ignoredExtensions;
0033     static bool extensionListsInitialized = false;
0034     if (!extensionListsInitialized) {
0035 #ifdef HAVE_KDCRAW
0036         _rawExtensions = QString::fromLatin1(raw_file_extentions).split(QChar::fromLatin1(' '), Qt::SkipEmptyParts);
0037 #endif /* HAVE_KDCRAW */
0038         for (QStringList::iterator it = _rawExtensions.begin(); it != _rawExtensions.end(); ++it)
0039             (*it).remove(QString::fromUtf8("*."));
0040 
0041         _standardExtensions << QString::fromLatin1("jpg")
0042                             << QString::fromLatin1("JPG")
0043                             << QString::fromLatin1("jpeg")
0044                             << QString::fromLatin1("JPEG")
0045                             << QString::fromLatin1("tif")
0046                             << QString::fromLatin1("TIF")
0047                             << QString::fromLatin1("tiff")
0048                             << QString::fromLatin1("TIFF")
0049                             << QString::fromLatin1("png")
0050                             << QString::fromLatin1("PNG");
0051         _ignoredExtensions << QString::fromLatin1("thm") // Thumbnails
0052                            << QString::fromLatin1("THM")
0053                            << QString::fromLatin1("thumb") // thumbnail files
0054                            // from dcraw
0055                            << QString::fromLatin1("ctg") // Catalog files
0056                            << QString::fromLatin1("gz") // Compressed files
0057                            << QString::fromLatin1("Z")
0058                            << QString::fromLatin1("bz2")
0059                            << QString::fromLatin1("zip")
0060                            << QString::fromLatin1("xml")
0061                            << QString::fromLatin1("XML")
0062                            << QString::fromLatin1("html")
0063                            << QString::fromLatin1("HTML")
0064                            << QString::fromLatin1("htm")
0065                            << QString::fromLatin1("HTM")
0066                            << QString::fromLatin1("pp3") // RawTherapee Sidecar files
0067                            << QString::fromLatin1("PP3")
0068                            << QString::fromLatin1("xmp") // Other sidecars
0069                            << QString::fromLatin1("XMP")
0070                            << QString::fromLatin1("pto") // Hugin sidecars
0071                            << QString::fromLatin1("PTO");
0072 
0073         QChar dot(QChar::fromLatin1('.'));
0074         for (QStringList::iterator it = _rawExtensions.begin(); it != _rawExtensions.end(); ++it)
0075             if (!(*it).startsWith(dot))
0076                 *it = dot + *it;
0077         for (QStringList::iterator it = _standardExtensions.begin(); it != _standardExtensions.end(); ++it)
0078             if (!(*it).startsWith(dot))
0079                 *it = dot + *it;
0080         for (QStringList::iterator it = _ignoredExtensions.begin(); it != _ignoredExtensions.end(); ++it)
0081             if (!(*it).startsWith(dot))
0082                 *it = dot + *it;
0083 
0084         extensionListsInitialized = true;
0085     }
0086 
0087     rawExtensions = _rawExtensions;
0088     standardExtensions = _standardExtensions;
0089     ignoredExtensions = _ignoredExtensions;
0090 }
0091 bool _fileExistsWithExtensions(const DB::FileName &fileName,
0092                                const QStringList &extensionList)
0093 {
0094     QString baseFileName = fileName.absolute();
0095     int extStart = baseFileName.lastIndexOf(QChar::fromLatin1('.'));
0096     // We're interested in xxx.yyy, not .yyy
0097     if (extStart <= 1)
0098         return false;
0099     baseFileName.remove(extStart, baseFileName.length() - extStart);
0100     for (QStringList::ConstIterator it = extensionList.begin();
0101          it != extensionList.end(); ++it) {
0102         if (QFile::exists(baseFileName + *it))
0103             return true;
0104     }
0105     return false;
0106 }
0107 
0108 bool _fileIsKnownWithExtensions(const DB::FileNameSet &files,
0109                                 const DB::FileName &fileName,
0110                                 const QStringList &extensionList)
0111 {
0112     QString baseFileName = fileName.absolute();
0113     int extStart = baseFileName.lastIndexOf(QChar::fromLatin1('.'));
0114     if (extStart <= 1)
0115         return false;
0116     baseFileName.remove(extStart, baseFileName.length() - extStart);
0117     for (QStringList::ConstIterator it = extensionList.begin();
0118          it != extensionList.end(); ++it) {
0119         if (files.contains(DB::FileName::fromAbsolutePath(baseFileName + *it)))
0120             return true;
0121     }
0122     return false;
0123 }
0124 
0125 bool _fileEndsWithExtensions(const DB::FileName &fileName,
0126                              const QStringList &extensionList)
0127 {
0128     for (QStringList::ConstIterator it = extensionList.begin();
0129          it != extensionList.end(); ++it) {
0130         if (fileName.relative().endsWith(*it, Qt::CaseInsensitive))
0131             return true;
0132     }
0133     return false;
0134 }
0135 } // namespace
0136 
0137 bool KPABase::fileCanBeSkipped(const DB::FileNameSet &loadedFiles, const DB::FileName &imageFile)
0138 {
0139     QStringList _rawExtensions, _standardExtensions, _ignoredExtensions;
0140     _initializeExtensionLists(_rawExtensions, _standardExtensions, _ignoredExtensions);
0141 
0142     // We're not interested in thumbnail and other files.
0143     if (_fileEndsWithExtensions(imageFile, _ignoredExtensions))
0144         return true;
0145 
0146     // If we *are* interested in raw files even when other equivalent
0147     // non-raw files are available, then we're interested in this file.
0148     if (!(Settings::SettingsData::instance()->skipRawIfOtherMatches()))
0149         return false;
0150 
0151     // If the file ends with something other than a known raw extension,
0152     // we're interested in it.
0153     if (!_fileEndsWithExtensions(imageFile, _rawExtensions))
0154         return false;
0155 
0156     // At this point, the file ends with a known raw extension, and we're
0157     // not interested in raw files when other non-raw files are available.
0158     // So search for an existing file with one of the standard
0159     // extensions.
0160     //
0161     // This may not be the best way to do this, but it's using the
0162     // same algorithm as _mightDecode above.
0163     // -- Robert Krawitz rlk@alum.mit.edu 2007-07-22
0164 
0165     return _fileIsKnownWithExtensions(loadedFiles, imageFile, _standardExtensions);
0166 }
0167 
0168 bool KPABase::isUsableRawImage(const DB::FileName &imageFile, FileTypePreference preference)
0169 {
0170     QStringList _rawExtensions, _standardExtensions, _ignoredExtensions;
0171     _initializeExtensionLists(_rawExtensions, _standardExtensions, _ignoredExtensions);
0172 
0173     if (preference == FileTypePreference::PreferNonRawFile && _fileExistsWithExtensions(imageFile, _standardExtensions))
0174         return false;
0175     if (_fileEndsWithExtensions(imageFile, _rawExtensions))
0176         return true;
0177     return false;
0178 }
0179 
0180 QStringList KPABase::rawExtensions()
0181 {
0182     QStringList _rawExtensions, _standardExtensions, _ignoredExtensions;
0183     _initializeExtensionLists(_rawExtensions, _standardExtensions, _ignoredExtensions);
0184     return _rawExtensions;
0185 }
0186 
0187 bool KPABase::isVideo(const DB::FileName &fileName)
0188 {
0189     QFileInfo fi(fileName.relative());
0190     QString ext = fi.suffix().toLower();
0191     return videoExtensions().contains(ext);
0192 }
0193 
0194 const QSet<QString> &KPABase::videoExtensions()
0195 {
0196     static QSet<QString> videoExtensions;
0197     if (videoExtensions.empty()) {
0198         videoExtensions.insert(QString::fromLatin1("3gp"));
0199         videoExtensions.insert(QString::fromLatin1("avi"));
0200         videoExtensions.insert(QString::fromLatin1("mp4"));
0201         videoExtensions.insert(QString::fromLatin1("m4v"));
0202         videoExtensions.insert(QString::fromLatin1("mpeg"));
0203         videoExtensions.insert(QString::fromLatin1("mpg"));
0204         videoExtensions.insert(QString::fromLatin1("qt"));
0205         videoExtensions.insert(QString::fromLatin1("mov"));
0206         videoExtensions.insert(QString::fromLatin1("moov"));
0207         videoExtensions.insert(QString::fromLatin1("qtvr"));
0208         videoExtensions.insert(QString::fromLatin1("rv"));
0209         videoExtensions.insert(QString::fromLatin1("3g2"));
0210         videoExtensions.insert(QString::fromLatin1("fli"));
0211         videoExtensions.insert(QString::fromLatin1("flc"));
0212         videoExtensions.insert(QString::fromLatin1("mkv"));
0213         videoExtensions.insert(QString::fromLatin1("mng"));
0214         videoExtensions.insert(QString::fromLatin1("asf"));
0215         videoExtensions.insert(QString::fromLatin1("asx"));
0216         videoExtensions.insert(QString::fromLatin1("wmp"));
0217         videoExtensions.insert(QString::fromLatin1("wmv"));
0218         videoExtensions.insert(QString::fromLatin1("ogm"));
0219         videoExtensions.insert(QString::fromLatin1("rm"));
0220         videoExtensions.insert(QString::fromLatin1("flv"));
0221         videoExtensions.insert(QString::fromLatin1("webm"));
0222         videoExtensions.insert(QString::fromLatin1("mts"));
0223         videoExtensions.insert(QString::fromLatin1("ogg"));
0224         videoExtensions.insert(QString::fromLatin1("ogv"));
0225         videoExtensions.insert(QString::fromLatin1("m2ts"));
0226     }
0227     return videoExtensions;
0228 }
0229 // vi:expandtab:tabstop=4 shiftwidth=4: