File indexing completed on 2024-05-12 16:39:37

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "KexiFileFilters.h"
0021 #include <core/KexiMainWindowIface.h>
0022 #include <core/KexiMigrateManagerInterface.h>
0023 
0024 #include <QMimeDatabase>
0025 #include <QMimeType>
0026 #include <QSet>
0027 
0028 #include <KDb>
0029 
0030 //! @internal
0031 class Q_DECL_HIDDEN KexiFileFilters::Private
0032 {
0033 public:
0034     Private() {}
0035 
0036     QList<QMimeType> mimeTypes() {
0037         update();
0038         return m_mimeTypes;
0039     }
0040 
0041     QMimeDatabase db;
0042     KexiFileFilters::Mode mode = KexiFileFilters::Opening;
0043     QStringList comments;
0044     QSet<QString> additionalMimeTypes;
0045     QSet<QString> excludedMimeTypes;
0046     QString defaultFilter;
0047     bool filtersUpdated = false;
0048 
0049 private:
0050     void update()
0051     {
0052         if (filtersUpdated) {
0053             return;
0054         }
0055         filtersUpdated = true;
0056         m_mimeTypes.clear();
0057 
0058         if (mode == KexiFileFilters::Opening || mode == KexiFileFilters::SavingFileBasedDB) {
0059             addMimeType(KDb::defaultFileBasedDriverMimeType());
0060         }
0061         if (mode == KexiFileFilters::Opening || mode == KexiFileFilters::SavingServerBasedDB) {
0062             addMimeType("application/x-kexiproject-shortcut");
0063         }
0064         if (mode == KexiFileFilters::Opening || mode == KexiFileFilters::SavingServerBasedDB) {
0065             addMimeType("application/x-kexi-connectiondata");
0066         }
0067 
0068         if (mode == KexiFileFilters::Opening) {
0069             const QStringList supportedFileMimeTypes = KexiMainWindowIface::global()->migrateManager()->supportedFileMimeTypes();
0070             foreach (const QString& supportedFileMimeType, supportedFileMimeTypes) {
0071                 addMimeType(supportedFileMimeType);
0072             }
0073         }
0074 
0075         foreach(const QString& mimeName, additionalMimeTypes) {
0076             if (mimeName == "all/allfiles") {
0077                 continue; // "All files" is added automatically by KFileWidget and we add it
0078                           // dynamically for KexiFileRequester
0079             }
0080             addMimeType(mimeName);
0081         }
0082     }
0083 
0084     bool addMimeType(const QString &mimeName)
0085     {
0086         const QMimeType mime = db.mimeTypeForName(mimeName);
0087         if (mime.isValid() && !excludedMimeTypes.contains(mime.name().toLower())) {
0088             m_mimeTypes += mime;
0089             return true;
0090         }
0091         return false;
0092     }
0093     /*! Adds file dialog-compatible filter to @a filter and patterns to @allfilters based on
0094         @a mimeName mime type name. Does nothing if excludedMimeTypes contains this mime name. */
0095     //! @todo ?
0096     /*
0097     bool addFilterForType(QStringList *allfilters, const QString &mimeName)
0098     {
0099         QMimeDatabase db;
0100         const QMimeType mime = db.mimeTypeForName(mimeName);
0101         if (mime.isValid() && !excludedMimeTypes.contains(mime.name().toLower())) {
0102             filters += mime.filterString(); // KexiUtils::fileDialogFilterString(mime);
0103             *allfilters += mime.globPatterns();
0104             return true;
0105         }
0106         return false;
0107     }*/
0108 
0109     QList<QMimeType> m_mimeTypes;
0110 };
0111 
0112 KexiFileFilters::KexiFileFilters()
0113  : d(new Private)
0114 {
0115 }
0116 
0117 KexiFileFilters::~KexiFileFilters()
0118 {
0119     delete d;
0120 }
0121 
0122 KexiFileFilters::Mode KexiFileFilters::mode() const
0123 {
0124     return d->mode;
0125 }
0126 
0127 void KexiFileFilters::setMode(Mode mode)
0128 {
0129     d->mode = mode;
0130     d->filtersUpdated = false;
0131 }
0132 
0133 void KexiFileFilters::setDefaultFilter(const QString &filter)
0134 {
0135     d->defaultFilter = filter;
0136 }
0137 
0138 QString KexiFileFilters::defaultFilter() const
0139 {
0140     return d->defaultFilter;
0141 }
0142 
0143 QStringList KexiFileFilters::additionalMimeTypes() const
0144 {
0145     return d->additionalMimeTypes.toList();
0146 }
0147 
0148 void KexiFileFilters::setAdditionalMimeTypes(const QStringList &mimeTypes)
0149 {
0150     //delayed
0151     d->additionalMimeTypes = mimeTypes.toSet();
0152     d->filtersUpdated = false;
0153 }
0154 
0155 QStringList KexiFileFilters::excludedMimeTypes() const
0156 {
0157     return d->excludedMimeTypes.toList();
0158 }
0159 
0160 void KexiFileFilters::setExcludedMimeTypes(const QStringList &mimeTypes)
0161 {
0162     //delayed
0163     d->excludedMimeTypes.clear();
0164     //convert to lowercase
0165     for(const QString& mimeType : mimeTypes) {
0166         d->excludedMimeTypes.insert(mimeType.toLower());
0167     }
0168     d->filtersUpdated = false;
0169 }
0170 
0171 static QStringList globPatterns(const QMimeType &mimeType)
0172 {
0173     QStringList result = mimeType.globPatterns();
0174     //! @todo Improve if possible.
0175     //!       This is a hack to remove misleading filter, QFileSystemModel can't check by content.
0176     if (mimeType.name() == QStringLiteral("text/plain")) {
0177         result.removeOne(QStringLiteral("*.doc"));
0178     }
0179     return result;
0180 }
0181 
0182 QStringList KexiFileFilters::allGlobPatterns() const
0183 {
0184     QStringList result;
0185     for(const QMimeType &mimeType : d->mimeTypes()) {
0186         result += globPatterns(mimeType);
0187     }
0188     //remove duplicates made because upper- and lower-case extensions are used:
0189     result = result.toSet().toList();
0190     std::sort(result.begin(), result.end());
0191     return result;
0192 }
0193 
0194 QList<QMimeType> KexiFileFilters::mimeTypes() const
0195 {
0196     return d->mimeTypes();
0197 }
0198 
0199 QStringList KexiFileFilters::mimeTypeNames() const
0200 {
0201     QStringList result;
0202     for (const QMimeType &mimeType : d->mimeTypes()) {
0203         result += mimeType.name();
0204     }
0205     return result;
0206 }
0207 
0208 bool KexiFileFilters::isExistingFileRequired() const
0209 {
0210     switch (mode()) {
0211     case Opening:
0212         return true;
0213     case CustomOpening:
0214         return true;
0215     default:
0216         return false;
0217     }
0218 }
0219 
0220 //static
0221 QString KexiFileFilters::separator(const KexiFileFiltersFormat &format)
0222 {
0223     return format.type == KexiFileFiltersFormat::Type::Qt ? QStringLiteral(";;")
0224                                                           : QStringLiteral("\n");
0225 }
0226 
0227 QStringList KexiFileFilters::toList(const KexiFileFiltersFormat &format) const
0228 {
0229     QStringList result;
0230     QStringList allPatterns;
0231     for(const QMimeType &mimeType : d->mimeTypes()) {
0232         result += KexiFileFilters::toString(mimeType, format);
0233     }
0234 
0235     if (!d->defaultFilter.isEmpty() && !d->excludedMimeTypes.contains("all/allfiles")) {
0236         result += d->defaultFilter;
0237     }
0238 
0239     const QStringList allGlobPatterns(this->allGlobPatterns());
0240     if (allGlobPatterns.count() > 1) {//prepend "all supoported files" entry
0241         result.prepend(KexiFileFilters::toString(allGlobPatterns,
0242             xi18n("All Supported Files"), format));
0243     }
0244 
0245     if (format.addAllFiles) {
0246         result.append(KexiFileFilters::toString({ QStringLiteral("*") }, xi18n("All Files"), format));
0247     }
0248     return result;
0249 }
0250 
0251 QString KexiFileFilters::toString(const KexiFileFiltersFormat &format) const
0252 {
0253     return toList(format).join(KexiFileFilters::separator(format));
0254 }
0255 
0256 //static
0257 QString KexiFileFilters::toString(const QStringList &patterns, const QString &comment,
0258                                   const KexiFileFiltersFormat &format)
0259 {
0260     QString str;
0261     if (format.type == KexiFileFiltersFormat::Type::KDE
0262         || format.type == KexiFileFiltersFormat::Type::KUrlRequester)
0263     {
0264         str += patterns.join(QStringLiteral(" ")) + QStringLiteral("|");
0265     }
0266     str += comment;
0267     if (format.type == KexiFileFiltersFormat::Type::Qt
0268         || format.type == KexiFileFiltersFormat::Type::KDE)
0269     {
0270         str += QStringLiteral(" (");
0271         if (patterns.isEmpty()) {
0272             str += QStringLiteral("*");
0273         } else {
0274 #ifdef Q_OS_WIN
0275             str += patterns.join(format.type == KexiFileFiltersFormat::Type::Qt ? " " : ";");
0276 #else
0277             str += QLocale().createSeparatedList(patterns);
0278 #endif
0279             str += ")";
0280         }
0281     }
0282     return str;
0283 }
0284 
0285 //static
0286 QString KexiFileFilters::toString(const QMimeType &mime, const KexiFileFiltersFormat &format)
0287 {
0288     if (!mime.isValid()) {
0289         return QString();
0290     }
0291 
0292     if (format.type == KexiFileFiltersFormat::Type::Qt) {
0293         return mime.filterString();
0294     }
0295 
0296     QString str;
0297     QStringList patterns(globPatterns(mime));
0298     if (patterns.isEmpty()) {
0299         patterns += QStringLiteral("*");
0300     }
0301     return toString(patterns, mime.comment(), format);
0302 }
0303 
0304 //static
0305 QString KexiFileFilters::toString(const QString& mimeName, const KexiFileFiltersFormat &format)
0306 {
0307     QMimeDatabase db;
0308     return KexiFileFilters::toString(db.mimeTypeForName(mimeName), format);
0309 }
0310 
0311 // static
0312 QStringList KexiFileFilters::toList(const QStringList &mimeNames,
0313                                     const KexiFileFiltersFormat &format)
0314 {
0315     QStringList result;
0316     for(const QString &mimeName : mimeNames) {
0317         result += KexiFileFilters::toString(mimeName, format);
0318     }
0319     return result;
0320 }
0321 
0322 //static
0323 QString KexiFileFilters::toString(const QStringList& mimeNames, const KexiFileFiltersFormat &format)
0324 {
0325     return KexiFileFilters::toList(mimeNames, format).join(KexiFileFilters::separator(format));
0326 }