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 }