File indexing completed on 2024-04-21 03:55:07

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2008 Peter Penz <peter.penz@gmx.at>
0004     SPDX-FileCopyrightText: 2008 George Goldberg <grundleborg@googlemail.com>
0005     SPDX-FileCopyrightText: 2009 David Faure <faure@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0008 */
0009 
0010 #include "kfileitemlistproperties.h"
0011 
0012 #include <kfileitem.h>
0013 #include <kprotocolmanager.h>
0014 
0015 #include <QFileInfo>
0016 
0017 class KFileItemListPropertiesPrivate : public QSharedData
0018 {
0019 public:
0020     KFileItemListPropertiesPrivate()
0021         : m_isDirectory(false)
0022         , m_isFile(false)
0023         , m_supportsReading(false)
0024         , m_supportsDeleting(false)
0025         , m_supportsWriting(false)
0026         , m_supportsMoving(false)
0027         , m_isLocal(true)
0028     {
0029     }
0030     void setItems(const KFileItemList &items);
0031 
0032     void determineMimeTypeAndGroup() const;
0033 
0034     KFileItemList m_items;
0035     mutable QString m_mimeType;
0036     mutable QString m_mimeGroup;
0037     bool m_isDirectory : 1;
0038     bool m_isFile : 1;
0039     bool m_supportsReading : 1;
0040     bool m_supportsDeleting : 1;
0041     bool m_supportsWriting : 1;
0042     bool m_supportsMoving : 1;
0043     bool m_isLocal : 1;
0044 };
0045 
0046 KFileItemListProperties::KFileItemListProperties()
0047     : d(new KFileItemListPropertiesPrivate)
0048 {
0049 }
0050 
0051 KFileItemListProperties::KFileItemListProperties(const KFileItemList &items)
0052     : d(new KFileItemListPropertiesPrivate)
0053 {
0054     setItems(items);
0055 }
0056 
0057 void KFileItemListProperties::setItems(const KFileItemList &items)
0058 {
0059     d->setItems(items);
0060 }
0061 
0062 void KFileItemListPropertiesPrivate::setItems(const KFileItemList &items)
0063 {
0064     const bool initialValue = !items.isEmpty();
0065     m_items = items;
0066     m_supportsReading = initialValue;
0067     m_supportsDeleting = initialValue;
0068     m_supportsWriting = initialValue;
0069     m_supportsMoving = initialValue;
0070     m_isDirectory = initialValue;
0071     m_isFile = initialValue;
0072     m_isLocal = true;
0073     m_mimeType.clear();
0074     m_mimeGroup.clear();
0075 
0076     QFileInfo parentDirInfo;
0077     for (const KFileItem &item : items) {
0078         const QUrl url = item.url();
0079         const auto [localUrl, isLocal] = item.isMostLocalUrl();
0080         m_isLocal = m_isLocal && isLocal;
0081         m_supportsReading = m_supportsReading && KProtocolManager::supportsReading(url);
0082         m_supportsDeleting = m_supportsDeleting && KProtocolManager::supportsDeleting(url);
0083         m_supportsWriting = m_supportsWriting && KProtocolManager::supportsWriting(url) && item.isWritable();
0084         m_supportsMoving = m_supportsMoving && KProtocolManager::supportsMoving(url);
0085 
0086         // For local files we can do better: check if we have write permission in parent directory
0087         // TODO: if we knew about the parent KFileItem, we could even do that for remote protocols too
0088 #ifndef Q_OS_WIN
0089         if (m_isLocal && (m_supportsDeleting || m_supportsMoving)) {
0090             const QString directory = localUrl.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).toLocalFile();
0091             if (parentDirInfo.filePath() != directory) {
0092                 parentDirInfo.setFile(directory);
0093             }
0094             if (!parentDirInfo.isWritable()) {
0095                 m_supportsDeleting = false;
0096                 m_supportsMoving = false;
0097             }
0098         }
0099 #else
0100         if (m_isLocal && m_supportsDeleting) {
0101             if (!QFileInfo(url.toLocalFile()).isWritable())
0102                 m_supportsDeleting = false;
0103         }
0104 #endif
0105         if (m_isDirectory && !item.isDir()) {
0106             m_isDirectory = false;
0107         }
0108 
0109         if (m_isFile && !item.isFile()) {
0110             m_isFile = false;
0111         }
0112     }
0113 }
0114 
0115 KFileItemListProperties::KFileItemListProperties(const KFileItemListProperties &other)
0116     : d(other.d)
0117 {
0118 }
0119 
0120 KFileItemListProperties &KFileItemListProperties::operator=(const KFileItemListProperties &other)
0121 {
0122     d = other.d;
0123     return *this;
0124 }
0125 
0126 KFileItemListProperties::~KFileItemListProperties()
0127 {
0128 }
0129 
0130 bool KFileItemListProperties::supportsReading() const
0131 {
0132     return d->m_supportsReading;
0133 }
0134 
0135 bool KFileItemListProperties::supportsDeleting() const
0136 {
0137     return d->m_supportsDeleting;
0138 }
0139 
0140 bool KFileItemListProperties::supportsWriting() const
0141 {
0142     return d->m_supportsWriting;
0143 }
0144 
0145 bool KFileItemListProperties::supportsMoving() const
0146 {
0147     return d->m_supportsMoving && d->m_supportsDeleting;
0148 }
0149 
0150 bool KFileItemListProperties::isLocal() const
0151 {
0152     return d->m_isLocal;
0153 }
0154 
0155 KFileItemList KFileItemListProperties::items() const
0156 {
0157     return d->m_items;
0158 }
0159 
0160 QList<QUrl> KFileItemListProperties::urlList() const
0161 {
0162     return d->m_items.targetUrlList();
0163 }
0164 
0165 bool KFileItemListProperties::isDirectory() const
0166 {
0167     return d->m_isDirectory;
0168 }
0169 
0170 bool KFileItemListProperties::isFile() const
0171 {
0172     return d->m_isFile;
0173 }
0174 
0175 QString KFileItemListProperties::mimeType() const
0176 {
0177     if (d->m_mimeType.isEmpty()) {
0178         d->determineMimeTypeAndGroup();
0179     }
0180     return d->m_mimeType;
0181 }
0182 
0183 QString KFileItemListProperties::mimeGroup() const
0184 {
0185     if (d->m_mimeType.isEmpty()) {
0186         d->determineMimeTypeAndGroup();
0187     }
0188     return d->m_mimeGroup;
0189 }
0190 
0191 void KFileItemListPropertiesPrivate::determineMimeTypeAndGroup() const
0192 {
0193     if (!m_items.isEmpty()) {
0194         m_mimeType = m_items.first().mimetype();
0195         m_mimeGroup = m_mimeType.left(m_mimeType.indexOf(QLatin1Char('/')));
0196     }
0197     for (const KFileItem &item : std::as_const(m_items)) {
0198         const QString itemMimeType = item.mimetype();
0199         // Determine if common MIME type among all items
0200         if (m_mimeType != itemMimeType) {
0201             m_mimeType.clear();
0202             const auto type = QStringView(itemMimeType).left(itemMimeType.indexOf(QLatin1Char('/')));
0203             if (m_mimeGroup != type) {
0204                 m_mimeGroup.clear(); // MIME type groups are different as well!
0205             }
0206         }
0207     }
0208 }