You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

198 lines
5.1 KiB

/*
Copyright (C) 2021 Kai Uwe Broulik <kde@broulik.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fileinfo.h"
#include <QAction>
#include <QMimeDatabase>
#include <KApplicationTrader>
#include <KAuthorized>
#include <KLocalizedString>
#include <KIO/ApplicationLauncherJob>
#include <KIO/JobUiDelegate>
#include <KIO/MimeTypeFinderJob>
#include <KIO/OpenUrlJob>
#include <KNotificationJobUiDelegate>
FileInfo::FileInfo(QObject *parent)
: QObject(parent)
{
}
FileInfo::~FileInfo() = default;
QUrl FileInfo::url() const
{
return m_url;
}
void FileInfo::setUrl(const QUrl &url)
{
if (m_url != url) {
m_url = url;
reload();
emit urlChanged(url);
}
}
bool FileInfo::busy() const
{
return m_busy;
}
void FileInfo::setBusy(bool busy)
{
if (m_busy != busy) {
m_busy = busy;
emit busyChanged(busy);
}
}
int FileInfo::error() const
{
return m_error;
}
void FileInfo::setError(int error)
{
if (m_error != error) {
m_error = error;
emit errorChanged(error);
}
}
QString FileInfo::mimeType() const
{
return m_mimeType;
}
QString FileInfo::iconName() const
{
return m_iconName;
}
QAction *FileInfo::openAction() const
{
return m_openAction;
}
QString FileInfo::openActionIconName() const
{
return m_openAction ? m_openAction->icon().name() : QString();
}
void FileInfo::reload()
{
if (!m_url.isValid()) {
return;
}
if (m_job) {
m_job->kill();
}
setError(0);
// Do a quick guess by file name while we wait for the job to find the mime type
QString guessedMimeType;
// NOTE using QUrl::path() for API that accepts local files is usually wrong
// but here we really only care about the file name and its extension.
const auto type = QMimeDatabase().mimeTypeForFile(m_url.path(), QMimeDatabase::MatchExtension);
if (!type.isDefault()) {
guessedMimeType = type.name();
}
mimeTypeFound(guessedMimeType);
m_job = new KIO::MimeTypeFinderJob(m_url);
m_job->setAuthenticationPromptEnabled(false);
const QUrl url = m_url;
connect(m_job, &KIO::MimeTypeFinderJob::result, this, [this, url] {
setError(m_job->error());
if (m_job->error()) {
qWarning() << "Failed to determine mime type for" << url << m_job->errorString();
} else {
mimeTypeFound(m_job->mimeType());
}
setBusy(false);
});
setBusy(true);
m_job->start();
}
void FileInfo::mimeTypeFound(const QString &mimeType)
{
if (m_mimeType == mimeType) {
return;
}
const QString oldOpenActionIconName = openActionIconName();
bool emitOpenActionChanged = false;
if (!m_openAction) {
m_openAction = new QAction(this);
connect(m_openAction, &QAction::triggered, this, [this] {
auto *job = new KIO::ApplicationLauncherJob(m_preferredApplication);
if (m_preferredApplication) {
job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoErrorHandlingEnabled));
} else {
// needs KIO::JobUiDelegate for open with handler
job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoErrorHandlingEnabled, nullptr /*widget*/));
}
job->setUrls({m_url});
job->start();
});
emitOpenActionChanged = true;
}
m_mimeType = mimeType;
m_preferredApplication.reset();
if (!mimeType.isEmpty()) {
const auto type = QMimeDatabase().mimeTypeForName(mimeType);
m_iconName = type.iconName();
m_preferredApplication = KApplicationTrader::preferredService(mimeType);
} else {
m_iconName.clear();
}
if (m_preferredApplication) {
m_openAction->setText(i18n("Open with %1", m_preferredApplication->name()));
m_openAction->setIcon(QIcon::fromTheme(m_preferredApplication->icon()));
m_openAction->setEnabled(true);
} else {
m_openAction->setText(i18n("Open with…"));
m_openAction->setIcon(QIcon::fromTheme(QStringLiteral("system-run")));
m_openAction->setEnabled(KAuthorized::authorizeAction(QStringLiteral("openwith")));
}
Q_EMIT mimeTypeChanged();
if (emitOpenActionChanged) {
Q_EMIT openActionChanged();
}
if (oldOpenActionIconName != openActionIconName()) {
Q_EMIT openActionIconNameChanged();
}
}