File indexing completed on 2024-05-12 05:37:07
0001 /* 0002 SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "fileinfo.h" 0008 #include "notifications_debug.h" 0009 0010 #include <QAction> 0011 #include <QMimeDatabase> 0012 0013 #include <KApplicationTrader> 0014 #include <KAuthorized> 0015 #include <KIO/ApplicationLauncherJob> 0016 #include <KIO/JobUiDelegateFactory> 0017 #include <KIO/MimeTypeFinderJob> 0018 #include <KIO/OpenUrlJob> 0019 #include <KLocalizedString> 0020 #include <KNotificationJobUiDelegate> 0021 0022 FileInfo::FileInfo(QObject *parent) 0023 : QObject(parent) 0024 { 0025 } 0026 0027 FileInfo::~FileInfo() = default; 0028 0029 QUrl FileInfo::url() const 0030 { 0031 return m_url; 0032 } 0033 0034 void FileInfo::setUrl(const QUrl &url) 0035 { 0036 if (m_url != url) { 0037 m_url = url; 0038 reload(); 0039 Q_EMIT urlChanged(url); 0040 } 0041 } 0042 0043 bool FileInfo::busy() const 0044 { 0045 return m_busy; 0046 } 0047 0048 void FileInfo::setBusy(bool busy) 0049 { 0050 if (m_busy != busy) { 0051 m_busy = busy; 0052 Q_EMIT busyChanged(busy); 0053 } 0054 } 0055 0056 int FileInfo::error() const 0057 { 0058 return m_error; 0059 } 0060 0061 void FileInfo::setError(int error) 0062 { 0063 if (m_error != error) { 0064 m_error = error; 0065 Q_EMIT errorChanged(error); 0066 } 0067 } 0068 0069 QString FileInfo::mimeType() const 0070 { 0071 return m_mimeType; 0072 } 0073 0074 QString FileInfo::iconName() const 0075 { 0076 return m_iconName; 0077 } 0078 0079 QAction *FileInfo::openAction() const 0080 { 0081 return m_openAction; 0082 } 0083 0084 QString FileInfo::openActionIconName() const 0085 { 0086 return m_openAction ? m_openAction->icon().name() : QString(); 0087 } 0088 0089 void FileInfo::reload() 0090 { 0091 if (!m_url.isValid()) { 0092 return; 0093 } 0094 0095 if (m_job) { 0096 m_job->kill(); 0097 } 0098 0099 setError(0); 0100 0101 // Do a quick guess by file name while we wait for the job to find the mime type 0102 QString guessedMimeType; 0103 0104 // NOTE using QUrl::path() for API that accepts local files is usually wrong 0105 // but here we really only care about the file name and its extension. 0106 const auto type = QMimeDatabase().mimeTypeForFile(m_url.path(), QMimeDatabase::MatchExtension); 0107 if (!type.isDefault()) { 0108 guessedMimeType = type.name(); 0109 } 0110 0111 mimeTypeFound(guessedMimeType); 0112 0113 m_job = new KIO::MimeTypeFinderJob(m_url); 0114 m_job->setAuthenticationPromptEnabled(false); 0115 0116 const QUrl url = m_url; 0117 connect(m_job, &KIO::MimeTypeFinderJob::result, this, [this, url] { 0118 setError(m_job->error()); 0119 if (m_job->error()) { 0120 qCWarning(PLASMA_APPLET_NOTIFICATIONS_DEBUG) << "Failed to determine mime type for" << url << m_job->errorString(); 0121 } else { 0122 mimeTypeFound(m_job->mimeType()); 0123 } 0124 setBusy(false); 0125 }); 0126 0127 setBusy(true); 0128 m_job->start(); 0129 } 0130 0131 void FileInfo::mimeTypeFound(const QString &mimeType) 0132 { 0133 if (m_mimeType == mimeType) { 0134 return; 0135 } 0136 0137 const QString oldOpenActionIconName = openActionIconName(); 0138 0139 bool emitOpenActionChanged = false; 0140 if (!m_openAction) { 0141 m_openAction = new QAction(this); 0142 connect(m_openAction, &QAction::triggered, this, [this] { 0143 auto *job = new KIO::ApplicationLauncherJob(m_preferredApplication); 0144 if (m_preferredApplication) { 0145 job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoErrorHandlingEnabled)); 0146 } else { 0147 // needs KIO::JobUiDelegate for open with handler 0148 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoErrorHandlingEnabled, nullptr /*widget*/)); 0149 } 0150 job->setUrls({m_url}); 0151 job->start(); 0152 }); 0153 emitOpenActionChanged = true; 0154 } 0155 0156 m_mimeType = mimeType; 0157 0158 m_preferredApplication.reset(); 0159 0160 if (!mimeType.isEmpty()) { 0161 const auto type = QMimeDatabase().mimeTypeForName(mimeType); 0162 m_iconName = type.iconName(); 0163 0164 m_preferredApplication = KApplicationTrader::preferredService(mimeType); 0165 } else { 0166 m_iconName.clear(); 0167 } 0168 0169 if (m_preferredApplication) { 0170 m_openAction->setText(i18n("Open with %1", m_preferredApplication->name())); 0171 m_openAction->setIcon(QIcon::fromTheme(m_preferredApplication->icon())); 0172 m_openAction->setEnabled(true); 0173 } else { 0174 m_openAction->setText(i18n("Open with…")); 0175 m_openAction->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); 0176 m_openAction->setEnabled(KAuthorized::authorizeAction(KAuthorized::OPEN_WITH)); 0177 } 0178 0179 Q_EMIT mimeTypeChanged(); 0180 0181 if (emitOpenActionChanged) { 0182 Q_EMIT openActionChanged(); 0183 } 0184 if (oldOpenActionIconName != openActionIconName()) { 0185 Q_EMIT openActionIconNameChanged(); 0186 } 0187 } 0188 0189 #include "moc_fileinfo.cpp"