Commit 73c55284 authored by Kai Uwe Broulik's avatar Kai Uwe Broulik 🍇

WIP: libnotificationmanager and new notification applet

libnotificationmanager provides a proper notification model situation similar
to libtaskmanager. There is also a new notification applet implementing the
suggestions and VDG mockups in the wiki

NOTE: the notification dataengine is defunct in this branch, so while the applet
(for now) installs as "new notifications", the old applet will stop working when
you use this. The dataengine will eventually be restored (famous last words)
for compatibility but using the NotificationServer singleton introduced in
libnotificationmanager.

The applet can show notifications, they expire, can be closed, and their
default action invoked. Still heavily WIP and API subject to change.

[1] https://community.kde.org/Plasma/Notifications
parent 14b23600
......@@ -140,6 +140,7 @@ add_subdirectory(libdbusmenuqt)
add_subdirectory(appmenu)
add_subdirectory(libtaskmanager)
add_subdirectory(libnotificationmanager)
add_subdirectory(libcolorcorrect)
add_subdirectory(components)
......
......@@ -18,5 +18,6 @@ if(NOT WIN32)
# #notifications
# #should compile also on windows? (even if doesn't really make sense)
add_subdirectory(notifications)
add_subdirectory(newnotifications)
add_subdirectory(systemtray)
endif()
add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.notifications\")
set(notificationapplet_SRCS
notificationapplet.cpp
)
add_library(plasma_applet_newnotifications MODULE ${notificationapplet_SRCS}) # FIXME
kcoreaddons_desktop_to_json(plasma_applet_newnotifications package/metadata.desktop) # FIXME
target_link_libraries(plasma_applet_newnotifications # FIXME
# shouldnt require it as it's all QML, isn't it?
#PW::NotificationManager
KF5::I18n
KF5::Plasma)
install(TARGETS plasma_applet_newnotifications DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/applets) # FIXME
plasma_install_package(package org.kde.plasma.newnotifications)
#! /usr/bin/env bash
$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_org.kde.plasma.notifications.pot
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "notificationapplet.h"
NotificationApplet::NotificationApplet(QObject *parent, const QVariantList &data)
: Plasma::Applet(parent, data)
{
}
NotificationApplet::~NotificationApplet() = default;
void NotificationApplet::init()
{
}
void NotificationApplet::configChanged()
{
}
K_EXPORT_PLASMA_APPLET_WITH_JSON(icon, NotificationApplet, "metadata.json")
#include "notificationapplet.moc"
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <Plasma/Applet>
class NotificationApplet : public Plasma::Applet
{
Q_OBJECT
public:
explicit NotificationApplet(QObject *parent, const QVariantList &data);
~NotificationApplet() override;
void init() override;
void configChanged() override;
private:
};
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
</group>
</kcfg>
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
MouseArea {
id: compactRoot
property bool wasExpanded: false
onPressed: wasExpanded = plasmoid.expanded
onClicked: plasmoid.expanded = !wasExpanded
PlasmaCore.Svg {
id: notificationSvg
imagePath: "icons/notification"
colorGroup: PlasmaCore.ColorScope.colorGroup
}
PlasmaCore.SvgItem {
anchors.centerIn: parent
width: units.roundToIconSize(Math.min(parent.width, parent.height))
height: width
svg: notificationSvg
// TODO icon depending on unread notifications, active jobs, etc
// TODO use States for the icon handling including animation and what not?
elementId: {
return "notification-disabled"
}
// FIXME just so I can tell the two apart in system tray
Text {
anchors.fill: parent
text: "N" // "New"
}
}
// TODO progress
// would be lovely if we could get back the circular pie thing back we had in Plasma < 4.10
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as Components
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.notificationmanager 1.0 as NotificationManager
Item {
id: fullRoot
// FIXME use PlasmaComponents 3 everywhere?
PlasmaExtras.ScrollArea {
anchors.fill: parent
ListView {
id: list
// FIXME use history model or the finalized API with NotificationModel instance
// that you can tel what you want (filtered, sorted by, etc), cf. TasksModel
model: NotificationManager.NotificationModel
delegate: NotificationDelegate {
width: list.width
summary: model.summary
body: model.body
icon: model.iconName || model.image
}
}
}
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
NotificationItem {
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.notificationmanager 1.0 as NotificationManager
// TODO turn into MouseArea or MEL for expand/collapse
RowLayout {
id: notificationItem
property alias icon: iconItem.source
property alias text: label.text
property alias ageText: ageLabel.text
property alias closable: closeButton.visible
// TODO property bool/alias configurable
signal closeClicked
spacing: units.smallSpacing
PlasmaCore.IconItem {
id: iconItem
Layout.preferredWidth: units.iconSizes.small
Layout.preferredHeight: units.iconSizes.small
}
PlasmaExtras.DescriptiveLabel {
id: label
Layout.fillWidth: true
textFormat: Text.PlainText
// font.pointSize: theme.smallestFont?
}
// TODO number of notifications in group, expand collapse arrow
PlasmaExtras.DescriptiveLabel {
id: ageLabel
}
PlasmaComponents.ToolButton {
id: closeButton
iconName: "window-close" // FIXME
visible: false
}
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.notificationmanager 1.0 as NotificationManager
// TODO turn into MouseArea or MEL for "default action"
// or should that be done where the Popup/ListView is?
ColumnLayout {
id: notificationItem
property alias summary: summaryLabel.text
property alias ageText: ageLabel.text
property alias closable: closeButton.visible
// TODO property bool/alias configurable
property alias body: bodyLabel.text
property alias icon: iconItem.source
property var actionNames: []
property var actionLabels: []
signal closeClicked
signal actionInvoked(string actionName)
spacing: 0
RowLayout {
Layout.fillWidth: true
spacing: units.smallSpacing
PlasmaExtras.Heading {
id: summaryLabel
Layout.fillWidth: true
textFormat: Text.PlainText
wrapMode: Text.NoWrap
elide: Text.ElideRight
level: 4
}
PlasmaExtras.DescriptiveLabel {
id: ageLabel
}
PlasmaComponents.ToolButton {
id: closeButton
iconName: "window-close" // FIXME
visible: false
onClicked: notificationItem.closeClicked()
}
}
RowLayout {
Layout.fillWidth: true
spacing: units.smallSpacing
// FIXME make selectable, scrollable, links clickable, etc
PlasmaComponents.Label {
id: bodyLabel
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
maximumLineCount: 10
textFormat: Text.StyledText
wrapMode: Text.WordWrap
elide: Text.ElideRight
}
PlasmaCore.IconItem {
id: iconItem
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: units.iconSizes.large
Layout.preferredHeight: units.iconSizes.large
usesPlasmaTheme: false
visible: valid
}
}
RowLayout {
Layout.fillWidth: true
visible: actionRepeater.count > 0
spacing: units.smallSpacing
Repeater {
id: actionRepeater
model: notificationItem.actionNames
PlasmaComponents.ToolButton {
text: notificationItem.actionLabels[index]
onClicked: notificationItem.actionInvoked(modelData)
}
}
Item { // compact layout
Layout.fillWidth: true
}
}
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as Components
PlasmaCore.Dialog {
id: notificationPopup
property int notificationId
property string summary
property string body
property var icon
property int timeout
property bool hasDefaultAction
signal closeClicked
signal defaultActionInvoked
signal actionInvoked(string actionName)
signal expired
location: PlasmaCore.Types.Floating
type: PlasmaCore.Dialog.Notification
flags: Qt.WindowDoesNotAcceptFocus
visible: false
mainItem: MouseArea {
id: area
width: units.gridUnit * 20//notificationItem.implicitWidth
height: notificationItem.implicitHeight
hoverEnabled: true
cursorShape: hasDefaultAction ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: hasDefaultAction ? Qt.LeftButton : Qt.NoButton
onClicked: notificationPopup.defaultActionInvoked()
Timer {
id: timer
interval: notificationPopup.timeout
running: !area.containsMouse && notificationPopup.timeout > 0
onTriggered: notificationPopup.expired()
}
NotificationItem {
id: notificationItem
width: parent.width
summary: notificationPopup.summary
body: notificationPopup.body
icon: notificationPopup.icon
closable: true // TODO with grouping and what not
onCloseClicked: notificationPopup.closeClicked()
}
// FIXME so I can see whether hover handling actually works
Rectangle {
anchors {
right: parent.right
}
color: "#f0f"
width: 20
height: 20
visible: timer.running
}
Rectangle {
anchors {
right: parent.right
rightMargin: 20
}
width: 20
height: 20
color: "#f00"
visible: area.containsMouse
}
}
}
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
import QtQuick 2.8
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as Components
import org.kde.kquickcontrolsaddons 2.0
import org.kde.notificationmanager 1.0 as NotificationManager
Item {
id: root
// TODO status depending on unread notifications
//Plasmoid.status:
// TODO tooltip depending on unread and persistent notifications, running jobs, etc?
//Plasmoid.toolTipSubText:
Plasmoid.compactRepresentation: CompactRepresentation {}
Plasmoid.fullRepresentation: FullRepresentation {}
Plasmoid.onLocationChanged: Qt.callLater(positionPopups)
Plasmoid.onAvailableScreenRectChanged: Qt.callLater(positionPopups)
// mapping of notificationId -> NotificationPopup instance