widgets/notifications: Remove accidental dependency on being an applet

Followup to https://invent.kde.org/plasma/plasma-mobile/-/merge_requests/558 and removes the dependency on being an applet, as it causes the notifications to break on the lockscreen
This commit is contained in:
Devin Lin 2024-07-28 14:54:14 -04:00
parent 56458bad59
commit 8f79654989
4 changed files with 276 additions and 4 deletions

View file

@ -10,6 +10,7 @@ set(mobileshellplugin_SRCS
components/swipearea.cpp components/swipearea.cpp
notifications/notificationthumbnailer.cpp notifications/notificationthumbnailer.cpp
notifications/notificationfilemenu.cpp notifications/notificationfilemenu.cpp
notifications/notificationfileinfo.cpp
) )
target_include_directories(mobileshellplugin PRIVATE components) target_include_directories(mobileshellplugin PRIVATE components)
target_include_directories(mobileshellplugin PRIVATE notifications) target_include_directories(mobileshellplugin PRIVATE notifications)

View file

@ -0,0 +1,188 @@
/*
SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "notificationfileinfo.h"
#include <QAction>
#include <QMimeDatabase>
#include <KApplicationTrader>
#include <KAuthorized>
#include <KIO/ApplicationLauncherJob>
#include <KIO/JobUiDelegateFactory>
#include <KIO/MimeTypeFinderJob>
#include <KIO/OpenUrlJob>
#include <KLocalizedString>
#include <KNotificationJobUiDelegate>
NotificationFileInfo::NotificationFileInfo(QObject *parent)
: QObject(parent)
{
}
NotificationFileInfo::~NotificationFileInfo() = default;
QUrl NotificationFileInfo::url() const
{
return m_url;
}
void NotificationFileInfo::setUrl(const QUrl &url)
{
if (m_url != url) {
m_url = url;
reload();
Q_EMIT urlChanged(url);
}
}
bool NotificationFileInfo::busy() const
{
return m_busy;
}
void NotificationFileInfo::setBusy(bool busy)
{
if (m_busy != busy) {
m_busy = busy;
Q_EMIT busyChanged(busy);
}
}
int NotificationFileInfo::error() const
{
return m_error;
}
void NotificationFileInfo::setError(int error)
{
if (m_error != error) {
m_error = error;
Q_EMIT errorChanged(error);
}
}
QString NotificationFileInfo::mimeType() const
{
return m_mimeType;
}
QString NotificationFileInfo::iconName() const
{
return m_iconName;
}
QAction *NotificationFileInfo::openAction() const
{
return m_openAction;
}
QString NotificationFileInfo::openActionIconName() const
{
return m_openAction ? m_openAction->icon().name() : QString();
}
void NotificationFileInfo::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 NotificationFileInfo::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(KIO::createDefaultJobUiDelegate(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(KAuthorized::OPEN_WITH));
}
Q_EMIT mimeTypeChanged();
if (emitOpenActionChanged) {
Q_EMIT openActionChanged();
}
if (oldOpenActionIconName != openActionIconName()) {
Q_EMIT openActionIconNameChanged();
}
}
#include "moc_notificationfileinfo.cpp"

View file

@ -0,0 +1,84 @@
/*
SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#pragma once
#include <QObject>
#include <QPointer>
#include <QString>
#include <QUrl>
#include <KService>
#include <qqmlregistration.h>
class QAction;
namespace KIO
{
class MimeTypeFinderJob;
}
class NotificationFileInfo : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
Q_PROPERTY(int error READ error NOTIFY errorChanged)
Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged)
Q_PROPERTY(QString iconName READ iconName NOTIFY mimeTypeChanged)
Q_PROPERTY(QAction *openAction READ openAction NOTIFY openActionChanged)
// QML can't deal with QIcon...
Q_PROPERTY(QString openActionIconName READ openActionIconName NOTIFY openActionIconNameChanged)
public:
explicit NotificationFileInfo(QObject *parent = nullptr);
~NotificationFileInfo() override;
QUrl url() const;
void setUrl(const QUrl &url);
Q_SIGNAL void urlChanged(const QUrl &url);
bool busy() const;
Q_SIGNAL void busyChanged(bool busy);
int error() const;
Q_SIGNAL void errorChanged(bool error);
QString mimeType() const;
Q_SIGNAL void mimeTypeChanged();
QString iconName() const;
Q_SIGNAL void iconNameChanged(const QString &iconName);
QAction *openAction() const;
Q_SIGNAL void openActionChanged();
QString openActionIconName() const;
Q_SIGNAL void openActionIconNameChanged();
private:
void reload();
void mimeTypeFound(const QString &mimeType);
void setBusy(bool busy);
void setError(int error);
QUrl m_url;
QPointer<KIO::MimeTypeFinderJob> m_job;
bool m_busy = false;
int m_error = 0;
QString m_mimeType;
QString m_iconName;
KService::Ptr m_preferredApplication;
QAction *m_openAction = nullptr;
};

View file

@ -9,11 +9,10 @@ import QtQml 2.15
import org.kde.plasma.components 3.0 as PlasmaComponents3 import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.kirigami 2.20 as Kirigami import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.notificationmanager as NotificationManager import org.kde.notificationmanager as NotificationManager
import org.kde.plasma.private.notifications 2.0 as Notifications
ColumnLayout { ColumnLayout {
id: jobItem id: jobItem
@ -59,7 +58,7 @@ ColumnLayout {
spacing: Kirigami.Units.smallSpacing spacing: Kirigami.Units.smallSpacing
Notifications.FileInfo { MobileShell.NotificationFileInfo {
id: fileInfo id: fileInfo
url: jobItem.totalFiles === 1 && jobItem.url ? jobItem.url : "" url: jobItem.totalFiles === 1 && jobItem.url ? jobItem.url : ""
} }
@ -196,7 +195,7 @@ ColumnLayout {
enabled: parent.text === "" enabled: parent.text === ""
} }
Notifications.FileMenu { MobileShell.NotificationFileMenu {
id: otherFileActionsMenu id: otherFileActionsMenu
url: jobItem.url || "" url: jobItem.url || ""
onActionTriggered: jobItem.fileActionInvoked(action) onActionTriggered: jobItem.fileActionInvoked(action)