File indexing completed on 2024-09-08 03:39:00
0001 /* 0002 This file is part of the KDE project. 0003 SPDX-FileCopyrightText: 2003 Carsten Pfeiffer <pfeiffer@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "kfilemetapreview_p.h" 0009 0010 #include <QLayout> 0011 #include <QMimeDatabase> 0012 0013 #include <KPluginFactory> 0014 #include <QDebug> 0015 #include <kimagefilepreview.h> 0016 #include <kio/previewjob.h> 0017 0018 bool KFileMetaPreview::s_tryAudioPreview = true; 0019 0020 KFileMetaPreview::KFileMetaPreview(QWidget *parent) 0021 : KPreviewWidgetBase(parent) 0022 , haveAudioPreview(false) 0023 { 0024 QHBoxLayout *layout = new QHBoxLayout(this); 0025 layout->setContentsMargins(0, 0, 0, 0); 0026 m_stack = new QStackedWidget(this); 0027 layout->addWidget(m_stack); 0028 0029 // ### 0030 // m_previewProviders.setAutoDelete( true ); 0031 initPreviewProviders(); 0032 } 0033 0034 KFileMetaPreview::~KFileMetaPreview() 0035 { 0036 } 0037 0038 void KFileMetaPreview::initPreviewProviders() 0039 { 0040 qDeleteAll(m_previewProviders); 0041 m_previewProviders.clear(); 0042 // hardcoded so far 0043 0044 // image previews 0045 KImageFilePreview *imagePreview = new KImageFilePreview(m_stack); 0046 (void)m_stack->addWidget(imagePreview); 0047 m_stack->setCurrentWidget(imagePreview); 0048 resize(imagePreview->sizeHint()); 0049 0050 const QStringList mimeTypes = imagePreview->supportedMimeTypes(); 0051 QStringList::ConstIterator it = mimeTypes.begin(); 0052 for (; it != mimeTypes.end(); ++it) { 0053 // qDebug(".... %s", (*it).toLatin1().constData()); 0054 m_previewProviders.insert(*it, imagePreview); 0055 } 0056 } 0057 0058 KPreviewWidgetBase *KFileMetaPreview::findExistingProvider(const QString &mimeType, const QMimeType &mimeInfo) const 0059 { 0060 KPreviewWidgetBase *provider = m_previewProviders.value(mimeType); 0061 if (provider) { 0062 return provider; 0063 } 0064 0065 if (mimeInfo.isValid()) { 0066 // check MIME type inheritance 0067 const QStringList parentMimeTypes = mimeInfo.allAncestors(); 0068 for (const QString &parentMimeType : parentMimeTypes) { 0069 provider = m_previewProviders.value(parentMimeType); 0070 if (provider) { 0071 return provider; 0072 } 0073 } 0074 } 0075 0076 // ### MIME type may be image/* for example, try that 0077 const int index = mimeType.indexOf(QLatin1Char('/')); 0078 if (index > 0) { 0079 provider = m_previewProviders.value(QStringView(mimeType).left(index + 1) + QLatin1Char('*')); 0080 if (provider) { 0081 return provider; 0082 } 0083 } 0084 0085 return nullptr; 0086 } 0087 0088 KPreviewWidgetBase *KFileMetaPreview::previewProviderFor(const QString &mimeType) 0089 { 0090 QMimeDatabase db; 0091 QMimeType mimeInfo = db.mimeTypeForName(mimeType); 0092 0093 // qDebug("### looking for: %s", mimeType.toLatin1().constData()); 0094 // often the first highlighted item, where we can be sure, there is no plugin 0095 // (this "folders reflect icons" is a konq-specific thing, right?) 0096 if (mimeInfo.inherits(QStringLiteral("inode/directory"))) { 0097 return nullptr; 0098 } 0099 0100 KPreviewWidgetBase *provider = findExistingProvider(mimeType, mimeInfo); 0101 if (provider) { 0102 return provider; 0103 } 0104 0105 // qDebug("#### didn't find anything for: %s", mimeType.toLatin1().constData()); 0106 0107 if (s_tryAudioPreview && !mimeType.startsWith(QLatin1String("text/")) && !mimeType.startsWith(QLatin1String("image/"))) { 0108 if (!haveAudioPreview) { 0109 KPreviewWidgetBase *audioPreview = createAudioPreview(m_stack); 0110 if (audioPreview) { 0111 haveAudioPreview = true; 0112 (void)m_stack->addWidget(audioPreview); 0113 const QStringList mimeTypes = audioPreview->supportedMimeTypes(); 0114 QStringList::ConstIterator it = mimeTypes.begin(); 0115 for (; it != mimeTypes.end(); ++it) { 0116 // only add non already handled MIME types 0117 if (m_previewProviders.constFind(*it) == m_previewProviders.constEnd()) { 0118 m_previewProviders.insert(*it, audioPreview); 0119 } 0120 } 0121 } 0122 } 0123 } 0124 0125 // with the new MIME types from the audio-preview, try again 0126 provider = findExistingProvider(mimeType, mimeInfo); 0127 if (provider) { 0128 return provider; 0129 } 0130 0131 // The logic in this code duplicates the logic in PreviewJob. 0132 // But why do we need multiple KPreviewWidgetBase instances anyway? 0133 0134 return nullptr; 0135 } 0136 0137 void KFileMetaPreview::showPreview(const QUrl &url) 0138 { 0139 QMimeDatabase db; 0140 QMimeType mt = db.mimeTypeForUrl(url); 0141 KPreviewWidgetBase *provider = previewProviderFor(mt.name()); 0142 if (provider) { 0143 if (provider != m_stack->currentWidget()) { // stop the previous preview 0144 clearPreview(); 0145 } 0146 0147 m_stack->setEnabled(true); 0148 m_stack->setCurrentWidget(provider); 0149 provider->showPreview(url); 0150 } else { 0151 clearPreview(); 0152 m_stack->setEnabled(false); 0153 } 0154 } 0155 0156 void KFileMetaPreview::clearPreview() 0157 { 0158 if (m_stack->currentWidget()) { 0159 static_cast<KPreviewWidgetBase *>(m_stack->currentWidget())->clearPreview(); 0160 } 0161 } 0162 0163 void KFileMetaPreview::addPreviewProvider(const QString &mimeType, KPreviewWidgetBase *provider) 0164 { 0165 m_previewProviders.insert(mimeType, provider); 0166 } 0167 0168 void KFileMetaPreview::clearPreviewProviders() 0169 { 0170 for (auto it = m_previewProviders.cbegin(); it != m_previewProviders.cend(); ++it) { 0171 m_stack->removeWidget(it.value()); 0172 } 0173 qDeleteAll(m_previewProviders); 0174 m_previewProviders.clear(); 0175 } 0176 0177 // static 0178 KPreviewWidgetBase *KFileMetaPreview::createAudioPreview(QWidget *parent) 0179 { 0180 KPluginMetaData data(QStringLiteral("kfileaudiopreview")); 0181 if (auto plugin = KPluginFactory::instantiatePlugin<KPreviewWidgetBase>(data, parent).plugin) { 0182 plugin->setObjectName(QStringLiteral("kfileaudiopreview")); 0183 return plugin; 0184 } else { 0185 s_tryAudioPreview = false; 0186 return nullptr; 0187 } 0188 } 0189 0190 #include "moc_kfilemetapreview_p.cpp"