From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id D9098138A1F for ; Tue, 29 Apr 2014 22:47:47 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 6015CE0807; Tue, 29 Apr 2014 22:47:45 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 8BEF4E0807 for ; Tue, 29 Apr 2014 22:47:44 +0000 (UTC) Received: from spoonbill.gentoo.org (spoonbill.gentoo.org [81.93.255.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 209593400FF for ; Tue, 29 Apr 2014 22:47:43 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by spoonbill.gentoo.org (Postfix) with ESMTP id EB19E1818D for ; Tue, 29 Apr 2014 22:47:39 +0000 (UTC) From: "Andreas Hüttel" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Andreas Hüttel" Message-ID: <1398811654.e8643b94912d0327564600ee9196efebc06394ec.dilfridge@gentoo> Subject: [gentoo-commits] dev/dilfridge:master commit in: kde-base/plasma-workspace/files/, kde-base/plasma-workspace/ X-VCS-Repository: dev/dilfridge X-VCS-Files: kde-base/plasma-workspace/Manifest kde-base/plasma-workspace/files/oldnotify.patch kde-base/plasma-workspace/files/plasma-workspace-4.10.1-noplasmalock.patch kde-base/plasma-workspace/metadata.xml kde-base/plasma-workspace/plasma-workspace-4.11.2-r2.ebuild X-VCS-Directories: kde-base/plasma-workspace/files/ kde-base/plasma-workspace/ X-VCS-Committer: dilfridge X-VCS-Committer-Name: Andreas Hüttel X-VCS-Revision: e8643b94912d0327564600ee9196efebc06394ec X-VCS-Branch: master Date: Tue, 29 Apr 2014 22:47:39 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 8ff49c34-432f-4289-a33d-1224e2c6a340 X-Archives-Hash: 5dda77f930058e204d9d4c50ab38cde4 commit: e8643b94912d0327564600ee9196efebc06394ec Author: Andreas K. Huettel (dilfridge) gentoo org> AuthorDate: Tue Apr 29 22:47:09 2014 +0000 Commit: Andreas Hüttel gentoo org> CommitDate: Tue Apr 29 22:47:34 2014 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=dev/dilfridge.git;a=commit;h=e8643b94 [kde-base/plasma-workspace] clean up --- kde-base/plasma-workspace/Manifest | 1 - kde-base/plasma-workspace/files/oldnotify.patch | 8557 -------------------- .../plasma-workspace-4.10.1-noplasmalock.patch | 11 - kde-base/plasma-workspace/metadata.xml | 9 - .../plasma-workspace-4.11.2-r2.ebuild | 125 - 5 files changed, 8703 deletions(-) diff --git a/kde-base/plasma-workspace/Manifest b/kde-base/plasma-workspace/Manifest deleted file mode 100644 index 48cd387..0000000 --- a/kde-base/plasma-workspace/Manifest +++ /dev/null @@ -1 +0,0 @@ -DIST kde-workspace-4.11.2.tar.xz 13870828 SHA256 260e46f30b8faaa1ad834d9fa69465ab1f565cb18a174bd814327083bb28d917 SHA512 8d034e147ebb630941465b77e302aa2385c2f1419847e8a65ac19d445846435b61d78323fdb094b9a71089ab183c96af141db93c7c9c53a9b30c84ae69bddf2a WHIRLPOOL 0db07ef64caf873c0aa6398a28b92fdc9334eb04897c9a71ed0e3c54ad77e9e8dc23b13b6343844650a2ec7c2784664185f01cf64424d694a8c33167affb5720 diff --git a/kde-base/plasma-workspace/files/oldnotify.patch b/kde-base/plasma-workspace/files/oldnotify.patch deleted file mode 100644 index c4c5c3b..0000000 --- a/kde-base/plasma-workspace/files/oldnotify.patch +++ /dev/null @@ -1,8557 +0,0 @@ -diff --git a/plasma/generic/applets/notifications/CMakeLists.txt b/plasma/generic/applets/notifications/CMakeLists.txt -index 02afb93..a38fe47 100644 ---- a/plasma/generic/applets/notifications/CMakeLists.txt -+++ b/plasma/generic/applets/notifications/CMakeLists.txt -@@ -1,2 +1,47 @@ --installPackage(. org.kde.notifications) -+project(plasma-notifications) -+#TODO: see if is still the case -+# 'engineName' causes error -+kde4_no_enable_final(plasma-notifications) - -+set(notifications_SRCS -+ -+ core/notificationsmanager.cpp -+ core/protocol.cpp -+ core/notification.cpp -+ core/completedjobnotification.cpp -+ core/job.cpp -+ -+ protocols/notifications/dbusnotificationprotocol.cpp -+ protocols/notifications/dbusnotification.cpp -+ -+ protocols/jobs/dbusjobprotocol.cpp -+ protocols/jobs/dbusjob.cpp -+ -+ ui/busywidget.cpp -+ ui/notifications.cpp -+ ui/notificationwidget.cpp -+ ui/jobtotalswidget.cpp -+ ui/jobwidget.cpp -+ ui/notificationgroup.cpp -+ ui/notificationstack.cpp -+ ui/stackdialog.cpp -+ ) -+ -+kde4_add_ui_files(notifications_SRCS -+ ui/notificationsconfig.ui) -+ -+ -+include (CheckLibraryExists) -+check_library_exists (Xss XScreenSaverQueryInfo "" HAVE_LIBXSS) -+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config-notifications.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-notifications.h) -+IF (HAVE_LIBXSS) -+ SET (IDLE_DETECTION_LIB "Xss") -+ENDIF (HAVE_LIBXSS) -+ -+ -+kde4_add_plugin(plasma_applet_notifications ${notifications_SRCS}) -+include_directories(${CMAKE_SOURCE_DIR}) -+target_link_libraries(plasma_applet_notifications ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${X11_LIBRARIES} ${X11_Xrender_LIB} ${X11_Xfixes_LIB} ${X11_Xdamage_LIB} ${X11_Xcomposite_LIB} ${KDE4_SOLID_LIBS} ${IDLE_DETECTION_LIB}) -+ -+install(TARGETS plasma_applet_notifications DESTINATION ${PLUGIN_INSTALL_DIR}) -+install(FILES plasma-applet-notifications.desktop DESTINATION ${SERVICES_INSTALL_DIR}) -diff --git a/plasma/generic/applets/notifications/Messages.sh b/plasma/generic/applets/notifications/Messages.sh -old mode 100644 -new mode 100755 -index bd3e2d9..5582bc6 ---- a/plasma/generic/applets/notifications/Messages.sh -+++ b/plasma/generic/applets/notifications/Messages.sh -@@ -1,5 +1,4 @@ - #! /usr/bin/env bash --$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp --$XGETTEXT `find . -name \*.qml` -L Java -o $podir/plasma_applet_org.kde.notifications.pot --$XGETTEXT rc.cpp -jo $podir/plasma_applet_org.kde.notifications.pot -+$EXTRACTRC `find . -name '*.ui'` >> rc.cpp -+$XGETTEXT `find . -name '*.cpp'` -o $podir/plasma_applet_notifications.pot - rm -f rc.cpp -diff --git a/plasma/generic/applets/notifications/config-notifications.h.cmake b/plasma/generic/applets/notifications/config-notifications.h.cmake -new file mode 100644 -index 0000000..aac3113 ---- /dev/null -+++ b/plasma/generic/applets/notifications/config-notifications.h.cmake -@@ -0,0 +1 @@ -+#cmakedefine HAVE_LIBXSS -diff --git a/plasma/generic/applets/notifications/contents/config/main.xml b/plasma/generic/applets/notifications/contents/config/main.xml -deleted file mode 100644 -index 399159d..0000000 ---- a/plasma/generic/applets/notifications/contents/config/main.xml -+++ /dev/null -@@ -1,23 +0,0 @@ -- -- -- -- -- -- -- -- -1,-1 -- -- -- -- true -- -- -- -- true -- -- -- -- -diff --git a/plasma/generic/applets/notifications/contents/ui/JobDelegate.qml b/plasma/generic/applets/notifications/contents/ui/JobDelegate.qml -deleted file mode 100644 -index e94866d..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/JobDelegate.qml -+++ /dev/null -@@ -1,310 +0,0 @@ --/* -- * Copyright 2011 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.0 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.plasma.graphicswidgets 0.1 as PlasmaWidgets --import org.kde.qtextracomponents 0.1 -- --PlasmaComponents.ListItem { -- id: notificationItem -- width: popupFlickable.width -- -- property int toolIconSize: theme.smallMediumIconSize -- property int layoutSpacing: 4 -- -- function getData(data, name, defaultValue) { -- return data[modelData] ? (data[modelData][name] ? data[modelData][name] : defaultValue) : defaultValue; -- } -- -- property string labelName0: getData(jobsSource.data, "labelName0", '') -- property string label0: getData(jobsSource.data, "label0", '') -- property string labelName1: getData(jobsSource.data, "labelName1", '') -- property string label1: getData(jobsSource.data, "label1", '') -- property string jobstate: getData(jobsSource.data, "state", '') -- property int eta: getData(jobsSource.data, "eta", 0) -- property string speed: getData(jobsSource.data, "speed", '') -- -- Column { -- spacing: notificationItem.layoutSpacing -- width: parent.width -- PlasmaComponents.Label { -- text: getData(jobsSource.data, "infoMessage", '') -- font.bold: true -- color: theme.textColor -- anchors.horizontalCenter: parent.horizontalCenter -- } -- Grid { -- anchors { -- left: parent.left -- right: parent.right -- rightMargin: notificationItem.layoutSpacing -- } -- spacing: notificationItem.layoutSpacing -- rows: 4 -- columns: 2 -- -- PlasmaComponents.Label { -- id: labelName0Text -- text: labelName0 ? i18n("%1:", labelName0) : '' -- width: Math.max(paintedWidth, labelName1Text.paintedWidth) -- horizontalAlignment: Text.AlignRight -- visible: labelName0 != '' -- } -- PlasmaComponents.Label { -- id: label0Text -- text: label0 ? label0 : '' -- width: parent.width - labelName0Text.width -- elide: Text.ElideMiddle -- visible: label0 != '' -- -- PlasmaCore.ToolTip { -- target: label0Text -- subText: label0Text.truncated ? label0 : "" -- } -- -- } -- PlasmaComponents.Label { -- id: labelName1Text -- text: labelName1 ? i18n("%1:", labelName1) : '' -- width: Math.max(paintedWidth, labelName0Text.paintedWidth) -- horizontalAlignment: Text.AlignRight -- visible: labelName1 != '' -- } -- PlasmaComponents.Label { -- id: label1Text -- text: label1 ? label1 : '' -- width: parent.width - labelName0Text.width -- elide: Text.ElideMiddle -- visible: label1 != '' -- -- PlasmaCore.ToolTip { -- target: label1Text -- subText: label1Text.truncated ? label1 : "" -- } -- } -- QIconItem { -- icon: getData(jobsSource.data, "appIconName", '') -- width: notificationItem.toolIconSize -- height: width -- anchors { -- verticalCenter: progressItem.verticalCenter -- right: progressItem.left -- rightMargin: notificationItem.layoutSpacing -- } -- } -- Item { -- id: progressItem -- width: parent.width - labelName0Text.width -- height: childrenRect.height -- PlasmaComponents.ProgressBar { -- width: parent.width - pauseButton.width*2 - theme.largeIconSize - notificationItem.layoutSpacing*3 -- height: 16 -- orientation: Qt.Horizontal -- minimumValue: 0 -- maximumValue: 100 -- //percentage doesn't always exist, so doesn't get in the model -- value: getData(jobsSource.data, "percentage", 0) -- -- anchors { -- left: parent.left -- right: buttonsRow.left -- verticalCenter: parent.verticalCenter -- rightMargin: notificationItem.layoutSpacing -- } -- } -- Row { -- id: buttonsRow -- spacing: notificationItem.layoutSpacing -- anchors.right: parent.right -- PlasmaComponents.ToolButton { -- id: pauseButton -- width: notificationItem.toolIconSize -- height: width -- iconSource: jobstate == "suspended" ? "media-playback-start" : "media-playback-pause" -- flat: false -- onClicked: { -- var operationName = "suspend" -- if (jobstate == "suspended") { -- operationName = "resume" -- } -- var service = jobsSource.serviceForSource(modelData) -- var operation = service.operationDescription(operationName) -- service.startOperationCall(operation) -- } -- } -- PlasmaComponents.ToolButton { -- id: stopButton -- width: notificationItem.toolIconSize -- height: width -- iconSource: "media-playback-stop" -- flat: false -- onClicked: { -- var service = jobsSource.serviceForSource(modelData) -- var operation = service.operationDescription("stop") -- service.startOperationCall(operation) -- } -- } -- } -- } -- PlasmaComponents.ToolButton { -- id: expandButton -- width: notificationItem.toolIconSize -- height: width -- flat: false -- iconSource: checked ? "list-remove" : "list-add" -- checkable: true -- anchors { -- right: speedLabel.left -- rightMargin: notificationItem.layoutSpacing -- verticalCenter: speedLabel.verticalCenter -- } -- } -- PlasmaComponents.Label { -- id: speedLabel -- text: eta > 0 ? i18nc("Speed and estimated time to completition", "%1 (%2 remaining)", speed, locale.prettyFormatDuration(eta)) : speed -- } -- } -- -- -- Item { -- id: detailsItem -- state: expandButton.checked ? "expanded" : "collapsed" -- anchors { -- left: parent.left -- right: parent.right -- leftMargin: speedLabel.x -- } -- property Item contentsItem -- Component { -- id: detailsComponent -- Column { -- id: detailsColumn -- anchors { -- left: parent.left -- right: parent.right -- } -- -- function localizeProcessedAmount(id) { -- //if bytes localise the unit -- if (jobsSource.data[modelData]["processedUnit"+id] == "bytes") { -- return i18nc("How much many bytes (or whether unit in the locale has been copied over total", "%1 of %2", -- locale.formatByteSize(jobsSource.data[modelData]["processedAmount"+id]), -- locale.formatByteSize(jobsSource.data[modelData]["totalAmount"+id])) -- //else print something only if is interesting data (ie more than one file/directory etc to copy -- } else if (jobsSource.data[modelData]["totalAmount"+id] > 1) { -- return i18n( "%1 of %2 %3", -- jobsSource.data[modelData]["processedAmount"+id], -- jobsSource.data[modelData]["totalAmount"+id], -- jobsSource.data[modelData]["processedUnit"+id]) -- } else { -- return "" -- } -- } -- PlasmaComponents.Label { -- text: jobsSource.data[modelData] ? detailsColumn.localizeProcessedAmount(0) : "" -- anchors.left: parent.left -- visible: text != "" -- } -- PlasmaComponents.Label { -- text: jobsSource.data[modelData] ? detailsColumn.localizeProcessedAmount(1) : "" -- anchors.left: parent.left -- visible: text != "" -- } -- PlasmaComponents.Label { -- text: jobsSource.data[modelData] ? detailsColumn.localizeProcessedAmount(2) : "" -- anchors.left: parent.left -- visible: text != "" -- } -- PlasmaWidgets.SignalPlotter { -- id: plotter -- width: parent.width -- useAutoRange: true -- showVerticalLines: false -- unit: i18n("KiB/s") -- height: theme.defaultFont.mSize.height * 5 -- Component.onCompleted: plotter.addPlot(theme.highlightColor) -- } -- Connections { -- target: jobsSource -- onDataChanged: { -- plotter.addSample([jobsSource.data[modelData]["numericSpeed"]/1000]) -- } -- } -- } -- } -- -- states: [ -- State { -- name: "expanded" -- PropertyChanges { -- target: detailsItem -- height: detailsItem.childrenRect.height -- } -- }, -- State { -- name: "collapsed" -- PropertyChanges { -- target: detailsItem -- height: 0 -- } -- } -- ] -- transitions : [ -- Transition { -- from: "collapsed" -- to: "expanded" -- SequentialAnimation { -- ScriptAction { -- script: { -- detailsItem.visible = true -- detailsItem.clip = true -- //create the contents if they don't exist yet -- if (!detailsItem.contentsItem) { -- detailsItem.contentsItem = detailsComponent.createObject(detailsItem) -- } -- } -- } -- NumberAnimation { -- duration: 250 -- properties: "height" -- easing: PropertyAnimation.EaseInOut -- } -- ScriptAction {script: detailsItem.clip = false} -- } -- }, -- Transition { -- from: "expanded" -- to: "collapsed" -- SequentialAnimation { -- ScriptAction {script: detailsItem.clip = true} -- NumberAnimation { -- duration: 250 -- properties: "height" -- easing: PropertyAnimation.EaseInOut -- } -- //TODO: delete the details? -- ScriptAction {script: detailsItem.visible = false} -- } -- } -- ] -- } -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/Jobs.qml b/plasma/generic/applets/notifications/contents/ui/Jobs.qml -deleted file mode 100644 -index 7e2f2a2..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/Jobs.qml -+++ /dev/null -@@ -1,105 +0,0 @@ --/* -- * Copyright 2012 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents -- --Column { -- id: jobsRoot -- property alias count: jobsRepeater.count -- anchors { -- left: parent.left -- right: parent.right -- } -- -- PlasmaCore.DataSource { -- id: jobsSource -- engine: "applicationjobs" -- interval: 0 -- -- onSourceAdded: { -- connectSource(source); -- } -- property variant runningJobs -- -- onSourceRemoved: { -- if (!notifications) { -- return -- } -- var message = runningJobs[source]["label1"] ? runningJobs[source]["label1"] : runningJobs[source]["label0"] -- notifications.addNotification( -- source, -- runningJobs[source]["appIconName"], -- 0, -- runningJobs[source]["appName"], -- i18n("%1 [Finished]", runningJobs[source]["infoMessage"]), -- message, -- 0, -- 0, -- [{"id": message, "text": i18n("Open")}]) -- delete runningJobs[source] -- } -- Component.onCompleted: { -- jobsSource.runningJobs = new Object -- connectedSources = sources -- } -- onNewData: { -- var jobs = runningJobs -- jobs[sourceName] = data -- runningJobs = jobs -- } -- onDataChanged: { -- var total = 0 -- for (var i = 0; i < sources.length; ++i) { -- if (jobsSource.data[sources[i]]["percentage"]) { -- total += jobsSource.data[sources[i]]["percentage"] -- } -- } -- -- total /= sources.length -- notificationsApplet.globalProgress = total/100 -- } -- } -- -- Title { -- visible: jobsRepeater.count > 0 && notifications && notifications.count > 0 -- text: i18n("Transfers") -- } -- PlasmaComponents.ListItem { -- visible: jobsRepeater.count > 1 -- PlasmaComponents.ProgressBar { -- anchors { -- verticalCenter: parent.verticalCenter -- left: parent.left -- right: parent.right -- } -- minimumValue: 0 -- maximumValue: 100 -- value: notificationsApplet.globalProgress * 100 -- } -- } -- Repeater { -- id: jobsRepeater -- model: jobsSource.sources -- delegate: JobDelegate { -- toolIconSize: notificationsApplet.toolIconSize -- } -- } --} -\ No newline at end of file -diff --git a/plasma/generic/applets/notifications/contents/ui/LastNotificationPopup.qml b/plasma/generic/applets/notifications/contents/ui/LastNotificationPopup.qml -deleted file mode 100644 -index 26bce0f..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/LastNotificationPopup.qml -+++ /dev/null -@@ -1,414 +0,0 @@ --/*************************************************************************** -- * Copyright 2011 Davide Bettio * -- * Copyright 2011 Marco Martin * -- * * -- * This program is free software; you can redistribute it and/or modify * -- * it under the terms of the GNU Library General Public License as published by * -- * the Free Software Foundation; either version 2 of the License, or * -- * (at your option) any later version. * -- * * -- * 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 Library General Public License for more details. * -- * * -- * You should have received a copy of the GNU Library General Public License * -- * along with this program; if not, write to the * -- * Free Software Foundation, Inc., * -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -- ***************************************************************************/ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.qtextracomponents 0.1 --import org.kde.plasma.extras 0.1 as PlasmaExtras -- -- --PlasmaCore.Dialog { -- id: lastNotificationPopup -- -- property variant savedPos -- property bool customPosition: false -- -- onHeightChanged: setCustomPosition(lastNotificationPopup.savedPos, false) -- onWidthChanged: setCustomPosition(lastNotificationPopup.savedPos, false) -- -- function popup(notification) -- { -- if (!lastNotificationPopup.visible) { -- lastNotificationsModel.clear() -- } -- lastNotificationsModel.append(notification) -- -- setCustomPosition(lastNotificationPopup.savedPos, false) -- -- lastNotificationPopup.visible = true -- lastNotificationTimer.interval = Math.max(4000, Math.min(60*1000, notificationsModel.get(0).expireTimeout)) -- notificationsView.currentIndex = lastNotificationsModel.count - 1 -- lastNotificationTimer.restart() -- mainItem.buttonPressed = false -- } -- -- function setCustomPosition(pos, writeConfig) -- { -- var popupPos = lastNotificationPopup.popupPosition(notificationIcon, Qt.AlignCenter) -- var finalPos -- -- //custom -- if ((pos.x >= 0 || pos.y >= 0) && -- (Math.abs(popupPos.x - pos.x) > 40 || -- Math.abs(popupPos.y - pos.y) > 40)) { -- finalPos = pos -- if (writeConfig) { -- plasmoid.writeConfig("CustomPosition", pos) -- lastNotificationPopup.savedPos = pos -- lastNotificationPopup.customPosition = true -- } -- } else { -- finalPos = popupPos -- if (writeConfig) { -- plasmoid.writeConfig("CustomPosition", QPoint(-1,-1)) -- lastNotificationPopup.savedPos = QPoint(-1,-1) -- lastNotificationPopup.customPosition = false -- } -- } -- lastNotificationPopup.x = finalPos.x -- lastNotificationPopup.y = finalPos.y -- } -- -- location: customPosition ? Floating : plasmoid.location -- windowFlags: Qt.WindowStaysOnTopHint -- Component.onCompleted: { -- setAttribute(Qt.WA_X11NetWmWindowTypeDock, true) -- -- lastNotificationPopup.savedPos = plasmoid.readConfig("CustomPosition") -- setCustomPosition(lastNotificationPopup.savedPos, true) -- plasmoid.popupEvent.connect(lastNotificationPopup.popupEvent) -- } -- -- function popupEvent(popupShowing) -- { -- if(popupShowing) { -- lastNotificationPopup.visible = false -- } -- } -- -- mainItem: MouseEventListener { -- id: mainItem -- width: maximumWidth -- height: maximumHeight -- property int maximumWidth: theme.defaultFont.mSize.width * 35 -- property int maximumHeight: theme.defaultFont.mSize.width * 10 -- property int minimumWidth: maximumWidth -- property int minimumHeight: maximumHeight -- -- property int startX: 0 -- property int startY: 0 -- property int startScreenX: 0 -- property int startScreenY: 0 -- hoverEnabled: true -- property bool buttonPressed: false -- -- state: "controlsHidden" -- onContainsMouseChanged: { -- if (containsMouse) { -- mainItem.state = "controlsShown" -- lastNotificationTimer.running = false -- } else { -- mainItem.state = "controlsHidden" -- lastNotificationTimer.restart() -- } -- } -- onPressed: { -- startX = mouse.x + lastNotificationPopup.margins.left -- startY = mouse.y + lastNotificationPopup.margins.top -- startScreenX = mouse.screenX -- startScreenY = mouse.screenY -- lastNotificationTimer.running = false -- } -- onReleased: { -- //FIXME: bind startdragdistance -- if ((navigationButtonsColumn.visible && mouse.x < navigationButtonsColumn.width) || -- buttonPressed || -- Math.sqrt(Math.pow(startScreenX - mouse.screenX, 2) + Math.pow(startScreenY - mouse.screenY, 2)) > 4) { -- } else { -- lastNotificationPopup.visible = false -- } -- -- setCustomPosition(QPoint(Math.max(0, mouse.screenX - startX), Math.max(mouse.screenY - startY)), true) -- } -- onPositionChanged: { -- lastNotificationPopup.x = Math.max(0, mouse.screenX - startX) -- lastNotificationPopup.y = Math.max(0, mouse.screenY - startY) -- } -- onWheelMoved: { -- if (notificationsView.moving) { -- return -- } -- -- if (wheel.delta > 0) { -- notificationsView.currentIndex = Math.max(0, notificationsView.currentIndex-1) -- } else { -- notificationsView.currentIndex = Math.min(notificationsView.count-1, notificationsView.currentIndex+1) -- } -- } -- -- Timer { -- id: lastNotificationTimer -- interval: 4000 -- repeat: false -- running: false -- onTriggered: lastNotificationPopup.visible = false -- } -- -- ListView { -- id: notificationsView -- clip: true -- snapMode: ListView.SnapOneItem -- orientation: ListView.Horizontal -- anchors.fill: parent -- model: ListModel { -- id: lastNotificationsModel -- } -- interactive: false -- delegate: Item { -- height: notificationsView.height -- width: notificationsView.width -- -- PlasmaComponents.Label { -- id: titleLabel -- text: model.summary -- //font.weight: Font.Bold -- visible: model.summary.length > 0 -- height: model.summary.length > 0 ? paintedHeight : 0 -- horizontalAlignment: Text.AlignHCenter -- color: theme.textColor -- elide: Text.ElideRight -- anchors { -- left: appIconItem.y > y + height ? parent.left : appIconItem.right -- right: parent.right -- rightMargin: settingsButton.visible ? settingsButton.width + closeButton.width : closeButton.width -- top: parent.top -- topMargin: 6 -- leftMargin: 6 -- } -- onLinkActivated: plasmoid.openUrl(link) -- } -- -- QIconItem { -- id: appIconItem -- icon: model.appIcon -- width: (model.appIcon.length > 0 || imageItem.visible) ? theme.largeIconSize : 0 -- height: theme.largeIconSize -- visible: !imageItem.visible -- anchors { -- left: parent.left -- verticalCenter: parent.verticalCenter -- leftMargin: navigationButtonsColumn.width -- } -- } -- QImageItem { -- id: imageItem -- anchors.fill: appIconItem -- image: model.image -- smooth: true -- visible: nativeWidth > 0 -- } -- /* -- * this extra item is for clip the overflowed body text -- * maximumLineCount cannot control the behavior of rich text, -- * so manual clip is required. -- */ -- Item { -- id: bodyLabel -- clip: true -- height: Math.min(parent.height - (titleLabel.height+titleLabel.y), lastNotificationText.height) -- property bool tallText: bodyLabel.height >= (bodyLabel.parent.height - (titleLabel.height+titleLabel.y)*2) -- anchors { -- top: tallText ? titleLabel.bottom : undefined -- verticalCenter: tallText ? undefined : parent.verticalCenter -- left: appIconItem.right -- right: actionsColumn.left -- leftMargin: 6 -- rightMargin: 6 -- } -- PlasmaComponents.Label { -- id: lastNotificationText -- text: model.body -- width: parent.width -- //textFormat: Text.PlainText -- color: theme.textColor -- wrapMode: Text.Wrap -- elide: Text.ElideRight -- maximumLineCount: 4 -- onLinkActivated: plasmoid.openUrl(link) -- } -- } -- Column { -- id: actionsColumn -- spacing: 6 -- anchors { -- right: parent.right -- rightMargin: 6 -- verticalCenter: parent.verticalCenter -- } -- Repeater { -- model: actions -- PlasmaComponents.Button { -- text: model.text -- width: theme.defaultFont.mSize.width * 8 -- height: theme.defaultFont.mSize.width * 2 -- onPressedChanged: { -- if (pressed) { -- mainItem.buttonPressed = true -- } else { -- mainItem.buttonPressed = false -- } -- } -- onClicked: { -- executeAction(source, model.id) -- actionsColumn.visible = false -- } -- } -- } -- } -- } -- } -- -- Column { -- id: navigationButtonsColumn -- opacity: 0 -- visible: backButton.enabled || nextButton.enabled -- anchors { -- left: parent.left -- verticalCenter: parent.verticalCenter -- } -- -- PlasmaComponents.ToolButton { -- id: nextButton -- iconSource: "go-next" -- width: theme.smallMediumIconSize -- height: mainItem.height/2 - 4 -- enabled: notificationsView.currentIndex < notificationsView.count-1 -- onPressedChanged: { -- if (pressed) { -- mainItem.buttonPressed = true -- } else { -- mainItem.buttonPressed = false -- } -- } -- onClicked: { -- notificationsView.currentIndex = Math.min(notificationsView.count-1, notificationsView.currentIndex+1) -- } -- } -- -- PlasmaComponents.ToolButton { -- id: backButton -- iconSource: "go-previous" -- width: theme.smallMediumIconSize -- height: mainItem.height/2 - 4 -- enabled: notificationsView.currentIndex > 0 -- onPressedChanged: { -- if (pressed) { -- mainItem.buttonPressed = true -- } else { -- mainItem.buttonPressed = false -- } -- } -- onClicked: { -- notificationsView.currentIndex = Math.max(0, notificationsView.currentIndex-1) -- } -- } -- } -- PlasmaComponents.ToolButton { -- id: closeButton -- opacity: 0 -- iconSource: "window-close" -- width: theme.smallMediumIconSize -- height: width -- anchors { -- right: parent.right -- top: parent.top -- } -- onPressedChanged: { -- if (pressed) { -- mainItem.buttonPressed = true -- } else { -- mainItem.buttonPressed = false -- } -- } -- onClicked: { -- lastNotificationPopup.visible = false -- lastNotificationTimer.running = false -- closeNotification(notificationsModel.get((notificationsView.count-1)-notificationsView.currentIndex).source) -- notificationsModel.remove((notificationsView.count-1)-notificationsView.currentIndex) -- } -- } -- PlasmaComponents.ToolButton { -- id: settingsButton -- opacity: 0 -- iconSource: "configure" -- width: theme.smallMediumIconSize -- height: width -- visible: notificationsModel.get((notificationsView.count-1)-notificationsView.currentIndex).configurable -- anchors { -- right: closeButton.left -- top: parent.top -- rightMargin: 5 -- } -- onPressedChanged: { -- if (pressed) { -- mainItem.buttonPressed = true -- } else { -- mainItem.buttonPressed = false -- } -- } -- onClicked: { -- lastNotificationPopup.visible = false -- configureNotification(notificationsModel.get((notificationsView.count-1)-notificationsView.currentIndex).appRealName) -- } -- } -- states: [ -- State { -- name: "controlsShown" -- PropertyChanges { -- target: navigationButtonsColumn -- opacity: 1 -- } -- PropertyChanges { -- target: closeButton -- opacity: 1 -- } -- PropertyChanges { -- target: settingsButton -- opacity: 1 -- } -- }, -- State { -- name: "controlsHidden" -- PropertyChanges { -- target: navigationButtonsColumn -- opacity: 0 -- } -- PropertyChanges { -- target: closeButton -- opacity: 0 -- } -- PropertyChanges { -- target: settingsButton -- opacity: 0 -- } -- } -- ] -- transitions: [ -- Transition { -- NumberAnimation { -- properties: "opacity" -- easing.type: Easing.InOutQuad -- duration: 250 -- } -- } -- ] -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/NotificationDelegate.qml b/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/NotificationDelegate.qml -deleted file mode 100644 -index bf33eb1..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/NotificationDelegate.qml -+++ /dev/null -@@ -1,253 +0,0 @@ --/* -- * Copyright 2011 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.qtextracomponents 0.1 -- --PlasmaComponents.ListItem { -- id: notificationItem -- opacity: 1-Math.abs(x)/width -- width: popupFlickable.width -- property int toolIconSize: theme.smallMediumIconSize -- property int layoutSpacing: 4 -- -- visible: appTabBar.currentTab == allAppsTab || appTabBar.currentTab.text == appName -- -- Component.onCompleted: { -- allApplicationsModel.addApplication(appIcon, appName) -- mainScrollArea.height = mainScrollArea.implicitHeight -- } -- Component.onDestruction: { -- allApplicationsModel.removeApplication(model.appName) -- mainScrollArea.height = mainScrollArea.implicitHeight -- } -- Timer { -- interval: 10*60*1000 -- repeat: false -- running: !idleTimeSource.idle -- onTriggered: { -- notificationsModel.remove(index) -- } -- } -- -- MouseArea { -- width: parent.width -- height: childrenRect.height -- drag { -- target: notificationItem -- axis: Drag.XAxis -- //kind of an hack over Column being too smart -- minimumX: -parent.width + 1 -- maximumX: parent.width - 1 -- } -- onReleased: { -- if (notificationItem.x < -notificationItem.width/2) { -- removeAnimation.exitFromRight = false -- removeAnimation.running = true -- } else if (notificationItem.x > notificationItem.width/2 ) { -- removeAnimation.exitFromRight = true -- removeAnimation.running = true -- } else { -- resetAnimation.running = true -- } -- } -- SequentialAnimation { -- id: removeAnimation -- property bool exitFromRight: true -- NumberAnimation { -- target: notificationItem -- properties: "x" -- to: removeAnimation.exitFromRight ? notificationItem.width-1 : 1-notificationItem.width -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- NumberAnimation { -- target: notificationItem -- properties: "height" -- to: 0 -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- ScriptAction { -- script: notificationsModel.remove(index) -- } -- } -- SequentialAnimation { -- id: resetAnimation -- NumberAnimation { -- target: notificationItem -- properties: "x" -- to: 0 -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- } -- Column { -- spacing: notificationItem.layoutSpacing -- width: parent.width -- Item { -- width: parent.width -- height: summaryLabel.height -- -- PlasmaComponents.Label { -- id: summaryLabel -- text: summary -- height: paintedHeight -- anchors { -- left: parent.left -- right: parent.right -- leftMargin: closeButton.width -- rightMargin: settingsButton.visible ? settingsButton.width + closeButton.width : closeButton.width -- } -- horizontalAlignment: Text.AlignHCenter -- elide: Text.ElideRight -- onLinkActivated: plasmoid.openUrl(link) -- } -- -- PlasmaComponents.ToolButton { -- id: closeButton -- iconSource: "window-close" -- width: notificationItem.toolIconSize -- height: width -- onClicked: { -- if (notificationsModel.count > 1) { -- removeAnimation.running = true -- } else { -- closeNotification(model.source) -- notificationsModel.remove(index) -- } -- } -- anchors { -- top: parent.top -- right: parent.right -- } -- } -- -- PlasmaComponents.ToolButton { -- id: settingsButton -- iconSource: "configure" -- width: notificationItem.toolIconSize -- height: width -- visible: model.configurable -- onClicked: { -- plasmoid.hidePopup() -- configureNotification(model.appRealName) -- } -- anchors { -- top: parent.top -- right: closeButton.left -- rightMargin: 5 -- } -- } -- } -- -- Item { -- height: childrenRect.height -- width: parent.width -- QIconItem { -- id: appIconItem -- icon: QIcon(appIcon) -- width: theme.largeIconSize -- height: theme.largeIconSize -- visible: !imageItem.visible -- anchors { -- left: parent.left -- verticalCenter: parent.verticalCenter -- } -- } -- QImageItem { -- id: imageItem -- anchors.fill: appIconItem -- image: model.image -- smooth: true -- visible: nativeWidth > 0 -- } -- PlasmaComponents.ContextMenu { -- id: contextMenu -- visualParent: contextMouseArea -- PlasmaComponents.MenuItem { -- text: i18n("Copy") -- onClicked: bodyText.copy() -- } -- PlasmaComponents.MenuItem { -- text: i18n("Select All") -- onClicked: bodyText.selectAll() -- } -- } -- MouseArea { -- id: contextMouseArea -- anchors { -- left: appIconItem.right -- right: actionsColumn.left -- verticalCenter: parent.verticalCenter -- leftMargin: 6 -- rightMargin: 6 -- } -- acceptedButtons: Qt.RightButton -- height: bodyText.paintedHeight -- preventStealing: true -- onPressed: contextMenu.open(mouse.x, mouse.y) -- TextEdit { -- id: bodyText -- anchors.fill: parent -- text: body -- color: theme.textColor -- font.capitalization: theme.defaultFont.capitalization -- font.family: theme.defaultFont.family -- font.italic: theme.defaultFont.italic -- font.letterSpacing: theme.defaultFont.letterSpacing -- font.pointSize: theme.defaultFont.pointSize -- font.strikeout: theme.defaultFont.strikeout -- font.underline: theme.defaultFont.underline -- font.weight: theme.defaultFont.weight -- font.wordSpacing: theme.defaultFont.wordSpacing -- selectByMouse: true -- readOnly: true -- wrapMode: Text.Wrap -- textFormat: TextEdit.RichText -- onLinkActivated: plasmoid.openUrl(link) -- } -- } -- Column { -- id: actionsColumn -- spacing: notificationItem.layoutSpacing -- anchors { -- right: parent.right -- rightMargin: 6 -- verticalCenter: parent.verticalCenter -- } -- Repeater { -- model: actions -- PlasmaComponents.Button { -- text: model.text -- width: theme.defaultFont.mSize.width * 8 -- height: theme.defaultFont.mSize.width * 2 -- onClicked: { -- executeAction(source, model.id) -- actionsColumn.visible = false -- } -- } -- } -- } -- } -- } -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/qmldir b/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/qmldir -deleted file mode 100644 -index 88fc37a..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/NotificationDelegate/qmldir -+++ /dev/null -@@ -1 +0,0 @@ --NotificationDelegate 0.1 NotificationDelegate.qml -diff --git a/plasma/generic/applets/notifications/contents/ui/NotificationIcon.qml b/plasma/generic/applets/notifications/contents/ui/NotificationIcon.qml -deleted file mode 100644 -index f12cd56..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/NotificationIcon.qml -+++ /dev/null -@@ -1,188 +0,0 @@ --/*************************************************************************** -- * Copyright 2011 Davide Bettio * -- * Copyright 2011 Marco Martin * -- * * -- * This program is free software; you can redistribute it and/or modify * -- * it under the terms of the GNU Library General Public License as published by * -- * the Free Software Foundation; either version 2 of the License, or * -- * (at your option) any later version. * -- * * -- * 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 Library General Public License for more details. * -- * * -- * You should have received a copy of the GNU Library General Public License * -- * along with this program; if not, write to the * -- * Free Software Foundation, Inc., * -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -- ***************************************************************************/ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.qtextracomponents 0.1 --import org.kde.plasma.extras 0.1 as PlasmaExtras -- -- --Item { -- PlasmaCore.SvgItem { -- id: notificationSvgItem -- svg: notificationSvg -- elementId: "notification-disabled" -- anchors.centerIn: parent -- width: Math.min(parent.width, parent.height) -- height: width -- state: notificationsApplet.state -- -- PlasmaCore.Svg { -- id: notificationSvg -- imagePath: "icons/notification" -- } -- -- Item { -- id: jobProgressItem -- width: notificationSvgItem.width * globalProgress -- clip: true -- visible: jobs.count > 0 -- anchors { -- left: parent.left -- top: parent.top -- bottom: parent.bottom -- } -- PlasmaCore.SvgItem { -- svg: notificationSvg -- elementId: "notification-progress-active" -- anchors { -- left: parent.left -- top: parent.top -- bottom: parent.bottom -- } -- width: notificationSvgItem.width -- } -- } -- PlasmaComponents.BusyIndicator { -- anchors.fill: parent -- visible: jobs ? jobs.count > 0 : false -- running: visible -- } -- -- Column { -- id: countColumn -- visible: false -- anchors.centerIn: parent -- PlasmaCore.SvgItem { -- svg: notificationSvg -- elementId: { -- switch (plasmoid.location) { -- case TopEdge: -- return "expander-top" -- case LeftEdge: -- return "expander-left" -- case RightEdge: -- return "expander-right" -- default: -- return "expander-bottom" -- } -- } -- width: naturalSize.width -- height: naturalSize.height -- anchors.horizontalCenter: parent.horizontalCenter -- } -- PlasmaComponents.Label { -- property int totalCount: notificationsApplet.totalCount -- text: totalCount -- -- property int oldTotalCount: 0 -- font.pointSize: theme.smallestFont.pointSize -- height: paintedHeight - 3 -- onTotalCountChanged: { -- if (totalCount > oldTotalCount) { -- notificationAnimation.running = true -- } -- oldTotalCount = totalCount -- } -- } -- } -- -- PlasmaCore.SvgItem { -- id: notificationAnimatedItem -- anchors.fill: parent -- svg: notificationSvg -- elementId: "notification-active" -- opacity: 0 -- scale: 2 -- -- SequentialAnimation { -- id: notificationAnimation -- NumberAnimation { -- target: notificationAnimatedItem -- duration: 250 -- properties: "opacity, scale" -- to: 1 -- easing.type: Easing.InOutQuad -- } -- PauseAnimation { duration: 500 } -- ParallelAnimation { -- NumberAnimation { -- target: notificationAnimatedItem -- duration: 250 -- properties: "opacity" -- to: 0 -- easing.type: Easing.InOutQuad -- } -- NumberAnimation { -- target: notificationAnimatedItem -- duration: 250 -- properties: "scale" -- to: 2 -- easing.type: Easing.InOutQuad -- } -- } -- } -- } -- MouseArea { -- anchors.fill: parent -- onClicked: { -- if (notificationsApplet.totalCount > 0) { -- plasmoid.togglePopup() -- } else { -- plasmoid.hidePopup() -- } -- } -- } -- states: [ -- State { -- name: "default" -- PropertyChanges { -- target: notificationSvgItem -- elementId: "notification-disabled" -- } -- PropertyChanges { -- target: countColumn -- visible: false -- } -- PropertyChanges { -- target: plasmoid -- status: PassiveStatus -- } -- }, -- State { -- name: "new-notifications" -- PropertyChanges { -- target: notificationSvgItem -- elementId: jobs.count > 0 ? "notification-progress-inactive" : "notification-empty" -- } -- PropertyChanges { -- target: countColumn -- visible: true -- } -- PropertyChanges { -- target: plasmoid -- status: ActiveStatus -- } -- } -- ] -- } --} -- -diff --git a/plasma/generic/applets/notifications/contents/ui/Notifications.qml b/plasma/generic/applets/notifications/contents/ui/Notifications.qml -deleted file mode 100644 -index 114ead2..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/Notifications.qml -+++ /dev/null -@@ -1,227 +0,0 @@ --/* -- * Copyright 2012 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents -- --import "plasmapackage:/ui/NotificationDelegate" -- --Column { -- id: notificationsRoot -- property alias count: notificationsRepeater.count -- anchors { -- left: parent.left -- right: parent.right -- } -- -- function addNotification(source, appIcon, image, appName, summary, body, expireTimeout, urgency, appRealName, configurable, actions) { -- // Do not show duplicated notifications -- for (var i = 0; i < notificationsModel.count; ++i) { -- if (notificationsModel.get(i).source == source && -- notificationsModel.get(i).appName == appName && -- notificationsModel.get(i).summary == summary && -- notificationsModel.get(i).body == body) { -- return -- } -- } -- -- for (var i = 0; i < notificationsModel.count; ++i) { -- if (notificationsModel.get(i).source == source) { -- notificationsModel.remove(i) -- break -- } -- } -- if (notificationsModel.count > 20) { -- notificationsModel.remove(notificationsModel.count-1) -- } -- var notification = {"source" : source, -- "appIcon" : appIcon, -- "image" : image, -- "appName" : appName, -- "summary" : summary, -- "body" : body, -- "expireTimeout": expireTimeout, -- "urgency" : urgency, -- "configurable": configurable, -- "appRealName": appRealName, -- "actions" : actions} -- notificationsModel.insert(0, notification); -- if (plasmoid.popupShowing) { -- return -- } -- if (!lastNotificationPopup) { -- lastNotificationPopup = lastNotificationPopupComponent.createObject(notificationsRoot) -- } -- lastNotificationPopup.popup(notification) -- } -- -- function executeAction(source, id) { -- //try to use the service -- if (source.indexOf("notification") !== -1) { -- var service = notificationsSource.serviceForSource(source) -- var op = service.operationDescription("invokeAction") -- op["actionId"] = id -- -- service.startOperationCall(op) -- //try to open the id as url -- } else if (source.indexOf("Job") !== -1) { -- plasmoid.openUrl(id) -- } -- } -- -- function configureNotification(appRealName) { -- var service = notificationsSource.serviceForSource("notification") -- var op = service.operationDescription("configureNotification") -- op["appRealName"] = appRealName; -- service.startOperationCall(op) -- } -- -- function closeNotification(source) { -- var service = notificationsSource.serviceForSource(source) -- var op = service.operationDescription("userClosed") -- service.startOperationCall(op) -- } -- -- property QtObject lastNotificationPopup -- Component { -- id: lastNotificationPopupComponent -- LastNotificationPopup { -- } -- } -- -- ListModel { -- id: notificationsModel -- } -- ListModel { -- id: allApplicationsModel -- function addApplication(icon, name) -- { -- for (var i = 0; i < count; ++i) { -- var item = get(i) -- if (item.name == name) { -- setProperty(i, "count", item.count + 1) -- return -- } -- } -- append({"icon": icon, "name": name, "count": 1}) -- } -- function removeApplication(name) -- { -- for (var i = 0; i < count; ++i) { -- var item = get(i) -- if (item.name == name) { -- if (item.count <= 1) { -- remove(i) -- appTabBar.currentTab = allAppsTab -- return -- } -- setProperty(i, "count", item.count - 1) -- return -- } -- } -- } -- } -- -- PlasmaCore.DataSource { -- id: idleTimeSource -- engine: "powermanagement" -- interval: 30000 -- connectedSources: ["UserActivity"] -- //Idle whith more than 5 minutes of user inactivity -- property bool idle: data["UserActivity"]["IdleTime"] > 300000 -- } -- -- PlasmaCore.DataSource { -- id: notificationsSource -- engine: "notifications" -- interval: 0 -- -- onSourceAdded: { -- connectSource(source); -- } -- -- onNewData: { -- var actions = new Array() -- if (data["actions"] && data["actions"].length % 2 == 0) { -- for (var i = 0; i < data["actions"].length; i += 2) { -- var action = new Object() -- action["id"] = data["actions"][i] -- action["text"] = data["actions"][i+1] -- actions.push(action) -- } -- } -- notificationsRoot.addNotification( -- sourceName, -- data["appIcon"], -- data["image"], -- data["appName"], -- data["summary"], -- data["body"], -- data["expireTimeout"], -- data["urgency"], -- data["appRealName"], -- data["configurable"], -- actions) -- } -- -- } -- -- Title { -- visible: notificationsRepeater.count > 1 || (jobs && jobs.count > 0 && notificationsRepeater.count > 0) -- text: i18n("Notifications") -- PlasmaComponents.ToolButton { -- iconSource: "window-close" -- width: notificationsApplet.toolIconSize -- height: width -- anchors { -- right: parent.right -- verticalCenter: parent.verticalCenter -- } -- onClicked: notificationsModel.clear() -- } -- } -- PlasmaComponents.ListItem { -- visible: allApplicationsModel.count > 1 -- PlasmaComponents.TabBar { -- id: appTabBar -- anchors.horizontalCenter: parent.horizontalCenter -- width: Math.min(implicitWidth, parent.width-8) -- PlasmaComponents.TabButton { -- id: allAppsTab -- text: i18n("All") -- iconSource: "dialog-information" -- } -- Repeater { -- model: allApplicationsModel -- PlasmaComponents.TabButton { -- text: name -- iconSource: icon -- } -- } -- } -- } -- Repeater { -- id: notificationsRepeater -- model: notificationsModel -- delegate: NotificationDelegate { -- toolIconSize: notificationsApplet.toolIconSize -- } -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/Title.qml b/plasma/generic/applets/notifications/contents/ui/Title.qml -deleted file mode 100644 -index dff4f72..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/Title.qml -+++ /dev/null -@@ -1,43 +0,0 @@ --/* -- * Copyright 2012 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents -- --PlasmaComponents.ListItem { -- id: root -- property alias text: titleLabel.text -- -- -- sectionDelegate: true -- -- width: parent.width -- -- PlasmaComponents.Label { -- id: titleLabel -- horizontalAlignment: Text.AlignHCenter -- elide: Text.ElideRight -- anchors { -- verticalCenter: parent.verticalCenter -- left: parent.left -- right: parent.right -- } -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/config.ui b/plasma/generic/applets/notifications/contents/ui/config.ui -deleted file mode 100644 -index 7769bba..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/config.ui -+++ /dev/null -@@ -1,69 +0,0 @@ -- -- -- feedsConfig -- -- -- -- 0 -- 0 -- 337 -- 181 -- -- -- -- -- -- -- &Application notifications: -- -- -- kcfg_ShowNotifications -- -- -- -- -- -- -- -- -- -- -- -- -- -- &File transfers and jobs: -- -- -- kcfg_ShowJobs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 75 -- true -- -- -- -- Choose which information to show -- -- -- -- -- -- -- kcfg_ShowNotifications -- kcfg_ShowJobs -- -- -- -- -diff --git a/plasma/generic/applets/notifications/contents/ui/main.qml b/plasma/generic/applets/notifications/contents/ui/main.qml -deleted file mode 100644 -index 4d4b0f7..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/main.qml -+++ /dev/null -@@ -1,171 +0,0 @@ --/*************************************************************************** -- * Copyright 2011 Davide Bettio * -- * Copyright 2011 Marco Martin * -- * * -- * This program is free software; you can redistribute it and/or modify * -- * it under the terms of the GNU Library General Public License as published by * -- * the Free Software Foundation; either version 2 of the License, or * -- * (at your option) any later version. * -- * * -- * 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 Library General Public License for more details. * -- * * -- * You should have received a copy of the GNU Library General Public License * -- * along with this program; if not, write to the * -- * Free Software Foundation, Inc., * -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -- ***************************************************************************/ -- --import QtQuick 1.1 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.qtextracomponents 0.1 --import org.kde.plasma.extras 0.1 as PlasmaExtras --import org.kde.locale 0.1 as KLocale -- --import "plasmapackage:/ui/uiproperties.js" as UiProperties -- -- --MouseEventListener { -- id: notificationsApplet -- state: "default" -- width: 32 -- height: 32 -- property int minimumWidth: mainScrollArea.implicitWidth -- property int minimumHeight: mainScrollArea.implicitHeight -- property int maximumWidth: -1 -- property int maximumHeight: mainScrollArea.implicitHeight -- -- property int toolIconSize: UiProperties.toolIconSize -- property int layoutSpacing: UiProperties.layoutSpacing -- -- property real globalProgress: 0 -- -- property bool showNotifications: false -- property bool showJobs: false -- -- property Item notifications: notificationsLoader.item -- property Item jobs: jobsLoader.item -- -- //notifications + jobs -- property int totalCount: (notifications ? notifications.count : 0) + (jobs ? jobs.count : 0) -- onTotalCountChanged: { -- if (totalCount > 0) { -- state = "new-notifications" -- } else { -- state = "default" -- plasmoid.hidePopup() -- } -- -- var data = new Object -- data["image"] = "preferences-desktop-notification" -- data["mainText"] = i18n("Notifications and Jobs") -- if (totalCount == 0) { -- data["subText"] = i18n("No notifications or jobs") -- } else if (!notifications.count) { -- data["subText"] = i18np("%1 running job", "%1 running jobs", jobs.count) -- } else if (!jobs.count) { -- data["subText"] = i18np("%1 notification", "%1 notifications", notifications.count) -- } else { -- data["subText"] = i18np("%1 running job", "%1 running jobs", jobs.count) + "
" + i18np("%1 notification", "%1 notifications", notifications.count) -- } -- plasmoid.popupIconToolTip = data -- plasmoid.passivePopup = jobs.count != 0 -- } -- -- property Item notificationIcon -- -- Component.onCompleted: { -- //plasmoid.popupIcon = QIcon("preferences-desktop-notification") -- plasmoid.aspectRatioMode = "ConstrainedSquare" -- plasmoid.status = PassiveStatus -- allApplications = new Object -- plasmoid.addEventListener('ConfigChanged', configChanged); -- configChanged() -- } -- -- function configChanged() -- { -- showNotifications = plasmoid.readConfig("ShowNotifications") -- showJobs = plasmoid.readConfig("ShowJobs") -- } -- -- KLocale.Locale { -- id: locale -- } -- -- PlasmaCore.Svg { -- id: configIconsSvg -- imagePath: "widgets/configuration-icons" -- } -- -- property Component compactRepresentation: Component { -- NotificationIcon { -- id: notificationIcon -- Component.onCompleted: notificationsApplet.notificationIcon = notificationIcon -- } -- } -- -- hoverEnabled: !UiProperties.touchInput -- -- PlasmaExtras.ScrollArea { -- id: mainScrollArea -- anchors.fill: parent -- implicitWidth: theme.defaultFont.mSize.width * 40 -- implicitHeight: Math.min(theme.defaultFont.mSize.height * 40, Math.max(theme.defaultFont.mSize.height * 6, contentsColumn.height)) -- state: "" -- -- states: [ -- State { -- name: "underMouse" -- when: notificationsApplet.containsMouse -- PropertyChanges { -- target: mainScrollArea -- implicitHeight: implicitHeight -- } -- }, -- State { -- name: "" -- when: !notificationsApplet.containsMouse -- PropertyChanges { -- target: mainScrollArea -- implicitHeight: Math.min(theme.defaultFont.mSize.height * 40, Math.max(theme.defaultFont.mSize.height * 6, contentsColumn.height)) -- } -- } -- ] -- -- Flickable { -- id: popupFlickable -- anchors.fill:parent -- -- contentWidth: width -- contentHeight: contentsColumn.height -- clip: true -- -- Column { -- id: contentsColumn -- width: popupFlickable.width -- -- //TODO: load those on demand based on configuration -- Loader { -- id: jobsLoader -- source: showJobs ? "Jobs.qml" : "" -- anchors { -- left: parent.left -- right: parent.right -- } -- } -- Loader { -- id: notificationsLoader -- source: showNotifications ? "Notifications.qml" : "" -- anchors { -- left: parent.left -- right: parent.right -- } -- } -- } -- } -- } --} -diff --git a/plasma/generic/applets/notifications/contents/ui/uiproperties.js b/plasma/generic/applets/notifications/contents/ui/uiproperties.js -deleted file mode 100644 -index efad371..0000000 ---- a/plasma/generic/applets/notifications/contents/ui/uiproperties.js -+++ /dev/null -@@ -1,23 +0,0 @@ --/* -- * Copyright 2012 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- -- --var toolIconSize = theme.smallMediumIconSize --var layoutSpacing = 4 --var touchInput = false -diff --git a/plasma/generic/applets/notifications/core/completedjobnotification.cpp b/plasma/generic/applets/notifications/core/completedjobnotification.cpp -new file mode 100644 -index 0000000..9a08390 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/completedjobnotification.cpp -@@ -0,0 +1,99 @@ -+/*************************************************************************** -+ * completedjobnotification.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "completedjobnotification.h" -+#include "job.h" -+ -+#include -+ -+#include -+#include -+#include -+ -+ -+static const int completedJobExpireDelay = 60 * 1000; -+static const int completedShortJobExpireDelay = 8 * 1000; -+static const uint shortJobsLength = 30 * 1000; -+ -+CompletedJobNotification::CompletedJobNotification(QObject *parent) -+ : Notification(parent) -+{ -+} -+ -+CompletedJobNotification::~CompletedJobNotification() -+{ -+} -+ -+void CompletedJobNotification::setJob(Job *job) -+{ -+ setApplicationName(job->applicationName()); -+ setApplicationIcon(KIcon(job->applicationIconName())); -+ setSummary(i18n("%1 [Finished]", job->message())); -+ -+ if (job->error().isEmpty()) { -+ setMessage(job->completedMessage()); -+ } else { -+ setMessage(job->error()); -+ } -+ -+ if (job->elapsed() < shortJobsLength) { -+ setTimeout(completedShortJobExpireDelay); -+ } else { -+ setTimeout(completedJobExpireDelay); -+ } -+ -+ if (job->destination().isValid()) { -+ QHash actions; -+ actions.insert("open", i18n("Open")); -+ setActions(actions); -+ setActionOrder(QStringList()<<"open"); -+ -+ // create location url as is done in job->completedMessage() -+ KUrl location(job->destination()); -+ if (job->totalAmounts().value("files") > 1) { -+ location.setFileName(QString()); -+ } -+ -+ m_destinationPrettyUrl = location.prettyUrl(); -+ } -+ -+ m_job = job; -+} -+ -+void CompletedJobNotification::linkActivated(const QString &url) -+{ -+ kDebug() << "open " << url; -+ QProcess::startDetached("kde-open", QStringList() << url); -+} -+ -+Job *CompletedJobNotification::job() const -+{ -+ return m_job; -+} -+ -+void CompletedJobNotification::triggerAction(const QString &actionId) -+{ -+ if (actionId == "open" && !m_destinationPrettyUrl.isNull()) { -+ linkActivated(m_destinationPrettyUrl); -+ } -+} -+ -+ -+#include "completedjobnotification.moc" -diff --git a/plasma/generic/applets/notifications/core/completedjobnotification.h b/plasma/generic/applets/notifications/core/completedjobnotification.h -new file mode 100644 -index 0000000..b5e1f15 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/completedjobnotification.h -@@ -0,0 +1,51 @@ -+/*************************************************************************** -+ * completedjobnotification.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef COMPLETEDJOBNOTIFICATION_H -+#define COMPLETEDJOBNOTIFICATION_H -+ -+#include "notification.h" -+ -+ -+class Job; -+ -+class CompletedJobNotification : public Notification -+{ -+ Q_OBJECT -+ -+public: -+ CompletedJobNotification(QObject *parent = 0); -+ virtual ~CompletedJobNotification(); -+ -+ void setJob(Job *job); -+ Job *job() const; -+ -+public Q_SLOTS: -+ void linkActivated(const QString &link); -+ void triggerAction(const QString &actionId); -+ -+private: -+ Job *m_job; -+ QString m_destinationPrettyUrl; -+}; -+ -+ -+#endif -+ -diff --git a/plasma/generic/applets/notifications/core/job.cpp b/plasma/generic/applets/notifications/core/job.cpp -new file mode 100644 -index 0000000..77ea03f ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/job.cpp -@@ -0,0 +1,360 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "job.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+ -+class Job::Private -+{ -+public: -+ Private() : -+ numericSpeed(0), -+ finalElapsed(0), -+ state(Running), -+ percentage(0), -+ eta(0), -+ timerId(0), -+ killable(false), -+ suspendable(false), -+ shown(false) -+ { -+ } -+ -+ QString applicationName; -+ QString applicationIconName; -+ QString message; -+ QString error; -+ QString speed; -+ QString destination; -+ qlonglong numericSpeed; -+ -+ -+ QMap totalAmounts; -+ QMap processedAmounts; -+ -+ QList > labels; -+ -+ QTime elapsed; -+ uint finalElapsed; -+ -+ State state; -+ uint percentage; -+ uint eta; -+ int timerId; -+ -+ bool killable : 1; -+ bool suspendable : 1; -+ bool shown : 1; -+}; -+ -+Job::Job(QObject *parent) -+ : QObject(parent), -+ d(new Private) -+{ -+ //delay a little the job to avoid the user to be distracted with short ones -+ QTimer::singleShot(1500, this, SLOT(show())); -+ d->elapsed.restart(); -+} -+ -+Job::~Job() -+{ -+ delete d; -+} -+ -+void Job::destroy() -+{ -+ emit destroyed(this); -+ deleteLater(); -+} -+ -+QString Job::applicationName() const -+{ -+ return d->applicationName; -+} -+ -+void Job::setApplicationName(const QString &applicationName) -+{ -+ if (d->applicationName != applicationName) { -+ d->applicationName = applicationName; -+ scheduleChangedSignal(); -+ } -+} -+ -+QString Job::applicationIconName() const -+{ -+ return d->applicationIconName; -+} -+ -+void Job::setApplicationIconName(const QString &applicationIcon) -+{ -+ if (d->applicationIconName != applicationIcon) { -+ d->applicationIconName = applicationIcon; -+ scheduleChangedSignal(); -+ } -+} -+ -+QString Job::message() const -+{ -+ return d->message; -+} -+ -+void Job::setMessage(const QString &message) -+{ -+ if (d->message != message) { -+ d->message = message; -+ scheduleChangedSignal(); -+ } -+} -+ -+QString Job::error() const -+{ -+ return d->error; -+} -+ -+void Job::setError(const QString &error) -+{ -+ if (d->error != error) { -+ d->error = error; -+ scheduleChangedSignal(); -+ } -+} -+ -+QString Job::speed() const -+{ -+ return d->speed; -+} -+ -+void Job::setSpeed(const QString &speed) -+{ -+ if (d->speed != speed) { -+ d->speed = speed; -+ scheduleChangedSignal(); -+ } -+} -+ -+qlonglong Job::numericSpeed() const -+{ -+ return d->numericSpeed; -+} -+ -+void Job::setNumericSpeed(const qlonglong speed) -+{ -+ if (d->numericSpeed != speed) { -+ d->numericSpeed = speed; -+ scheduleChangedSignal(); -+ } -+} -+ -+QString Job::completedMessage() const -+{ -+ KUrl location(d->destination); -+ if (location.isValid()) { -+ if (totalAmounts().value("files") > 1) { -+ location.setFileName(QString()); -+ } -+ -+ QString destinationString; -+ if (location.isLocalFile()) { -+ destinationString = location.toLocalFile(); -+ } else { -+ destinationString = location.prettyUrl(); -+ } -+ -+ //FIXME: this is visualization stuff, but putting html here is not so model as well -+ -+ kDebug() << "href = " << location.url(); -+ QString destinationLink = QString("%2").arg(location.url()) -+ .arg(Qt::escape(destinationString)); -+ -+ if (totalAmounts().value("files") > 1) { -+ return i18np("%1 file, to: %2", "%1 files, to: %2", totalAmounts().value("files"), -+ destinationLink); -+ } else { -+ return destinationLink; -+ } -+ } else { -+ return QString("%1: %2").arg(labels().value(0).first).arg(labels().value(0).second); -+ } -+} -+ -+KUrl Job::destination() const -+{ -+ return d->destination; -+} -+ -+ulong Job::eta() const -+{ -+ return d->eta; -+} -+ -+void Job::setEta(ulong eta) -+{ -+ d->eta = eta; -+} -+ -+QMap Job::totalAmounts() const -+{ -+ return d->totalAmounts; -+} -+ -+void Job::setTotalAmounts(QMap amounts) -+{ -+ d->totalAmounts = amounts; -+ scheduleChangedSignal(); -+} -+ -+QMap Job::processedAmounts() const -+{ -+ return d->processedAmounts; -+} -+ -+void Job::setProcessedAmounts(QMap amounts) -+{ -+ d->processedAmounts = amounts; -+ scheduleChangedSignal(); -+} -+ -+Job::State Job::state() const -+{ -+ return d->state; -+} -+ -+void Job::setState(State state) -+{ -+ if (d->state != state) { -+ d->state = state; -+ show(); -+ if (state == Stopped) { -+ d->finalElapsed = d->elapsed.elapsed(); -+ } -+ emit stateChanged(this); -+ } -+} -+ -+QList > Job::labels() const -+{ -+ return d->labels; -+} -+ -+void Job::setLabels(QList > labels) -+{ -+ d->labels = labels; -+ if (d->labels.count() > 1 && d->destination.isEmpty()) { -+ d->destination = d->labels.value(1).second; -+ } -+ scheduleChangedSignal(); -+} -+ -+uint Job::percentage() const -+{ -+ return d->percentage; -+} -+ -+void Job::setPercentage(uint percentage) -+{ -+ if (d->percentage != percentage) { -+ d->percentage = percentage; -+ scheduleChangedSignal(); -+ } -+} -+ -+uint Job::elapsed() const -+{ -+ if (d->finalElapsed) { -+ return d->finalElapsed; -+ } else { -+ return d->elapsed.elapsed(); -+ } -+} -+ -+bool Job::isSuspendable() const -+{ -+ return d->suspendable; -+} -+ -+void Job::setSuspendable(bool suspendable) -+{ -+ if (d->suspendable != suspendable) { -+ d->suspendable = suspendable; -+ scheduleChangedSignal(); -+ } -+} -+ -+bool Job::isKillable() const -+{ -+ return d->killable; -+} -+ -+void Job::setKillable(bool killable) -+{ -+ if (d->killable != killable) { -+ d->killable = killable; -+ scheduleChangedSignal(); -+ } -+} -+ -+void Job::suspend() -+{ -+ kWarning() << "Suspend is not implemented in this job provider."; -+} -+ -+void Job::resume() -+{ -+ kWarning() << "Resume is not implemented in this job provider."; -+} -+ -+void Job::stop() -+{ -+ kWarning() << "Stop is not implemented in this job provider."; -+} -+ -+void Job::show() -+{ -+ if (state() == Job::Running && !d->shown) { -+ d->shown = true; -+ emit ready(this); -+ } -+} -+ -+void Job::scheduleChangedSignal() -+{ -+ if (d->shown && !d->timerId) { -+ d->timerId = startTimer(0); -+ } -+} -+ -+void Job::timerEvent(QTimerEvent *) -+{ -+ killTimer(d->timerId); -+ d->timerId = 0; -+ emit changed(this); -+} -+ -+ -+#include "job.moc" -diff --git a/plasma/generic/applets/notifications/core/job.h b/plasma/generic/applets/notifications/core/job.h -new file mode 100644 -index 0000000..3d2984d ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/job.h -@@ -0,0 +1,188 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef JOB_H -+#define JOB_H -+ -+#include -+#include -+ -+#include -+ -+ -+class Job : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ enum State { -+ Running = 0, -+ Suspended = 1, -+ Stopped = 2 -+ }; -+ -+ Job(QObject *parent = 0); -+ virtual ~Job(); -+ -+ /** -+ * Request and signal destruction of this object -+ */ -+ void destroy(); -+ -+ /** -+ * @return the name of the application which started this job. -+ */ -+ QString applicationName() const; -+ -+ /** -+ * @return the name of the icon to be used for this job. -+ */ -+ QString applicationIconName() const; -+ -+ /** -+ * @return the descripion of the activity that is performed. -+ */ -+ QString message() const; -+ -+ /** -+ * @return the errormessage if an error has occurred. -+ */ -+ QString error() const; -+ -+ /** -+ * @return the (human readable) speed at which the jobs is progressing. -+ */ -+ QString speed() const; -+ -+ /** -+ * @return the (in bytes per second) speed at which the jobs is progressing. -+ */ -+ qlonglong numericSpeed() const; -+ -+ /** -+ * @return a nice description of the job that has been completed. -+ */ -+ QString completedMessage() const; -+ -+ /** -+ * @return the time (in seconds) in which this job is expected to complete. -+ */ -+ ulong eta() const; -+ -+ void setEta(ulong eta); -+ -+ QMap totalAmounts() const; -+ -+ QMap processedAmounts() const; -+ -+ /** -+ * @return a list of pairs containing label names/values in the order they should be displayed. -+ */ -+ QList > labels() const; -+ -+ /** -+ * @return the state this job is in. -+ */ -+ State state() const; -+ -+ bool isSuspendable() const; -+ -+ bool isKillable() const; -+ -+ /** -+ * @retun the percentage of the job that has been completed. -+ */ -+ uint percentage() const; -+ -+ /** -+ * total elapsed job time -+ */ -+ uint elapsed() const; -+ -+ /** -+ * Destination url -+ */ -+ KUrl destination() const; -+ -+public slots: -+ /** -+ * suspend this job. -+ */ -+ virtual void suspend(); -+ -+ /** -+ * resume this job. -+ */ -+ virtual void resume(); -+ -+ /** -+ * stop this job. -+ */ -+ virtual void stop(); -+ -+signals: -+ /** -+ * Emitted when the job is ready to be shown -+ */ -+ void ready(Job *job); -+ -+ /** -+ * Emitted when the job changes state -+ */ -+ void stateChanged(Job *job); -+ -+ /** -+ * Emitted when the job details change -+ */ -+ void changed(Job *job); -+ -+ /** -+ * Emitted when the job is about to be destroyed -+ **/ -+ void destroyed(Job *job); -+ -+protected: -+ void setApplicationName(const QString &applicationName); -+ void setApplicationIconName(const QString &applicationIcon); -+ void setMessage(const QString &message); -+ void setError(const QString &error); -+ void setSpeed(const QString &speed); -+ void setNumericSpeed(const qlonglong speed); -+ void setTotalAmounts(QMap amount); -+ void setProcessedAmounts(QMap amount); -+ void setState(State state); -+ void setSuspendable(bool suspendable); -+ void setKillable(bool killable); -+ void setPercentage(uint percentage); -+ void setLabels(QList > labels); -+ void timerEvent(QTimerEvent *); -+ -+private slots: -+ void show(); -+ -+private: -+ void scheduleChangedSignal(); -+ -+ class Private; -+ Private* const d; -+ -+ friend class Manager; -+}; -+ -+#endif -diff --git a/plasma/generic/applets/notifications/core/notification.cpp b/plasma/generic/applets/notifications/core/notification.cpp -new file mode 100644 -index 0000000..26833b6 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/notification.cpp -@@ -0,0 +1,272 @@ -+/*************************************************************************** -+ * notification.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "notification.h" -+ -+#include -+#include -+ -+#include -+ -+ -+class Notification::Private -+{ -+public: -+ Private() -+ : timeout(0), -+ urgency(0), -+ hideTimer(0), -+ expired(false), -+ read(false) -+ { -+ } -+ -+ QString identifier; -+ QString applicationName; -+ QIcon applicationIcon; -+ QString message; -+ QString summary; -+ int timeout; -+ int urgency; -+ QImage image; -+ QTimer *deleteTimer; -+ QTimer *hideTimer; -+ bool expired; -+ bool read; -+ -+ QHash actions; -+ QStringList actionOrder; -+}; -+ -+Notification::Notification(QObject *parent) -+ : QObject(parent), -+ d(new Private) -+{ -+ d->deleteTimer = new QTimer(this); -+ d->deleteTimer->setSingleShot(true); -+ connect(d->deleteTimer, SIGNAL(timeout()), this, SLOT(destroy())); -+} -+ -+ -+Notification::~Notification() -+{ -+ emit notificationDestroyed(this); -+ delete d; -+} -+ -+void Notification::destroy() -+{ -+ emit notificationDestroyed(this); -+ deleteLater(); -+} -+ -+QString Notification::applicationName() const -+{ -+ return d->applicationName; -+} -+ -+ -+void Notification::setApplicationName(const QString &applicationName) -+{ -+ d->applicationName = applicationName; -+} -+ -+ -+QIcon Notification::applicationIcon() const -+{ -+ return d->applicationIcon; -+} -+ -+ -+void Notification::setApplicationIcon(const QIcon &applicationIcon) -+{ -+ d->applicationIcon = applicationIcon; -+} -+ -+ -+QString Notification::message() const -+{ -+ return d->message; -+} -+ -+ -+void Notification::setMessage(const QString &message) -+{ -+ d->message = message; -+} -+ -+ -+QString Notification::summary() const -+{ -+ return d->summary; -+} -+ -+ -+void Notification::setSummary(const QString &summary) -+{ -+ d->summary = summary; -+} -+ -+ -+int Notification::timeout() const -+{ -+ return d->timeout; -+} -+ -+QImage Notification::image() const -+{ -+ return d->image; -+} -+ -+void Notification::setImage(QImage image) -+{ -+ d->image = image; -+} -+ -+void Notification::setTimeout(int timeout) -+{ -+ //show them at most 30 seconds -+ if (!timeout) { -+ d->timeout = 30 * 1000; -+ } else { -+ d->timeout = timeout; -+ } -+ -+ if (d->urgency >= 2) { -+ return; -+ } -+ -+ if (!d->hideTimer) { -+ d->hideTimer = new QTimer(this); -+ d->hideTimer->setSingleShot(true); -+ connect(d->hideTimer, SIGNAL(timeout()), this, SLOT(hide())); -+ } -+ d->hideTimer->start(d->timeout); -+} -+ -+void Notification::setUrgency(int urgency) -+{ -+ if (urgency != d->urgency) { -+ d->urgency = urgency; -+ if (urgency >= 2) { -+ if (d->hideTimer) { -+ d->hideTimer->stop(); -+ } -+ d->deleteTimer->stop(); -+ } else { -+ setTimeout(d->timeout); -+ } -+ } -+} -+ -+int Notification::urgency() const -+{ -+ return d->urgency; -+} -+ -+QHash Notification::actions() const -+{ -+ return d->actions; -+} -+ -+ -+void Notification::setActions(const QHash &actions) -+{ -+ d->actions = actions; -+ emit changed(this); -+} -+ -+ -+QStringList Notification::actionOrder() const -+{ -+ return d->actionOrder; -+} -+ -+ -+void Notification::setActionOrder(const QStringList &actionOrder) -+{ -+ d->actionOrder = actionOrder; -+} -+ -+ -+void Notification::triggerAction(const QString &actionId) -+{ -+ Q_UNUSED(actionId); -+ kDebug() << "action triggered but no handler implemented"; -+} -+ -+void Notification::remove() -+{ -+ kDebug() << "remove requested but no handler implemented"; -+} -+ -+void Notification::linkActivated(const QString &link) -+{ -+ Q_UNUSED(link) -+ kDebug() << "link activation requested but no handler implemented"; -+} -+ -+void Notification::hide() -+{ -+ d->expired = true; -+ emit expired(this); -+} -+ -+void Notification::startDeletionCountdown() -+{ -+ if (d->urgency >= 2) { -+ return; -+ } -+ -+ //keep it available for 10 minutes -+ d->deleteTimer->start(10*60*1000); -+} -+ -+bool Notification::isExpired() const -+{ -+ return d->expired; -+} -+ -+void Notification::setRead(const bool read) -+{ -+ d->read = read; -+} -+ -+bool Notification::isRead() const -+{ -+ return d->read; -+} -+ -+void Notification::setDeleteTimeout(const int time) -+{ -+ if (d->deleteTimer->interval() != time) { -+ d->deleteTimer->start(time); -+ } -+} -+ -+int Notification::deleteTimeOut() const -+{ -+ return d->deleteTimer->interval(); -+} -+ -+ -+ -+#include "notification.moc" -diff --git a/plasma/generic/applets/notifications/core/notification.h b/plasma/generic/applets/notifications/core/notification.h -new file mode 100644 -index 0000000..e04fdba ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/notification.h -@@ -0,0 +1,100 @@ -+/*************************************************************************** -+ * notification.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATION_H -+#define NOTIFICATION_H -+ -+#include -+#include -+#include -+ -+#include -+ -+ -+ -+class Notification : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ Notification(QObject *parent = 0); -+ virtual ~Notification(); -+ -+ QString applicationName() const; -+ QIcon applicationIcon() const; -+ QString message() const; -+ QString summary() const; -+ int timeout() const; -+ QImage image() const; -+ -+ void setUrgency(int urgency); -+ int urgency() const; -+ -+ QHash actions() const; -+ QStringList actionOrder() const; -+ -+ bool isExpired() const; -+ -+ void setRead(const bool read); -+ bool isRead() const; -+ -+ void setDeleteTimeout(const int time); -+ int deleteTimeOut() const; -+ -+public slots: -+ virtual void triggerAction(const QString &actionId); -+ virtual void remove(); -+ virtual void linkActivated(const QString &link); -+ void startDeletionCountdown(); -+ void hide(); -+ void destroy(); -+ -+signals: -+ void changed(Notification *notification = 0); -+ -+ /** -+ * Emitted when the notification is about to be destroyed -+ **/ -+ void notificationDestroyed(Notification *notification = 0); -+ -+ /** -+ * emitted when the notification wants to hide itself -+ */ -+ void expired(Notification *notification = 0); -+ -+protected: -+ void setApplicationName(const QString &applicationName); -+ void setApplicationIcon(const QIcon &applicationIcon); -+ void setMessage(const QString &message); -+ void setSummary(const QString &summary); -+ void setImage(QImage image); -+ void setTimeout(int timeout); -+ void setActions(const QHash &actions); -+ void setActionOrder(const QStringList &actionOrder); -+ -+private: -+ class Private; -+ Private* const d; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/core/notificationsmanager.cpp b/plasma/generic/applets/notifications/core/notificationsmanager.cpp -new file mode 100644 -index 0000000..6892361 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/notificationsmanager.cpp -@@ -0,0 +1,245 @@ -+/*************************************************************************** -+ * manager.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "notificationsmanager.h" -+ -+#include -+ -+#include -+ -+#include -+ -+#include "job.h" -+#include "notification.h" -+#include "protocol.h" -+ -+#include "../protocols/notifications/dbusnotificationprotocol.h" -+#include "../protocols/jobs/dbusjobprotocol.h" -+ -+ -+static const int idleCheckInterval = 60 * 1000; -+ -+class Manager::Private -+{ -+public: -+ Private(Manager *manager) -+ : q(manager), -+ jobTotals(new Job(manager)), -+ jobProtocol(0), -+ notificationProtocol(0) -+ { -+ } -+ -+ void setupProtocol(Protocol *protocol); -+ void checkIdle(); -+ -+ Manager *q; -+ QList tasks; -+ QList notifications; -+ QList jobs; -+ Job *jobTotals; -+ Notifications *notificationsApplet; -+ Protocol *jobProtocol; -+ Protocol *notificationProtocol; -+ QTimer *idleTimer; -+ static const int s_notificationLimit = 15; -+}; -+ -+ -+Manager::Manager(Notifications *parentApplet) -+ : QObject(parentApplet), -+ d(new Private(this)) -+{ -+ d->notificationsApplet = parentApplet; -+ d->idleTimer = new QTimer(this); -+ d->idleTimer->setSingleShot(false); -+ connect(d->idleTimer, SIGNAL(timeout()), this, SLOT(checkIdle())); -+} -+ -+Manager::~Manager() -+{ -+ delete d; -+} -+ -+void Manager::registerNotificationProtocol() -+{ -+ if (!d->notificationProtocol) { -+ d->notificationProtocol = new DBusNotificationProtocol(this); -+ d->setupProtocol(d->notificationProtocol); -+ } -+} -+ -+void Manager::unregisterNotificationProtocol() -+{ -+ delete d->notificationProtocol; -+ d->notificationProtocol = 0; -+} -+ -+void Manager::addNotification(Notification* notification) -+{ -+ connect(notification, SIGNAL(notificationDestroyed(Notification*)), -+ this, SLOT(removeNotification(Notification*))); -+ connect(notification, SIGNAL(changed(Notification*)), -+ this, SIGNAL(notificationChanged(Notification*))); -+ connect(notification, SIGNAL(expired(Notification*)), -+ this, SIGNAL(notificationExpired(Notification*))); -+ -+ d->notifications.append(notification); -+ -+ if (!d->idleTimer->isActive()) { -+ d->idleTimer->start(idleCheckInterval); -+ } -+ connect(this, SIGNAL(idleTerminated()), notification, SLOT(startDeletionCountdown())); -+ -+ emit notificationAdded(notification); -+ -+ if (d->notifications.count() > d->s_notificationLimit) { -+ Notification *notification = d->notifications.first(); -+ d->notifications.pop_front(); -+ notification->deleteLater(); -+ } -+} -+ -+void Manager::removeNotification(Notification *notification) -+{ -+ d->notifications.removeAll(notification); -+ disconnect(notification, 0, this, 0); -+ disconnect(this, 0, notification, 0); -+ -+ if (d->notifications.isEmpty()) { -+ d->idleTimer->stop(); -+ } -+ -+ emit notificationRemoved(notification); -+} -+ -+QList Manager::notifications() const -+{ -+ return d->notifications; -+} -+ -+void Manager::clearNotifications() -+{ -+ qDeleteAll(d->notifications); -+ d->notifications.clear(); -+} -+ -+void Manager::registerJobProtocol() -+{ -+ if (!d->jobProtocol) { -+ d->jobProtocol = new DBusJobProtocol(this); -+ d->setupProtocol(d->jobProtocol); -+ } -+} -+ -+void Manager::unregisterJobProtocol() -+{ -+ delete d->jobProtocol; -+ d->jobProtocol = 0; -+} -+ -+void Manager::addJob(Job *job) -+{ -+ connect(job, SIGNAL(destroyed(Job*)), this, SLOT(removeJob(Job*))); -+ connect(job, SIGNAL(changed(Job*)), this, SIGNAL(jobChanged(Job*))); -+ connect(job, SIGNAL(stateChanged(Job*)), this, SIGNAL(jobStateChanged(Job*))); -+ connect(job, SIGNAL(changed(Job*)), this, SLOT(updateTotals())); -+ -+ d->jobs.append(job); -+ emit jobAdded(job); -+} -+ -+void Manager::removeJob(Job *job) -+{ -+ d->jobs.removeAll(job); -+ disconnect(job); -+ updateTotals(); -+ emit jobRemoved(job); -+} -+ -+void Manager::updateTotals() -+{ -+ uint totalPercent = 0; -+ ulong totalEta = 0; -+ foreach (Job *job, d->jobs) { -+ totalPercent += job->percentage(); -+ if (job->eta() > totalEta) { -+ totalEta = job->eta(); -+ } -+ } -+ -+ if (d->jobs.count() > 0) { -+ d->jobTotals->setPercentage(totalPercent / d->jobs.count()); -+ d->jobTotals->setMessage(i18np("1 running job (%2 remaining)", "%1 running jobs (%2 remaining)", -+ d->jobs.count(), -+ KGlobal::locale()->prettyFormatDuration(totalEta))); -+ } else { -+ d->jobTotals->setPercentage(0); -+ d->jobTotals->setMessage(i18n("no running jobs")); -+ } -+ //TODO: set a sensible icon -+} -+ -+Job *Manager::jobTotals() const -+{ -+ return d->jobTotals; -+} -+ -+QList Manager::jobs() const -+{ -+ return d->jobs; -+} -+ -+void Manager::checkIdle() -+{ -+ int totalIdle; -+#ifdef HAVE_LIBXSS // Idle detection. -+ XScreenSaverInfo* _mit_info; -+ _mit_info = XScreenSaverAllocInfo(); -+ XScreenSaverQueryInfo( QX11Info::display(), QX11Info::appRootWindow(), _mit_info ); -+ totalIdle = _mit_info->idle; -+ XFree( _mit_info ); -+#else -+ totalIdle = 0; -+#endif // HAVE_LIBXSS -+ -+ if (totalIdle < idleCheckInterval) { -+ d->idleTimer->stop(); -+ emit idleTerminated(); -+ } -+} -+ -+void Manager::Private::setupProtocol(Protocol *protocol) -+{ -+ connect(protocol, SIGNAL(jobCreated(Job*)), q, SLOT(addJob(Job*))); -+ connect(protocol, SIGNAL(notificationCreated(Notification*)), -+ q, SLOT(addNotification(Notification*))); -+ protocol->init(); -+} -+ -+Notifications *Manager::applet() const -+{ -+ return d->notificationsApplet; -+} -+ -+ -+#include "notificationsmanager.moc" -diff --git a/plasma/generic/applets/notifications/core/notificationsmanager.h b/plasma/generic/applets/notifications/core/notificationsmanager.h -new file mode 100644 -index 0000000..a6d6639 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/notificationsmanager.h -@@ -0,0 +1,161 @@ -+/*************************************************************************** -+ * manager.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONSMANAGER_H -+#define NOTIFICATIONSMANAGER_H -+ -+#include -+ -+#include -+ -+#include -+#include "../ui/notifications.h" -+ -+ -+namespace Plasma -+{ -+class Applet; -+} -+ -+class Notifications; -+class Notification; -+class Task; -+class Job; -+ -+/** -+ * w -+ * @short Creator and amalgamator of the supported system tray specifications -+ **/ -+class Manager : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ Manager(Notifications *parentApplet); -+ ~Manager(); -+ -+ /** -+ * @return a list of all known Notification instances -+ **/ -+ QList notifications() const; -+ -+ /** -+ * clear all notifications -+ */ -+ void clearNotifications(); -+ -+ /** -+ * @return a list of all known Job instances -+ **/ -+ QList jobs() const; -+ -+ /** -+ * @return a Job instance that can be used to monitor total progress -+ **/ -+ Job *jobTotals() const; -+ -+ /** -+ * Integrates the Job progress info into the applet's notification system -+ **/ -+ void registerJobProtocol(); -+ -+ /** -+ * Iintegrates the notifications into the applet's notification system -+ **/ -+ void registerNotificationProtocol(); -+ -+ /** -+ * Removes the Job progress info from the applet's notification system -+ **/ -+ void unregisterJobProtocol(); -+ -+ /** -+ * Removes the notifications from the applet's notification system -+ **/ -+ void unregisterNotificationProtocol(); -+ -+ Notifications *applet() const; -+ -+signals: -+ /** -+ * Emitted when a new notification has been added -+ **/ -+ void notificationAdded(Notification *notification); -+ -+ /** -+ * Emitted when something about a notification changes -+ **/ -+ void notificationChanged(Notification *notification); -+ -+ /** -+ * The notification is expired and wants to hide itself -+ */ -+ void notificationExpired(Notification *notification); -+ -+ /** -+ * Emitted when a notification has been removed -+ **/ -+ void notificationRemoved(Notification *notification); -+ -+ /** -+ * Emitted when a new job has been added -+ **/ -+ void jobAdded(Job *job); -+ -+ /** -+ * Emitted when the state of a job changes -+ **/ -+ void jobStateChanged(Job *job); -+ -+ /** -+ * Emitted when something about a job changes -+ **/ -+ void jobChanged(Job *job); -+ -+ /** -+ * Emitted when a job has been removed -+ **/ -+ void jobRemoved(Job *job); -+ -+ /** -+ * the pc is out of idle and is starting being used -+ */ -+ void idleTerminated(); -+ -+private slots: -+ void addNotification(Notification *notification); -+ void removeNotification(Notification *notification); -+ void addJob(Job *job); -+ void removeJob(Job *job); -+ void updateTotals(); -+ void checkIdle(); -+ -+private: -+ class Private; -+ Private* const d; -+ -+ friend class Notifications; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/core/protocol.cpp b/plasma/generic/applets/notifications/core/protocol.cpp -new file mode 100644 -index 0000000..a3716a2 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/protocol.cpp -@@ -0,0 +1,31 @@ -+/*************************************************************************** -+ * taskprotocol.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "protocol.h" -+ -+ -+Protocol::Protocol(QObject *parent) -+ : QObject(parent) -+{ -+} -+ -+ -+#include "protocol.moc" -diff --git a/plasma/generic/applets/notifications/core/protocol.h b/plasma/generic/applets/notifications/core/protocol.h -new file mode 100644 -index 0000000..ea47292 ---- /dev/null -+++ b/plasma/generic/applets/notifications/core/protocol.h -@@ -0,0 +1,68 @@ -+/*************************************************************************** -+ * taskprotocol.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef PROTOCOL_H -+#define PROTOCOL_H -+ -+#include -+ -+ -+class Job; -+class Notification; -+class Task; -+ -+ -+/** -+ * @short System tray protocol base class -+ * -+ * To support a new system tray protocol, this class and Task should be -+ * subclassed and the subclass of this class registered with the global -+ * Manager. The Protocol subclass should emit taskCreated() for each new -+ * task created. -+ **/ -+class Protocol : public QObject -+{ -+ Q_OBJECT -+public: -+ explicit Protocol(QObject *parent); -+ -+ virtual void init() = 0; -+ -+signals: -+ /** -+ * Signals that a new task has been created -+ **/ -+ void taskCreated(Task *task); -+ -+ /** -+ * Signals that a new notification has been created -+ **/ -+ void jobCreated(Job *job); -+ -+ /** -+ * Signals that a new notification has been created -+ **/ -+ void notificationCreated(Notification *notification); -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/metadata.desktop b/plasma/generic/applets/notifications/metadata.desktop -deleted file mode 100644 -index 3a2be65..0000000 ---- a/plasma/generic/applets/notifications/metadata.desktop -+++ /dev/null -@@ -1,166 +0,0 @@ --[Desktop Entry] --Encoding=UTF-8 --Name=Notifications --Name[ar]=تنبيهات --Name[ast]=Notificaciones --Name[be]=Абвяшчэнні --Name[be@latin]=Infarmavańnie --Name[bg]=Уведомяване --Name[bn]=বিজ্ঞপ্তি --Name[bn_IN]=সূচনাবার্তা --Name[br]=Kemenn --Name[bs]=obavještenja --Name[ca]=Notificacions --Name[ca@valencia]=Notificacions --Name[cs]=Oznamování --Name[csb]=Dôwanié wiédzë --Name[da]=Bekendtgørelser --Name[de]=Benachrichtigungen --Name[el]=Ειδοποιήσεις --Name[en_GB]=Notifications --Name[eo]=Atentigoj --Name[es]=Notificaciones --Name[et]=Märguanded --Name[eu]=Jakinarazpenak --Name[fa]=اخطارها --Name[fi]=Ilmoitukset --Name[fr]=Notifications --Name[fy]=Notifikaasjes --Name[ga]=Fógairt --Name[gl]=Notificacións --Name[gu]=નોંધણીઓ --Name[he]=הודעות --Name[hi]=सूचनाएँ --Name[hne]=सूचना मन ल --Name[hr]=Obavijesti --Name[hu]=Rendszerüzenetek --Name[ia]=Notificationes --Name[id]=Notifikasi --Name[is]=Kerfistilkynningar --Name[it]=Notifiche --Name[ja]=通知 --Name[kk]=Құлақтандыру --Name[km]=សេចក្តី​ជូន​ដំណឹង​ --Name[kn]=ಸೂಚನೆಗಳು --Name[ko]=알림 --Name[ku]=Agahdarî --Name[lt]=Pranešimai --Name[lv]=Paziņojumi --Name[mai]=सूचनासभ --Name[mk]=Известувања --Name[ml]=അറിയിപ്പുകള്‍ --Name[mr]=सूचना --Name[ms]=Pemberitahuan --Name[nb]=Varslinger --Name[nds]=Bescheden --Name[ne]=सूचना --Name[nl]=Meldingen --Name[nn]=Varslingar --Name[oc]=Notificacions --Name[or]=ବିଜ୍ଞପ୍ତି --Name[pa]=ਨੋਟੀਫਿਕੇਸ਼ਨ --Name[pl]=Powiadomienia --Name[pt]=Notificações --Name[pt_BR]=Notificações --Name[ro]=Notificări --Name[ru]=Системные уведомления --Name[se]=Dieđáhusat --Name[si]=දැනුම් දීම් --Name[sk]=Upozornenia --Name[sl]=Obvestila --Name[sr]=обавештења --Name[sr@ijekavian]=обавјештења --Name[sr@ijekavianlatin]=obavještenja --Name[sr@latin]=obaveštenja --Name[sv]=Underrättelser --Name[ta]=Notifications --Name[te]=నోటీసులు --Name[tg]=Огоҳиномаҳо --Name[th]=การแจ้งให้ทราบต่าง ๆ --Name[tr]=Bildirimler --Name[ug]=ئۇقتۇرۇشلار --Name[uk]=Сповіщення --Name[uz]=Xabarnomalar --Name[uz@cyrillic]=Хабарномалар --Name[wa]=Notifiaedjes --Name[x-test]=xxNotificationsxx --Name[zh_CN]=通知 --Name[zh_TW]=通知 --Comment=Display notifications and jobs --Comment[ar]=أظهر التنبيهات والمهام --Comment[ast]=Amosar notificaciones y xeres --Comment[bg]=Показване на уведомления и задачи --Comment[bs]=Prikazuje obavještenja i poslove --Comment[ca]=Mostra les notificacions i els treballs --Comment[ca@valencia]=Mostra les notificacions i els treballs --Comment[cs]=Oznámení a úlohy --Comment[da]=Vis bekendtgørelser og job --Comment[de]=Benachrichtigungen und Aktionen anzeigen --Comment[el]=Εμφανίζει ειδοποιήσεις και εργασίες --Comment[en_GB]=Display notifications and jobs --Comment[es]=Mostrar notificaciones y tareas --Comment[et]=Märguannete ja tööde näitamine --Comment[eu]=Bistaratu jakinarazpenak eta lanak --Comment[fi]=Näyttää ilmoituksia ja töitä --Comment[fr]=Affiche les notifications et les tâches --Comment[ga]=Taispeáin fógraí agus jabanna --Comment[gl]=Mostra notificacións e tarefas --Comment[he]=משמש להצגת הודעות ועבודות --Comment[hr]=Prikazuje obavijesti i poslove --Comment[hu]=Értesítések és feladatok megjelenítése --Comment[ia]=Monstra notificationes e labores --Comment[id]=Tampilan notifikasi dan tugas --Comment[is]=Birting tilkynninga og verka --Comment[it]=Mostra notifiche e processi --Comment[ja]=ディスプレイ通知とジョブ --Comment[kk]=Құлақтандыру мен тапсырмаларды көрсету --Comment[km]=បង្ហាញ​ការ​ជូនដំណឹង និង​ការងារ --Comment[kn]=ಸೂಚನೆಗಳು ಹಾಗು ಕಾರ್ಯಗಳನ್ನು ಪ್ರದರ್ಶಿಸು --Comment[ko]=알림과 작업 표시 --Comment[lt]=Rodyti pranešimus ir darbus --Comment[lv]=Parāda paziņojumus un darbus --Comment[mr]=सूचना व कार्यै दर्शवा --Comment[nb]=Vis varslinger og jobber --Comment[nds]=Bescheden un Opgaven wiesen --Comment[nl]=Meldingen en taken tonen --Comment[pa]=ਨੋਟੀਫਿਕੇਸ਼ਨ ਤੇ ਜਾਬ ਵੇਖੋ --Comment[pl]=Wyświetlanie powiadomień i zadań --Comment[pt]=Mostrar as notificações e tarefas --Comment[pt_BR]=Exibe notificações e tarefas --Comment[ro]=Afișează notificări și sarcini --Comment[ru]=Уведомления и задания --Comment[si]=කාර්ය සහ දැනුම්දීමෙ පෙන්වන්න --Comment[sk]=Zobrazenie upozornení a úloh --Comment[sl]=Prikazuje obvestila in opravila --Comment[sr]=Приказује обавештења и послове --Comment[sr@ijekavian]=Приказује обавјештења и послове --Comment[sr@ijekavianlatin]=Prikazuje obavještenja i poslove --Comment[sr@latin]=Prikazuje obaveštenja i poslove --Comment[sv]=Visa underrättelser och jobb --Comment[tg]=Иттилооти огоҳиҳо ва амалҳо --Comment[th]=แสดงการแจ้งให้ทราบและงานต่าง ๆ --Comment[tr]=Bildirimleri ve görevleri göster --Comment[ug]=ئۇقتۇرۇش ۋە ۋەزىپىلەرنى كۆرسىتىدۇ --Comment[uk]=Показ сповіщень і завдань --Comment[vi]=Hiển thị thông báo và công việc --Comment[wa]=Håyner notifiaedjes eyet bouyes --Comment[x-test]=xxDisplay notifications and jobsxx --Comment[zh_CN]=显示通知和任务 --Comment[zh_TW]=顯示通知與工作 -- --Type=Service --Icon=preferences-desktop-notification --X-KDE-ParentApp= --X-KDE-PluginInfo-Author=Davide Bettio --X-KDE-PluginInfo-Category=Tasks --X-KDE-PluginInfo-Email=davide.bettio@kdemail.net --X-KDE-PluginInfo-License=GPL --X-KDE-PluginInfo-Name=org.kde.notifications --X-KDE-PluginInfo-Version=0.1 --X-KDE-PluginInfo-Website=http://plasma.kde.org/ --X-KDE-ServiceTypes=Plasma/PopupApplet,Plasma/Applet --X-Plasma-API=declarativeappletscript --X-Plasma-DefaultSize=100,100 --X-Plasma-MainScript=ui/main.qml --X-Plasma-RequiredExtensions=LaunchApp --X-Plasma-NotificationArea=true -diff --git a/plasma/generic/applets/notifications/plasma-applet-notifications.desktop b/plasma/generic/applets/notifications/plasma-applet-notifications.desktop -new file mode 100644 -index 0000000..78a76f8 ---- /dev/null -+++ b/plasma/generic/applets/notifications/plasma-applet-notifications.desktop -@@ -0,0 +1,164 @@ -+[Desktop Entry] -+Name=Notifications -+Name[ar]=تنبيهات -+Name[ast]=Notificaciones -+Name[be]=Абвяшчэнні -+Name[be@latin]=Infarmavańnie -+Name[bg]=Уведомяване -+Name[bn]=বিজ্ঞপ্তি -+Name[bn_IN]=সূচনাবার্তা -+Name[br]=Kemenn -+Name[bs]=obavještenja -+Name[ca]=Notificacions -+Name[ca@valencia]=Notificacions -+Name[cs]=Oznamování -+Name[csb]=Dôwanié wiédzë -+Name[da]=Bekendtgørelser -+Name[de]=Benachrichtigungen -+Name[el]=Ειδοποιήσεις -+Name[en_GB]=Notifications -+Name[eo]=Atentigoj -+Name[es]=Notificaciones -+Name[et]=Märguanded -+Name[eu]=Jakinarazpenak -+Name[fa]=اخطارها -+Name[fi]=Ilmoitukset -+Name[fr]=Notifications -+Name[fy]=Notifikaasjes -+Name[ga]=Fógairt -+Name[gl]=Notificacións -+Name[gu]=નોંધણીઓ -+Name[he]=הודעות -+Name[hi]=सूचनाएँ -+Name[hne]=सूचना मन ल -+Name[hr]=Obavijesti -+Name[hu]=Rendszerüzenetek -+Name[ia]=Notificationes -+Name[id]=Notifikasi -+Name[is]=Kerfistilkynningar -+Name[it]=Notifiche -+Name[ja]=通知 -+Name[kk]=Құлақтандыру -+Name[km]=សេចក្តី​ជូន​ដំណឹង​ -+Name[kn]=ಸೂಚನೆಗಳು -+Name[ko]=알림 -+Name[ku]=Agahdarî -+Name[lt]=Pranešimai -+Name[lv]=Paziņojumi -+Name[mai]=सूचनासभ -+Name[mk]=Известувања -+Name[ml]=അറിയിപ്പുകള്‍ -+Name[mr]=सूचना -+Name[ms]=Pemberitahuan -+Name[nb]=Varslinger -+Name[nds]=Bescheden -+Name[ne]=सूचना -+Name[nl]=Meldingen -+Name[nn]=Varslingar -+Name[oc]=Notificacions -+Name[or]=ବିଜ୍ଞପ୍ତି -+Name[pa]=ਨੋਟੀਫਿਕੇਸ਼ਨ -+Name[pl]=Powiadomienia -+Name[pt]=Notificações -+Name[pt_BR]=Notificações -+Name[ro]=Notificări -+Name[ru]=Системные уведомления -+Name[se]=Dieđáhusat -+Name[si]=දැනුම් දීම් -+Name[sk]=Upozornenia -+Name[sl]=Obvestila -+Name[sr]=обавештења -+Name[sr@ijekavian]=обавјештења -+Name[sr@ijekavianlatin]=obavještenja -+Name[sr@latin]=obaveštenja -+Name[sv]=Underrättelser -+Name[ta]=Notifications -+Name[te]=నోటీసులు -+Name[tg]=Огоҳиномаҳо -+Name[th]=การแจ้งให้ทราบต่าง ๆ -+Name[tr]=Bildirimler -+Name[ug]=ئۇقتۇرۇشلار -+Name[uk]=Сповіщення -+Name[uz]=Xabarnomalar -+Name[uz@cyrillic]=Хабарномалар -+Name[wa]=Notifiaedjes -+Name[x-test]=xxNotificationsxx -+Name[zh_CN]=通知 -+Name[zh_TW]=通知 -+Comment=Display notifications and jobs -+Comment[ar]=أظهر التنبيهات والمهام -+Comment[ast]=Amosar notificaciones y xeres -+Comment[bg]=Показване на уведомления и задачи -+Comment[bs]=Prikazuje obavještenja i poslove -+Comment[ca]=Mostra les notificacions i els treballs -+Comment[ca@valencia]=Mostra les notificacions i els treballs -+Comment[cs]=Oznámení a úlohy -+Comment[da]=Vis bekendtgørelser og job -+Comment[de]=Benachrichtigungen und Aktionen anzeigen -+Comment[el]=Εμφανίζει ειδοποιήσεις και εργασίες -+Comment[en_GB]=Display notifications and jobs -+Comment[es]=Mostrar notificaciones y tareas -+Comment[et]=Märguannete ja tööde näitamine -+Comment[eu]=Bistaratu jakinarazpenak eta lanak -+Comment[fi]=Näyttää ilmoituksia ja töitä -+Comment[fr]=Affiche les notifications et les tâches -+Comment[ga]=Taispeáin fógraí agus jabanna -+Comment[gl]=Mostra notificacións e tarefas -+Comment[he]=משמש להצגת הודעות ועבודות -+Comment[hr]=Prikazuje obavijesti i poslove -+Comment[hu]=Értesítések és feladatok megjelenítése -+Comment[ia]=Monstra notificationes e labores -+Comment[id]=Tampilan notifikasi dan tugas -+Comment[is]=Birting tilkynninga og verka -+Comment[it]=Mostra notifiche e processi -+Comment[ja]=ディスプレイ通知とジョブ -+Comment[kk]=Құлақтандыру мен тапсырмаларды көрсету -+Comment[km]=បង្ហាញ​ការ​ជូនដំណឹង និង​ការងារ -+Comment[kn]=ಸೂಚನೆಗಳು ಹಾಗು ಕಾರ್ಯಗಳನ್ನು ಪ್ರದರ್ಶಿಸು -+Comment[ko]=알림과 작업 표시 -+Comment[lt]=Rodyti pranešimus ir darbus -+Comment[lv]=Parāda paziņojumus un darbus -+Comment[nb]=Vis varslinger og jobber -+Comment[nds]=Bescheden un Opgaven wiesen -+Comment[nl]=Meldingen en taken tonen -+Comment[pa]=ਨੋਟੀਫਿਕੇਸ਼ਨ ਤੇ ਜਾਬ ਵੇਖੋ -+Comment[pl]=Wyświetlanie powiadomień i zadań -+Comment[pt]=Mostrar as notificações e tarefas -+Comment[pt_BR]=Exibe notificações e tarefas -+Comment[ro]=Afișează notificări și sarcini -+Comment[ru]=Уведомления и задания -+Comment[si]=කාර්ය සහ දැනුම්දීමෙ පෙන්වන්න -+Comment[sk]=Zobrazenie upozornení a úloh -+Comment[sl]=Prikazuje obvestila in opravila -+Comment[sr]=Приказује обавештења и послове -+Comment[sr@ijekavian]=Приказује обавјештења и послове -+Comment[sr@ijekavianlatin]=Prikazuje obavještenja i poslove -+Comment[sr@latin]=Prikazuje obaveštenja i poslove -+Comment[sv]=Visa underrättelser och jobb -+Comment[tg]=Иттилооти огоҳиҳо ва амалҳо -+Comment[th]=แสดงการแจ้งให้ทราบและงานต่าง ๆ -+Comment[tr]=Bildirimleri ve görevleri göster -+Comment[ug]=ئۇقتۇرۇش ۋە ۋەزىپىلەرنى كۆرسىتىدۇ -+Comment[uk]=Показ сповіщень і завдань -+Comment[vi]=Hiển thị thông báo và công việc -+Comment[wa]=Håyner notifiaedjes eyet bouyes -+Comment[x-test]=xxDisplay notifications and jobsxx -+Comment[zh_CN]=显示通知和任务 -+Comment[zh_TW]=顯示通知與工作 -+ -+Icon=dialog-information -+Type=Service -+X-KDE-ServiceTypes=Plasma/Applet -+ -+X-KDE-Library=plasma_applet_notifications -+X-KDE-PluginInfo-Author=Marco Martin -+X-KDE-PluginInfo-Email=notmart@gmail.com -+X-KDE-PluginInfo-Name=notifications -+X-KDE-PluginInfo-Version=1.0 -+X-KDE-PluginInfo-Website=http://plasma.kde.org/ -+X-KDE-PluginInfo-Category=System Information -+X-KDE-PluginInfo-Depends= -+X-KDE-PluginInfo-License=GPL v2+ -+X-KDE-PluginInfo-EnabledByDefault=true -+ -+X-Plasma-NotificationArea=true -diff --git a/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/NotificationDelegate.qml b/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/NotificationDelegate.qml -deleted file mode 100644 -index bdb74c2..0000000 ---- a/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/NotificationDelegate.qml -+++ /dev/null -@@ -1,195 +0,0 @@ --/* -- * Copyright 2011 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- --import QtQuick 1.0 --import org.kde.plasma.core 0.1 as PlasmaCore --import org.kde.plasma.components 0.1 as PlasmaComponents --import org.kde.qtextracomponents 0.1 -- --PlasmaComponents.ListItem { -- id: notificationItem -- opacity: 1-Math.abs(x)/width -- width: popupFlickable.width -- property int toolIconSize: theme.smallMediumIconSize -- property int layoutSpacing: 4 -- -- visible: appTabBar.currentTab == allAppsTab || appTabBar.currentTab.text == appName -- -- Component.onCompleted: { -- allApplicationsModel.addApplication(appIcon, appName) -- mainScrollArea.height = mainScrollArea.implicitHeight -- } -- Component.onDestruction: { -- allApplicationsModel.removeApplication(model.appName) -- mainScrollArea.height = mainScrollArea.implicitHeight -- } -- Timer { -- interval: 10*60*1000 -- repeat: false -- running: !idleTimeSource.idle -- onTriggered: { -- notificationsModel.remove(index) -- } -- } -- -- -- MouseArea { -- width: parent.width -- height: childrenRect.height -- drag { -- target: notificationItem -- axis: Drag.XAxis -- //kind of an hack over Column being too smart -- minimumX: -parent.width + 1 -- maximumX: parent.width - 1 -- } -- onReleased: { -- if (notificationItem.x < -notificationItem.width/2) { -- removeAnimation.exitFromRight = false -- removeAnimation.running = true -- } else if (notificationItem.x > notificationItem.width/2 ) { -- removeAnimation.exitFromRight = true -- removeAnimation.running = true -- } else { -- resetAnimation.running = true -- } -- } -- SequentialAnimation { -- id: removeAnimation -- property bool exitFromRight: true -- NumberAnimation { -- target: notificationItem -- properties: "x" -- to: removeAnimation.exitFromRight ? notificationItem.width-1 : 1-notificationItem.width -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- NumberAnimation { -- target: notificationItem -- properties: "height" -- to: 0 -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- ScriptAction { -- script: notificationsModel.remove(index) -- } -- } -- SequentialAnimation { -- id: resetAnimation -- NumberAnimation { -- target: notificationItem -- properties: "x" -- to: 0 -- duration: 250 -- easing.type: Easing.InOutQuad -- } -- } -- Column { -- spacing: notificationItem.layoutSpacing -- width: parent.width -- Item { -- width: parent.width -- height: summaryLabel.height -- -- PlasmaComponents.Label { -- id: summaryLabel -- text: summary -- height: paintedHeight -- anchors { -- left: parent.left -- right: parent.right -- leftMargin: closeButton.width -- rightMargin: closeButton.width -- } -- horizontalAlignment: Text.AlignHCenter -- elide: Text.ElideRight -- } -- -- PlasmaComponents.ToolButton { -- id: closeButton -- iconSource: "window-close" -- width: notificationItem.toolIconSize -- height: width -- onClicked: removeAnimation.running = true -- anchors { -- top: parent.top -- right: parent.right -- } -- } -- } -- -- Item { -- height: childrenRect.height -- width: parent.width -- QIconItem { -- id: appIconItem -- icon: QIcon(appIcon) -- width: theme.largeIconSize -- height: theme.largeIconSize -- visible: !imageItem.visible -- anchors { -- left: parent.left -- verticalCenter: parent.verticalCenter -- } -- } -- QImageItem { -- id: imageItem -- anchors.fill: appIconItem -- image: model.image -- smooth: true -- visible: nativeWidth > 0 -- } -- PlasmaComponents.Label { -- text: body -- color: theme.textColor -- anchors { -- left: appIconItem.right -- right: actionsColumn.left -- verticalCenter: parent.verticalCenter -- leftMargin: 6 -- rightMargin: 6 -- } -- wrapMode: Text.Wrap -- } -- Column { -- id: actionsColumn -- spacing: notificationItem.layoutSpacing -- anchors { -- right: parent.right -- rightMargin: 6 -- verticalCenter: parent.verticalCenter -- } -- Repeater { -- model: actions -- PlasmaComponents.Button { -- text: model.text -- width: theme.defaultFont.mSize.width * 8 -- height: theme.defaultFont.mSize.width * 3 -- onClicked: { -- executeAction(source, model.id) -- actionsColumn.visible = false -- } -- } -- } -- } -- } -- } -- } --} -diff --git a/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/qmldir b/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/qmldir -deleted file mode 100644 -index 88fc37a..0000000 ---- a/plasma/generic/applets/notifications/platformcontents/touch/ui/NotificationDelegate/qmldir -+++ /dev/null -@@ -1 +0,0 @@ --NotificationDelegate 0.1 NotificationDelegate.qml -diff --git a/plasma/generic/applets/notifications/platformcontents/touch/ui/uiproperties.js b/plasma/generic/applets/notifications/platformcontents/touch/ui/uiproperties.js -deleted file mode 100644 -index f2f3d6b..0000000 ---- a/plasma/generic/applets/notifications/platformcontents/touch/ui/uiproperties.js -+++ /dev/null -@@ -1,23 +0,0 @@ --/* -- * Copyright 2012 Marco Martin -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU Library General Public License as -- * published by the Free Software Foundation; either version 2, or -- * (at your option) any later version. -- * -- * 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 Library General Public License for more details -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this program; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- */ -- -- --var toolIconSize = theme.mediumIconSize --var layoutSpacing = 6 --var touchInput = true -diff --git a/plasma/generic/applets/notifications/protocols/jobs/dbusjob.cpp b/plasma/generic/applets/notifications/protocols/jobs/dbusjob.cpp -new file mode 100644 -index 0000000..7c89275 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/jobs/dbusjob.cpp -@@ -0,0 +1,54 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "dbusjob.h" -+ -+#include -+ -+ -+ -+DBusJob::DBusJob(const QString &source, QObject *parent) -+ : Job(parent), -+ m_source(source) -+{ -+} -+ -+DBusJob::~DBusJob() -+{ -+ emit jobDeleted(m_source); -+} -+ -+void DBusJob::suspend() -+{ -+ emit suspend(m_source); -+ kDebug() << "suspend"; -+} -+ -+void DBusJob::resume() -+{ -+ emit resume(m_source); -+ kDebug() << "resume"; -+} -+ -+void DBusJob::stop() -+{ -+ emit stop(m_source); -+ kDebug() << "cancel"; -+} -+ -diff --git a/plasma/generic/applets/notifications/protocols/jobs/dbusjob.h b/plasma/generic/applets/notifications/protocols/jobs/dbusjob.h -new file mode 100644 -index 0000000..2e973d6 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/jobs/dbusjob.h -@@ -0,0 +1,54 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef DBUSJOB_H -+#define DBUSJOB_H -+ -+#include "../../core/job.h" -+ -+ -+ -+class DBusJob : public Job -+{ -+ Q_OBJECT -+ -+ friend class DBusJobProtocol; -+ -+public: -+ DBusJob(const QString &source, QObject *parent = 0); -+ ~DBusJob(); -+ -+public slots: -+ void suspend(); -+ void resume(); -+ void stop(); -+ -+signals: -+ void jobDeleted(const QString &source); -+ void suspend(const QString &source); -+ void resume(const QString &source); -+ void stop(const QString &source); -+ -+private: -+ QString m_source; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.cpp b/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.cpp -new file mode 100644 -index 0000000..dff6dc9 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.cpp -@@ -0,0 +1,180 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "dbusjob.h" -+#include "dbusjobprotocol.h" -+ -+ -+#include -+ -+#include -+#include -+#include -+ -+static const char engineName[] = "applicationjobs"; -+ -+DBusJobProtocol::DBusJobProtocol(Manager *parent) -+ : Protocol(parent), -+ m_manager(parent), -+ m_engine(0) -+{ -+} -+ -+ -+DBusJobProtocol::~DBusJobProtocol() -+{ -+ if (m_engine) { -+ Plasma::DataEngineManager::self()->unloadEngine(engineName); -+ } -+ -+ foreach (DBusJob *job, m_jobs) { -+ disconnect(job); -+ job->destroy(); -+ } -+ -+ m_jobs.clear(); -+} -+ -+ -+void DBusJobProtocol::init() -+{ -+ m_engine = Plasma::DataEngineManager::self()->loadEngine(engineName); -+ -+ if (!m_engine->isValid()) { -+ Plasma::DataEngineManager::self()->unloadEngine(engineName); -+ m_engine = 0; -+ return; -+ } -+ -+ connect(m_engine, SIGNAL(sourceAdded(QString)), -+ this, SLOT(prepareJob(QString))); -+ connect(m_engine, SIGNAL(sourceRemoved(QString)), -+ this, SLOT(removeJob(QString))); -+} -+ -+void DBusJobProtocol::prepareJob(const QString &source) -+{ -+ m_engine->connectSource(source, this); -+} -+ -+void DBusJobProtocol::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) -+{ -+ DBusJob *job = m_jobs.value(source, 0); -+ -+ if (!job) { -+ job = new DBusJob(source, this); -+ m_jobs.insert(source, job); -+ connect(job, SIGNAL(jobDeleted(QString)), -+ this, SLOT(removeJob(QString))); -+ connect(job, SIGNAL(suspend(QString)), -+ this, SLOT(suspend(QString))); -+ connect(job, SIGNAL(resume(QString)), -+ this, SLOT(resume(QString))); -+ connect(job, SIGNAL(stop(QString)), -+ this, SLOT(stop(QString))); -+ connect(job, SIGNAL(ready(Job*)), -+ this, SIGNAL(jobCreated(Job*))); -+ } -+ -+ job->setApplicationName(data.value("appName").toString()); -+ job->setApplicationIconName(data.value("appIconName").toString()); -+ job->setPercentage(data["percentage"].toUInt()); -+ job->setError(data["error"].toString()); -+ job->setMessage(data["infoMessage"].toString()); -+ job->setSuspendable(data["suspendable"].toBool()); -+ job->setKillable(data["killable"].toBool()); -+ job->setSpeed(data["speed"].toString()); -+ job->setNumericSpeed(data["numericSpeed"].toLongLong()); -+ job->setEta(data["eta"].toULongLong()); -+ -+ if (data["state"].toString() == "running") { -+ job->setState(Job::Running); -+ } else if (data["state"].toString() == "suspended") { -+ job->setState(Job::Suspended); -+ } else { -+ job->setState(Job::Stopped); -+ } -+ -+ int i = 0; -+ QList > labels; -+ while (data.contains(QString("label%1").arg(i))) { -+ QPair label; -+ label.first = data[QString("labelName%1").arg(i)].toString(); -+ label.second = data[QString("label%1").arg(i)].toString(); -+ labels << label; -+ i++; -+ } -+ job->setLabels(labels); -+ -+ i = 0; -+ QMap totalAmounts; -+ while (data.contains(QString("totalUnit%1").arg(i))) { -+ QString unit = data[QString("totalUnit%1").arg(i)].toString(); -+ qlonglong amount = data[QString("totalAmount%1").arg(i)].toLongLong(); -+ totalAmounts[unit] = amount; -+ i++; -+ } -+ job->setTotalAmounts(totalAmounts); -+ -+ i = 0; -+ QMap processedAmounts; -+ while (data.contains(QString("processedUnit%1").arg(i))) { -+ QString unit = data[QString("processedUnit%1").arg(i)].toString(); -+ qlonglong amount = data[QString("processedAmount%1").arg(i)].toLongLong(); -+ processedAmounts[unit] = amount; -+ i++; -+ } -+ -+ job->setProcessedAmounts(processedAmounts); -+} -+ -+void DBusJobProtocol::removeJob(const QString &source) -+{ -+ if (m_jobs.contains(source)) { -+ DBusJob *job = m_jobs.take(source); -+ job->setState(Job::Stopped); -+ job->destroy(); -+ } -+} -+ -+void DBusJobProtocol::suspend(const QString &source) -+{ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("suspend"); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+} -+ -+void DBusJobProtocol::resume(const QString &source) -+{ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("resume"); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+} -+ -+void DBusJobProtocol::stop(const QString &source) -+{ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("stop"); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+} -+ -+#include "dbusjobprotocol.moc" -diff --git a/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.h b/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.h -new file mode 100644 -index 0000000..230356c ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/jobs/dbusjobprotocol.h -@@ -0,0 +1,57 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef DBUSJOBPROTOCOL_H -+#define DBUSJOBPROTOCOL_H -+ -+#include "../../core/protocol.h" -+#include "../../core/notificationsmanager.h" -+ -+#include -+ -+ -+class DBusJob; -+ -+class DBusJobProtocol : public Protocol -+{ -+ Q_OBJECT -+ -+public: -+ DBusJobProtocol(Manager *parent); -+ ~DBusJobProtocol(); -+ void init(); -+ -+private slots: -+ void prepareJob(const QString &source); -+ void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data); -+ void removeJob(const QString &source); -+ //void relayAction(const QString &source, const QString &actionName); -+ void suspend(const QString &source); -+ void resume(const QString &source); -+ void stop(const QString &source); -+ -+private: -+ Manager *m_manager; -+ Plasma::DataEngine *m_engine; -+ QHash m_jobs; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.cpp b/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.cpp -new file mode 100644 -index 0000000..2c28ff2 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.cpp -@@ -0,0 +1,48 @@ -+/*************************************************************************** -+ * dbusnotification.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "dbusnotification.h" -+ -+#include -+ -+ -+DBusNotification::DBusNotification(const QString &source, QObject *parent) -+ : Notification(parent), -+ m_source(source) -+{ -+} -+ -+DBusNotification::~DBusNotification() -+{ -+ emit notificationDeleted(m_source); -+} -+ -+void DBusNotification::remove() -+{ -+ emit unregisterNotification(m_source); -+ deleteLater(); -+} -+ -+void DBusNotification::triggerAction(const QString &actionId) -+{ -+ emit actionTriggered(m_source, actionId); -+} -+ -diff --git a/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.h b/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.h -new file mode 100644 -index 0000000..213cc71 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/notifications/dbusnotification.h -@@ -0,0 +1,54 @@ -+/*************************************************************************** -+ * dbusnotification.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef DBUSNOTIFICATION_H -+#define DBUSNOTIFICATION_H -+ -+#include "../../core/notification.h" -+ -+ -+ -+class DBusNotification : public Notification -+{ -+ Q_OBJECT -+ -+ friend class DBusNotificationProtocol; -+ -+public: -+ DBusNotification(const QString &source, QObject *parent = 0); -+ ~DBusNotification(); -+ -+public slots: -+ void remove(); -+ void triggerAction(const QString &actionId); -+ -+signals: -+ void notificationDeleted(const QString &source); -+ void actionTriggered(const QString &source, const QString &actionId); -+ void unregisterNotification(const QString &source); -+ -+private: -+ QString m_source; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.cpp b/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.cpp -new file mode 100644 -index 0000000..fd94048 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.cpp -@@ -0,0 +1,192 @@ -+/*************************************************************************** -+ * fdoprotocol.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "dbusnotification.h" -+#include "dbusnotificationprotocol.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+ -+static const char engineName[] = "notifications"; -+ -+DBusNotificationProtocol::DBusNotificationProtocol(Manager *parent) -+ : Protocol(parent), -+ m_manager(parent), -+ m_engine(0) -+{ -+} -+ -+ -+DBusNotificationProtocol::~DBusNotificationProtocol() -+{ -+ if (m_engine) { -+ Plasma::DataEngineManager::self()->unloadEngine(engineName); -+ } -+} -+ -+ -+void DBusNotificationProtocol::init() -+{ -+ m_engine = Plasma::DataEngineManager::self()->loadEngine(engineName); -+ -+ if (!m_engine->isValid()) { -+ m_engine = 0; -+ Plasma::DataEngineManager::self()->unloadEngine(engineName); -+ return; -+ } -+ -+ connect(m_engine, SIGNAL(sourceAdded(QString)), -+ this, SLOT(prepareNotification(QString))); -+ connect(m_engine, SIGNAL(sourceRemoved(QString)), -+ this, SLOT(hideNotification(QString))); -+} -+ -+ -+void DBusNotificationProtocol::prepareNotification(const QString &source) -+{ -+ if (m_engine) { -+ m_engine->connectSource(source, this); -+ } -+} -+ -+ -+void DBusNotificationProtocol::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) -+{ -+ bool isNew = !m_notifications.contains(source); -+ -+ if (isNew) { -+ DBusNotification * notification = new DBusNotification(source, this); -+ connect(notification, SIGNAL(unregisterNotification(QString)), -+ this, SLOT(unregisterNotification(QString))); -+ connect(notification, SIGNAL(notificationDeleted(QString)), -+ this, SLOT(notificationDeleted(QString))); -+ connect(notification, SIGNAL(actionTriggered(QString,QString)), -+ this, SLOT(relayAction(QString,QString))); -+ m_notifications[source] = notification; -+ } -+ -+ DBusNotification* notification = m_notifications[source]; -+ notification->setApplicationName(data.value("appName").toString()); -+ notification->setApplicationIcon(KIcon(data.value("appIcon").toString())); -+ notification->setSummary(data.value("summary").toString()); -+ notification->setMessage(data.value("body").toString()); -+ notification->setTimeout(data.value("expireTimeout").toInt()); -+ notification->setUrgency(data.value("urgency").toInt()); -+ -+ if (data.contains("image")) { -+ QImage image = qvariant_cast(data.value("image")); -+ notification->setImage(image); -+ } -+ -+ QStringList codedActions = data.value("actions").toStringList(); -+ if (codedActions.count() % 2 != 0) { -+ kDebug() << "Invalid actions" << codedActions << "from" << notification->applicationName(); -+ codedActions.clear(); -+ } -+ -+ QHash actions; -+ QStringList actionOrder; -+ -+ while (!codedActions.isEmpty()) { -+ QString actionId = codedActions.takeFirst(); -+ QString actionName = codedActions.takeFirst(); -+ actions.insert(actionId, actionName); -+ actionOrder.append(actionId); -+ } -+ -+ notification->setActions(actions); -+ notification->setActionOrder(actionOrder); -+ -+ if (isNew) { -+ emit notificationCreated(notification); -+ } else { -+ emit notification->changed(notification); -+ } -+} -+ -+ -+void DBusNotificationProtocol::relayAction(const QString &source, const QString &actionId) -+{ -+ if (!m_engine) { -+ return; -+ } -+ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("invokeAction"); -+ -+ if (op.isValid()) { -+ op.writeEntry("actionId", actionId); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+ } else { -+ delete service; -+ kDebug() << "invalid operation"; -+ } -+} -+ -+void DBusNotificationProtocol::unregisterNotification(const QString &source) -+{ -+ if (!m_engine) { -+ return; -+ } -+ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("userClosed"); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+} -+ -+void DBusNotificationProtocol::hideNotification(const QString &source) -+{ -+ if (m_notifications.contains(source)) { -+ m_notifications.value(source)->hide(); -+ } -+} -+ -+void DBusNotificationProtocol::removeNotification(const QString &source) -+{ -+ if (m_notifications.contains(source)) { -+ m_notifications.take(source)->destroy(); -+ } -+} -+ -+void DBusNotificationProtocol::notificationDeleted(const QString &source) -+{ -+ if (!m_engine) { -+ return; -+ } -+ -+ Plasma::Service *service = m_engine->serviceForSource(source); -+ KConfigGroup op = service->operationDescription("userClosed"); -+ KJob *job = service->startOperationCall(op); -+ connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); -+ -+ m_notifications.remove(source); -+} -+ -+ -+#include "dbusnotificationprotocol.moc" -diff --git a/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.h b/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.h -new file mode 100644 -index 0000000..e52dfd9 ---- /dev/null -+++ b/plasma/generic/applets/notifications/protocols/notifications/dbusnotificationprotocol.h -@@ -0,0 +1,62 @@ -+/*************************************************************************** -+ * dbusnotificationprotocol.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2008 Dmitry Suzdalev * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef DBUSNOTIFICATIONPROTOCOL_H -+#define DBUSNOTIFICATIONPROTOCOL_H -+ -+#include "../../core/protocol.h" -+#include "../../core/notificationsmanager.h" -+ -+#include -+ -+#include -+ -+ -+class DBusNotification; -+ -+class DBusNotificationProtocol : public Protocol -+{ -+ Q_OBJECT -+ -+public: -+ DBusNotificationProtocol(Manager *parent); -+ ~DBusNotificationProtocol(); -+ void init(); -+ -+private slots: -+ void prepareNotification(const QString &source); -+ void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data); -+ void removeNotification(const QString &source); -+ void notificationDeleted(const QString &source); -+ void relayAction(const QString &source, const QString &actionId); -+ void unregisterNotification(const QString&); -+ void hideNotification(const QString &source); -+ -+private: -+ Manager *m_manager; -+ Plasma::DataEngine *m_engine; -+ QHash m_notifications; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/busywidget.cpp b/plasma/generic/applets/notifications/ui/busywidget.cpp -new file mode 100644 -index 0000000..6bce0d7 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/busywidget.cpp -@@ -0,0 +1,352 @@ -+/*************************************************************************** -+ * Copyright (C) 2008, 2009 Rob Scheepmaker * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "busywidget.h" -+#include -+ -+#include -+#include -+#include -+#include // QWIDGETSIZE_MAX -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "../core/notificationsmanager.h" -+#include "../core/job.h" -+#include "../core/notification.h" -+#include "../core/completedjobnotification.h" -+ -+ -+ -+BusyWidget::BusyWidget(Plasma::PopupApplet *parent, const Manager *manager) -+ : Plasma::BusyWidget(parent), -+ m_icon("dialog-information"), -+ m_state(Empty), -+ m_svg(new Plasma::Svg(this)), -+ m_systray(parent), -+ m_manager(manager), -+ m_total(0), -+ m_suppressToolTips(false) -+{ -+ setAcceptsHoverEvents(true); -+ m_svg->setImagePath("icons/notification"); -+ m_svg->setContainsMultipleImages(true); -+ setRunning(false); -+ -+ m_fadeInAnimation = Plasma::Animator::create(Plasma::Animator::PixmapTransitionAnimation); -+ m_fadeInAnimation->setTargetWidget(this); -+ m_fadeInAnimation->setProperty("duration", 1000); -+ m_fadeInAnimation->setProperty("targetPixmap", m_svg->pixmap("notification-active")); -+ -+ m_fadeOutAnimation = Plasma::Animator::create(Plasma::Animator::PixmapTransitionAnimation); -+ m_fadeOutAnimation->setTargetWidget(this); -+ m_fadeOutAnimation->setProperty("duration", 1000); -+ m_fadeOutAnimation->setProperty("startPixmap", m_svg->pixmap("notification-active")); -+ -+ -+ m_fadeGroup = new QSequentialAnimationGroup(this); -+ m_fadeGroup->addAnimation(m_fadeInAnimation); -+ m_fadeGroup->addAnimation(m_fadeOutAnimation); -+ -+ connect(manager, SIGNAL(notificationAdded(Notification*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(notificationRemoved(Notification*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(notificationChanged(Notification*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(notificationExpired(Notification*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(jobAdded(Job*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(jobRemoved(Job*)), -+ this, SLOT(updateTask())); -+ connect(manager, SIGNAL(jobStateChanged(Job*)), -+ this, SLOT(updateTask())); -+ -+ Plasma::Extender *extender = qobject_cast(m_systray->graphicsWidget()); -+ if (extender) { -+ connect(extender, SIGNAL(itemDetached(Plasma::ExtenderItem*)), -+ this, SLOT(updateTask())); -+ } -+ -+ Plasma::ToolTipManager::self()->registerWidget(this); -+ updateTask(); -+} -+ -+void BusyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -+{ -+ QRectF iconRect(0, 0, qMin(size().width(), size().height()), qMin(size().width(), size().height())); -+ iconRect.moveCenter(boundingRect().center()); -+ -+ if (m_state == Running) { -+ const int arcStart = 90*16; -+ const int arcEnd = -(360*(qreal)m_manager->jobTotals()->percentage()/100)*16; -+ -+ Plasma::BusyWidget::paint(painter, option, widget); -+ -+ //kDebug() << arcStart << arcEnd; -+ -+ QPixmap activePixmap(iconRect.size().toSize()); -+ activePixmap.fill(Qt::transparent); -+ QPixmap inActivePixmap(iconRect.size().toSize()); -+ inActivePixmap.fill(Qt::transparent); -+ QRect pieRect(QPoint(0, 0), activePixmap.size()*2); -+ pieRect.moveCenter(activePixmap.rect().center()); -+ -+ QPainter p(&activePixmap); -+ p.setPen(Qt::NoPen); -+ p.setBrush(Qt::black); -+ p.setCompositionMode(QPainter::CompositionMode_Source); -+ p.drawPie(pieRect, arcStart, arcEnd); -+ p.setCompositionMode(QPainter::CompositionMode_SourceIn); -+ m_svg->paint(&p, QRectF(QPointF(0, 0), iconRect.size()), "notification-progress-active"); -+ p.end(); -+ -+ p.begin(&inActivePixmap); -+ p.setPen(Qt::NoPen); -+ p.setBrush(Qt::black); -+ p.setCompositionMode(QPainter::CompositionMode_Source); -+ p.drawPie(pieRect, arcStart, (360*16)+arcEnd); -+ p.setCompositionMode(QPainter::CompositionMode_SourceIn); -+ m_svg->paint(&p, QRectF(QPointF(0, 0), iconRect.size()), "notification-progress-inactive"); -+ p.end(); -+ -+ painter->drawPixmap(iconRect.topLeft().toPoint(), activePixmap); -+ painter->drawPixmap(iconRect.topLeft().toPoint(), inActivePixmap); -+ -+ Plasma::BusyWidget::paint(painter, option, widget); -+ -+ } else if (m_state == Empty && m_manager->notifications().count() > 0) { -+ m_svg->paint(painter, iconRect, "notification-inactive"); -+ } else if (m_state == Empty && m_manager->notifications().count() == 0) { -+ m_svg->paint(painter, iconRect, "notification-disabled"); -+ } else { -+ // m_state == Info -+ m_svg->paint(painter, iconRect, "notification-empty"); -+ QFont font(KGlobalSettings::smallestReadableFont()); -+ painter->setFont(font); -+ QRectF r = rect(); -+ -+ painter->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor)); -+ -+ const QFontMetrics fm(font); -+ const QSize textSize = fm.boundingRect(label()).size(); -+ const bool textFits = textSize.width() <= r.width() && textSize.height() <= r.height(); -+ if (m_svg && m_svg->hasElement(expanderElement())) { -+ QSizeF arrowSize(m_svg->elementSize(expanderElement())); -+ QRectF arrowRect(r.center() - QPointF(arrowSize.width() / 2, arrowSize.height() + fm.xHeight() / 2), arrowSize); -+ m_svg->paint(painter, arrowRect, expanderElement()); -+ -+ r.setTop(arrowRect.bottom()); -+ -+ if (textFits) { -+ painter->drawText(r, Qt::AlignHCenter|Qt::AlignTop, label()); -+ } -+ } else if (textFits) { -+ painter->drawText(r, Qt::AlignCenter, label()); -+ } -+ } -+ -+ if (m_fadeInAnimation->state() == QAbstractAnimation::Running) { -+ QPixmap pix = m_fadeInAnimation->property("currentPixmap").value(); -+ painter->drawPixmap(iconRect, pix, pix.rect()); -+ } else if (m_fadeOutAnimation->state() == QAbstractAnimation::Running) { -+ QPixmap pix = m_fadeOutAnimation->property("currentPixmap").value(); -+ painter->drawPixmap(iconRect, pix, pix.rect()); -+ } -+} -+ -+void BusyWidget::resizeEvent(QGraphicsSceneResizeEvent *) -+{ -+ //regenerate pixmaps -+ m_svg->resize(contentsRect().size()); -+ m_fadeInAnimation->setProperty("targetPixmap", m_svg->pixmap("notification-active")); -+ m_fadeOutAnimation->setProperty("startPixmap", m_svg->pixmap("notification-active")); -+ m_svg->resize(); -+} -+ -+void BusyWidget::setState(State state) -+{ -+ if (m_state == state) { -+ return; -+ } -+ -+ m_state = state; -+ setRunning(m_state == Running); -+ update(); -+} -+ -+QString BusyWidget::expanderElement() const -+{ -+ switch (m_systray->location()) { -+ case Plasma::TopEdge: -+ return "expander-top"; -+ case Plasma::RightEdge: -+ return "expander-right"; -+ case Plasma::LeftEdge: -+ return "expander-left"; -+ case Plasma::BottomEdge: -+ default: -+ return "expander-bottom"; -+ } -+} -+ -+void BusyWidget::getJobCounts(int &runningJobs, int &pausedJobs, int &completedJobs, int &jobSpeed) -+{ -+ runningJobs = pausedJobs = completedJobs = jobSpeed = 0; -+ foreach (const Job *job, m_manager->jobs()) { -+ switch (job->state()) { -+ case Job::Running: -+ jobSpeed += job->numericSpeed(); -+ ++runningJobs; -+ break; -+ case Job::Suspended: -+ ++pausedJobs; -+ break; -+ default: -+ break; -+ } -+ } -+ -+} -+ -+void BusyWidget::updateTask() -+{ -+ int runningJobs, pausedJobs, completedJobs, jobSpeed; -+ getJobCounts(runningJobs, pausedJobs, completedJobs, jobSpeed); -+ -+ int total = m_manager->jobs().count(); -+ int activeNotifications = 0; -+ bool hasOldNotifications = false; -+ -+ foreach (Notification *notification, m_manager->notifications()) { -+ if (qobject_cast(notification)) { -+ ++completedJobs; -+ } else if (notification->isExpired()) { -+ hasOldNotifications = true; -+ } else { -+ ++activeNotifications; -+ } -+ } -+ -+ total += completedJobs + activeNotifications; -+ -+ if (total + m_manager->notifications().count() < 0) { -+ m_systray->hidePopup(); -+ } -+ -+ if (total > m_total) { -+ m_fadeGroup->start(); -+ } -+ -+ m_total = total; -+ -+ if (activeNotifications > 0) { -+ m_systray->setStatus(Plasma::NeedsAttentionStatus); -+ } else if (m_total > 0 || hasOldNotifications) { -+ m_systray->setStatus(Plasma::ActiveStatus); -+ } else { -+ m_systray->setStatus(Plasma::PassiveStatus); -+ } -+ -+ if (!total) { -+ setState(BusyWidget::Empty); -+ setLabel(QString()); -+ } else if (runningJobs) { -+ setState(BusyWidget::Running); -+ setLabel(QString("%1").arg(QString::number(total))); -+ } else { -+ setState(BusyWidget::Info); -+ setLabel(QString::number(total)); -+ } -+ -+ if (Plasma::ToolTipManager::self()->isVisible(this)) { -+ toolTipAboutToShow(); -+ } -+} -+ -+void BusyWidget::suppressToolTips(bool suppress) -+{ -+ m_suppressToolTips = suppress; -+} -+ -+void BusyWidget::toolTipAboutToShow() -+{ -+ if (m_suppressToolTips) { -+ Plasma::ToolTipManager::self()->setContent(this, Plasma::ToolTipContent()); -+ return; -+ } -+ -+ int runningJobs, pausedJobs, completedJobs, jobSpeed; -+ getJobCounts(runningJobs, pausedJobs, completedJobs, jobSpeed); -+ -+ //make a nice plasma tooltip -+ QString tooltipContent; -+ if (runningJobs > 0) { -+ tooltipContent += i18ncp("Number of jobs and the speed at which they are downloading", -+ "%1 running job (%2/s)", "%1 running jobs (%2/s)", runningJobs, -+ KGlobal::locale()->formatByteSize(jobSpeed)); -+ if (pausedJobs > 0 || completedJobs > 0 || !m_manager->notifications().isEmpty()) { -+ tooltipContent += "
"; -+ } -+ } -+ -+ if (pausedJobs > 0) { -+ tooltipContent += i18np("%1 suspended job", "%1 suspended jobs", pausedJobs); -+ if (completedJobs > 0 || !m_manager->notifications().isEmpty()) { -+ tooltipContent += "
"; -+ } -+ } -+ -+ if (completedJobs > 0) { -+ tooltipContent += i18np("%1 completed job", "%1 completed jobs", completedJobs); -+ if (!m_manager->notifications().isEmpty()) { -+ tooltipContent += "
"; -+ } -+ } -+ -+ if (!m_manager->notifications().isEmpty()) { -+ tooltipContent += i18np("%1 notification", "%1 notifications", -+ m_manager->notifications().count()); -+ } -+ -+ if (tooltipContent.isEmpty()) { -+ tooltipContent = i18n("No active jobs or notifications"); -+ } -+ -+ Plasma::ToolTipContent data(i18n("Notifications and jobs"), -+ tooltipContent, -+ KIcon("help-about")); -+ Plasma::ToolTipManager::self()->setContent(this, data); -+} -+ -+ -+#include "busywidget.moc" -diff --git a/plasma/generic/applets/notifications/ui/busywidget.h b/plasma/generic/applets/notifications/ui/busywidget.h -new file mode 100644 -index 0000000..ae5f994 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/busywidget.h -@@ -0,0 +1,80 @@ -+/*************************************************************************** -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONBUSYWIDGET_H -+#define NOTIFICATIONBUSYWIDGET_H -+ -+#include -+ -+#include -+ -+class QStyleOptionGraphicsItem; -+class QSequentialAnimationGroup; -+ -+namespace Plasma -+{ -+ class Animation; -+ class Extender; -+ class PopupApplet; -+ class Svg; -+} -+ -+ -+class Manager; -+ -+class BusyWidget : public Plasma::BusyWidget -+{ -+ Q_OBJECT -+ -+public: -+ enum State { Empty, Info, Running }; -+ -+ BusyWidget(Plasma::PopupApplet *parent, const Manager *manager); -+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); -+ void setState(State state); -+ void suppressToolTips(bool suppress); -+ -+public slots: -+ void toolTipAboutToShow(); -+ -+protected: -+ void resizeEvent(QGraphicsSceneResizeEvent *event); -+ -+protected slots: -+ void updateTask(); -+ -+private: -+ QString expanderElement() const; -+ void getJobCounts(int &runningJobs, int &pausedJobs, int &completedJobs, int &jobSpeed); -+ -+ KIcon m_icon; -+ State m_state; -+ Plasma::Svg *m_svg; -+ Plasma::PopupApplet *m_systray; -+ const Manager *m_manager; -+ Plasma::Animation *m_fadeInAnimation; -+ Plasma::Animation *m_fadeOutAnimation; -+ QSequentialAnimationGroup *m_fadeGroup; -+ int m_total; -+ bool m_suppressToolTips; -+}; -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/jobtotalswidget.cpp b/plasma/generic/applets/notifications/ui/jobtotalswidget.cpp -new file mode 100644 -index 0000000..6552ed3 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/jobtotalswidget.cpp -@@ -0,0 +1,94 @@ -+/*************************************************************************** -+ * Copyright 2009 by Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "jobtotalswidget.h" -+#include "../core/job.h" -+ -+#include -+#include -+ -+static const int UPDATE_TIMER_INTERVAL = 200; -+ -+ -+JobTotalsWidget::JobTotalsWidget(Job *job, QGraphicsWidget *parent) -+ : Meter(parent), -+ m_job(job), -+ m_updateTimerId(0) -+{ -+ m_extenderGroup = qobject_cast(parent), -+ -+ setSvg("widgets/bar_meter_horizontal"); -+ setMeterType(Plasma::Meter::BarMeterHorizontal); -+ -+ setMinimumWidth(350); -+ setMinimumHeight(16); -+ setMaximumHeight(16); -+ setMaximum(100); -+ setValue(0); -+ -+ if (m_job) { -+ connect(m_job, SIGNAL(changed(Job*)), -+ this, SLOT(scheduleJobUpdate())); -+ -+ updateJob(); -+ } -+} -+ -+JobTotalsWidget::~JobTotalsWidget() -+{ -+} -+ -+void JobTotalsWidget::scheduleJobUpdate() -+{ -+ if (!m_updateTimerId) { -+ m_updateTimerId = startTimer(UPDATE_TIMER_INTERVAL); -+ } -+} -+ -+void JobTotalsWidget::timerEvent(QTimerEvent *event) -+{ -+ if (event->timerId() == m_updateTimerId) { -+ killTimer(m_updateTimerId); -+ m_updateTimerId = 0; -+ updateJob(); -+ } else { -+ Meter::timerEvent(event); -+ } -+} -+ -+void JobTotalsWidget::updateJob() -+{ -+ setValue(m_job->percentage()); -+ -+ if (m_extenderGroup) { -+ if (m_extenderGroup->items().count() > 1 || m_extenderGroup->isGroupCollapsed()) { -+ m_extenderGroup->setTitle(m_job->message()); -+ } else { -+ m_extenderGroup->setTitle(i18nc("Generic title for the job transfer popup", "Jobs")); -+ } -+ m_extenderGroup->setIcon(m_job->applicationIconName()); -+ } else { -+ setLabelAlignment(0, Qt::AlignLeft|Qt::AlignVCenter); -+ setLabel(0, m_job->message()); -+ } -+} -+ -+ -+#include "jobtotalswidget.moc" -+ -diff --git a/plasma/generic/applets/notifications/ui/jobtotalswidget.h b/plasma/generic/applets/notifications/ui/jobtotalswidget.h -new file mode 100644 -index 0000000..4f07c86 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/jobtotalswidget.h -@@ -0,0 +1,65 @@ -+/*************************************************************************** -+ * Copyright 2009 by Rob Scheepmaker -+ -+#include -+#include -+#include -+#include -+ -+namespace Plasma -+{ -+ class ExtenderItem; -+ class Meter; -+} // namespace Plasma -+ -+ -+class Job; -+ -+class JobTotalsWidget : public Plasma::Meter -+{ -+ Q_OBJECT -+ -+ public: -+ explicit JobTotalsWidget(Job *job, QGraphicsWidget *parent); -+ ~JobTotalsWidget(); -+ -+ protected: -+ void timerEvent(QTimerEvent *event); -+ -+ private Q_SLOTS: -+ void scheduleJobUpdate(); -+ -+ private: -+ void updateJob(); -+ -+ Plasma::ExtenderGroup *m_extenderGroup; -+ Job *m_job; -+ int m_updateTimerId; -+}; -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/jobwidget.cpp b/plasma/generic/applets/notifications/ui/jobwidget.cpp -new file mode 100644 -index 0000000..06096fd ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/jobwidget.cpp -@@ -0,0 +1,435 @@ -+/*************************************************************************** -+ * Copyright 2008 by Rob Scheepmaker * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "jobwidget.h" -+#include "../core/job.h" -+ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static const int UPDATE_INTERVAL = 200; -+ -+JobWidget::JobWidget(Job *job, Plasma::ExtenderItem *parent) -+ : QGraphicsWidget(parent), -+ m_extenderItem(parent), -+ m_job(job), -+ m_updateTimerId(0), -+ m_extenderItemDestroyed(false) -+{ -+ Q_ASSERT(m_extenderItem); -+ -+ m_meter = new Plasma::Meter(this); -+ m_meter->setSvg("widgets/bar_meter_horizontal"); -+ m_meter->setMeterType(Plasma::Meter::BarMeterHorizontal); -+ m_meter->setMaximumHeight(16); -+ m_meter->setMaximum(100); -+ m_meter->setValue(0); -+ -+ m_plotter = new Plasma::SignalPlotter(this); -+ m_plotter->setUseAutoRange(true); -+ m_plotter->setShowVerticalLines(false); -+ m_plotter->setUnit(i18n("KiB/s")); -+ m_plotter->addPlot(Plasma::Theme::defaultTheme()->color(Plasma::Theme::HighlightColor)); -+ -+ m_fromNameLabel = new Plasma::Label(this); -+ m_fromLabel = new Plasma::Label(this); -+ m_toNameLabel = new Plasma::Label(this); -+ m_toLabel = new Plasma::Label(this); -+ m_totalBytesLabel = new Plasma::Label(this); -+ m_dirCountLabel = new Plasma::Label(this); -+ m_fileCountLabel = new Plasma::Label(this); -+ m_eta = new Plasma::Label(this); -+ m_details = new Plasma::IconWidget(this); -+ m_details->setSvg("widgets/action-overlays", "add-normal"); -+ m_details->setMaximumSize(KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium); -+ m_details->setMinimumSize(KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium); -+ -+ m_totalBytesLabel->setVisible(false); -+ m_dirCountLabel->setVisible(false); -+ m_fileCountLabel->setVisible(false); -+ m_plotter->setVisible(false); -+ -+ m_fromNameLabel->setAlignment(Qt::AlignRight); -+ m_fromLabel->setAlignment(Qt::AlignLeft); -+ m_toNameLabel->setAlignment(Qt::AlignRight); -+ m_toLabel->setAlignment(Qt::AlignLeft); -+ m_totalBytesLabel->setAlignment(Qt::AlignRight); -+ m_dirCountLabel->setAlignment(Qt::AlignRight); -+ m_fileCountLabel->setAlignment(Qt::AlignRight); -+ m_eta->setAlignment(Qt::AlignRight); -+ -+ m_fromLabel->nativeWidget()->setWordWrap(false); -+ m_toLabel->nativeWidget()->setWordWrap(false); -+ m_dirCountLabel->nativeWidget()->setWordWrap(false); -+ m_fileCountLabel->nativeWidget()->setWordWrap(false); -+ m_totalBytesLabel->nativeWidget()->setWordWrap(false); -+ m_eta->nativeWidget()->setWordWrap(false); -+ -+ m_layout = new QGraphicsGridLayout(this); -+ m_layout->addItem(m_fromNameLabel, 0, 0); -+ m_layout->addItem(m_fromLabel, 0, 1); -+ m_layout->addItem(m_toNameLabel, 1, 0); -+ m_layout->addItem(m_toLabel, 1, 1); -+ m_layout->addItem(m_eta, 2, 1); -+ m_layout->addItem(m_details, 3, 0, Qt::AlignVCenter|Qt::AlignRight); -+ m_layout->addItem(m_meter, 3, 1, Qt::AlignCenter); -+ -+ setMinimumWidth(350); -+ -+ if (m_job.data()) { -+ m_details->setToolTip(i18n("More")); -+ m_details->setSvg("widgets/action-overlays", "add-normal"); -+ -+ connect(m_job.data(), SIGNAL(stateChanged(Job*)), this, SLOT(updateJobState())); -+ connect(m_job.data(), SIGNAL(destroyed(Job*)), this, SLOT(destroyExtenderItem())); -+ connect(m_details, SIGNAL(clicked()), this, SLOT(detailsClicked())); -+ -+ //the suspend action -+ QAction *suspendAction = new QAction(m_extenderItem); -+ suspendAction->setIcon(KIcon("media-playback-pause")); -+ suspendAction->setEnabled(true); -+ suspendAction->setVisible(false); -+ suspendAction->setToolTip(i18n("Pause job")); -+ m_extenderItem->addAction("suspend", suspendAction); -+ connect(suspendAction, SIGNAL(triggered()), m_job.data(), SLOT(suspend())); -+ -+ //the resume action -+ QAction *resumeAction = new QAction(m_extenderItem); -+ resumeAction->setIcon(KIcon("media-playback-start")); -+ resumeAction->setEnabled(true); -+ resumeAction->setVisible(false); -+ resumeAction->setToolTip(i18n("Resume job")); -+ m_extenderItem->addAction("resume", resumeAction); -+ connect(resumeAction, SIGNAL(triggered()), m_job.data(), SLOT(resume())); -+ -+ //the friendly stop action -+ QAction *stopAction = new QAction(m_extenderItem); -+ stopAction->setIcon(KIcon("media-playback-stop")); -+ stopAction->setEnabled(true); -+ stopAction->setVisible(true); -+ stopAction->setToolTip(i18n("Cancel job")); -+ m_extenderItem->addAction("stop", stopAction); -+ connect(stopAction, SIGNAL(triggered()), m_job.data(), SLOT(stop())); -+ -+ updateJob(); -+ updateJobState(); // make sure to set the title -+ } else { -+ m_extenderItem->showCloseButton(); -+ -+ labelName0 = m_extenderItem->config().readEntry("labelName0", ""); -+ label0= m_extenderItem->config().readEntry("label0", ""); -+ labelName1 = m_extenderItem->config().readEntry("labelName1", ""); -+ label1 = m_extenderItem->config().readEntry("label1", ""); -+ -+ updateLabels(); -+ } -+} -+ -+JobWidget::~JobWidget() -+{ -+} -+ -+void JobWidget::destroyExtenderItem() -+{ -+ m_extenderItem->destroy(); -+ m_extenderItemDestroyed = true; -+} -+ -+void JobWidget::scheduleUpdateJob() -+{ -+ if (m_extenderItemDestroyed) { -+ return; -+ } -+ -+ if (!m_updateTimerId) { -+ m_updateTimerId = startTimer(UPDATE_INTERVAL); -+ } -+} -+ -+void JobWidget::updateJobState() -+{ -+ if (m_extenderItemDestroyed && m_job.data()) { -+ return; -+ } -+ -+ //show the current status in the title. -+ if (!m_job.data()->error().isEmpty()) { -+ m_extenderItem->setTitle(m_job.data()->error()); -+ } else if (m_job.data()->state() == Job::Running) { -+ m_extenderItem->setTitle(m_job.data()->message()); -+ if (m_job.data()->eta()) { -+ m_eta->setText(i18n("%1 (%2 remaining)", m_job.data()->speed(), -+ KGlobal::locale()->prettyFormatDuration(m_job.data()->eta()))); -+ } else { -+ m_eta->setText(QString()); -+ } -+ } else if (m_job.data()->state() == Job::Suspended) { -+ m_extenderItem->setTitle( -+ i18nc("%1 is the name of the job, can be things like Copying, deleting, moving", -+ "%1 [Paused]", m_job.data()->message())); -+ m_eta->setText(i18n("Paused")); -+ } else { -+ m_extenderItem->setTitle( -+ i18nc("%1 is the name of the job, can be things like Copying, deleting, moving", -+ "%1 [Finished]", m_job.data()->message())); -+ m_extenderItem->showCloseButton(); -+ } -+} -+ -+void JobWidget::updateJob() -+{ -+ if (m_extenderItemDestroyed || !m_job.data()) { -+ return; -+ } -+ -+ m_meter->setValue(m_job.data()->percentage()); -+ -+ //Update the ETA and job speed (only if running) -+ if (m_job.data()->state() == Job::Running) { -+ if (m_job.data()->eta()) { -+ m_eta->setText(i18n("%1 (%2 remaining)", m_job.data()->speed(), -+ KGlobal::locale()->prettyFormatDuration(m_job.data()->eta()))); -+ } else { -+ m_eta->setText(QString()); -+ } -+ } -+ -+ if (m_job.data()->labels().count() > 0) { -+ labelName0 = m_job.data()->labels().value(0).first; -+ label0 = m_job.data()->labels().value(0).second; -+ } -+ if (m_job.data()->labels().count() > 1) { -+ labelName1 = m_job.data()->labels().value(1).first; -+ label1 = m_job.data()->labels().value(1).second; -+ } -+ -+ //TODO: can we write this at some later point? -+ KConfigGroup cg = m_extenderItem->config(); -+ cg.writeEntry("labelName0", labelName0); -+ cg.writeEntry("label0", label0); -+ cg.writeEntry("labelName1", labelName1); -+ cg.writeEntry("label1", label1); -+ -+ updateLabels(); -+ -+ //set the correct actions to visible. -+ if (m_extenderItem->action("suspend")) { -+ m_extenderItem->action("suspend")->setVisible(m_job.data()->isSuspendable() && -+ m_job.data()->state() == Job::Running); -+ } -+ -+ if (m_extenderItem->action("resume")) { -+ m_extenderItem->action("resume")->setVisible(m_job.data()->isSuspendable() && -+ m_job.data()->state() == Job::Suspended); -+ } -+ -+ if (m_extenderItem->action("stop")) { -+ m_extenderItem->action("stop")->setVisible(m_job.data()->isKillable() && -+ m_job.data()->state() != Job::Stopped); -+ } -+ -+ QMap processed = m_job.data()->processedAmounts(); -+ QMap totals = m_job.data()->totalAmounts(); -+ -+ qlonglong dirs = totals.value("dirs"); -+ if (dirs > 1) { -+ m_dirCountLabel->setText(i18np("%2 / 1 folder", "%2 / %1 folders", dirs, processed["dirs"])); -+ m_dirCountLabel->setMaximumHeight(INT_MAX); -+ } else { -+ m_dirCountLabel->setMaximumHeight(0); -+ } -+ -+ qlonglong files = totals.value("files"); -+ if (files > 1) { -+ m_fileCountLabel->setText(i18np("%2 / 1 file", "%2 / %1 files", files, processed["files"])); -+ m_fileCountLabel->setMaximumHeight(INT_MAX); -+ } else { -+ m_fileCountLabel->setMaximumHeight(0); -+ } -+ -+ QList sample; -+ sample << m_job.data()->numericSpeed()/1000; -+ m_plotter->addSample(sample); -+ -+ qlonglong total = totals["bytes"]; -+ if (total > 0) { -+ QString processedString = KGlobal::locale()->formatByteSize(processed["bytes"]); -+ QString totalsString = KGlobal::locale()->formatByteSize(total); -+ m_totalBytesLabel->setText(QString("%1 / %2").arg(processedString, totalsString)); -+ } else { -+ m_details->hide(); -+ m_totalBytesLabel->hide(); -+ } -+ -+ if (m_totalBytesLabel->text().isEmpty() && -+ m_dirCountLabel->text().isEmpty() && -+ m_fileCountLabel->text().isEmpty()) { -+ m_details->hide(); -+ } else { -+ m_details->show(); -+ } -+ -+ m_extenderItem->setIcon(m_job.data()->applicationIconName()); -+} -+ -+void JobWidget::showEvent(QShowEvent *) -+{ -+ if (!m_job.data()) { -+ return; -+ } -+ -+ Plasma::PopupApplet *applet = qobject_cast(m_extenderItem->extender()->applet()); -+ if (applet && applet->isPopupShowing()) { -+ updateJob(); -+ disconnect(m_job.data(), SIGNAL(changed(Job*)), this, SLOT(scheduleUpdateJob())); -+ connect(m_job.data(), SIGNAL(changed(Job*)), this, SLOT(scheduleUpdateJob())); -+ return; -+ } -+} -+ -+void JobWidget::hideEvent(QHideEvent *) -+{ -+ if (!m_job.data()) { -+ return; -+ } -+ -+ disconnect(m_job.data(), SIGNAL(changed(Job*)), this, SLOT(scheduleUpdateJob())); -+} -+ -+void JobWidget::poppedUp(bool shown) -+{ -+ if (!m_job.data()) { -+ return; -+ } -+ -+ disconnect(m_job.data(), SIGNAL(changed(Job*)), this, SLOT(scheduleUpdateJob())); -+ -+ if (shown && isVisible()) { -+ updateJob(); -+ connect(m_job.data(), SIGNAL(changed(Job*)), this, SLOT(scheduleUpdateJob())); -+ return; -+ } -+} -+ -+Job *JobWidget::job() const -+{ -+ return m_job.data(); -+} -+ -+void JobWidget::resizeEvent(QGraphicsSceneResizeEvent *event) -+{ -+ Q_UNUSED(event) -+ updateLabels(); -+} -+ -+void JobWidget::timerEvent(QTimerEvent *event) -+{ -+ if (event->timerId() == m_updateTimerId) { -+ killTimer(m_updateTimerId); -+ m_updateTimerId = 0; -+ updateJob(); -+ } -+} -+ -+void JobWidget::updateLabels() -+{ -+ QFontMetricsF fm = m_fromLabel->nativeWidget()->fontMetrics(); -+ if (!labelName0.isEmpty()) { -+ m_fromNameLabel->setText(QString("%1: ").arg(labelName0)); -+ } -+ if (label0.startsWith(QLatin1String("file://"))) { -+ label0 = KUrl(label0).toLocalFile(); -+ } -+ -+ const QString shortLabel0(fm.elidedText(label0, Qt::ElideMiddle, m_fromLabel->size().width())); -+ m_fromLabel->setText(shortLabel0); -+ -+ -+ Plasma::ToolTipContent data; -+ -+ if (label0.length() > shortLabel0.length()) { -+ data.setSubText(label0); -+ Plasma::ToolTipManager::self()->setContent(m_fromLabel, data); -+ } -+ -+ if (!labelName1.isEmpty()) { -+ m_toNameLabel->setText(QString("%1: ").arg(labelName1)); -+ } -+ if (label1.startsWith(QLatin1String("file://"))) { -+ label1 = KUrl(label1).toLocalFile(); -+ } -+ -+ const QString shortLabel1(fm.elidedText(label1, Qt::ElideMiddle, m_toLabel->size().width())); -+ m_toLabel->setText(shortLabel1); -+ -+ if (label1.length() > shortLabel1.length()) { -+ data.setSubText(label1); -+ Plasma::ToolTipManager::self()->setContent(m_toLabel, data); -+ } -+} -+ -+void JobWidget::detailsClicked() -+{ -+ if (!m_totalBytesLabel->isVisible()) { -+ m_details->setToolTip(i18n("Less")); -+ m_details->setSvg("widgets/action-overlays", "remove-normal"); -+ m_totalBytesLabel->setVisible(true); -+ m_dirCountLabel->setVisible(true); -+ m_fileCountLabel->setVisible(true); -+ m_plotter->setVisible(true); -+ m_layout->addItem(m_totalBytesLabel, 4, 1); -+ m_layout->addItem(m_fileCountLabel, 5, 1); -+ m_layout->addItem(m_dirCountLabel, 6, 1); -+ m_layout->addItem(m_plotter, 7, 1); -+ m_extenderItem->setCollapsed(m_extenderItem->isCollapsed()); -+ } else { -+ m_details->setToolTip(i18n("More")); -+ m_details->setSvg("widgets/action-overlays", "add-normal"); -+ m_totalBytesLabel->setVisible(false); -+ m_dirCountLabel->setVisible(false); -+ m_fileCountLabel->setVisible(false); -+ m_plotter->setVisible(false); -+ for (int i = 0; i < 4; i++) { -+ m_layout->removeAt(m_layout->count() - 1); -+ } -+ m_layout->updateGeometry(); -+ m_extenderItem->setCollapsed(m_extenderItem->isCollapsed()); -+ } -+} -+ -+#include "jobwidget.moc" -+ -diff --git a/plasma/generic/applets/notifications/ui/jobwidget.h b/plasma/generic/applets/notifications/ui/jobwidget.h -new file mode 100644 -index 0000000..b949bac ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/jobwidget.h -@@ -0,0 +1,102 @@ -+/*************************************************************************** -+ * Copyright 2008 by Rob Scheepmaker -+#include -+ -+#include -+#include -+#include -+#include -+ -+namespace Plasma -+{ -+ class ExtenderItem; -+ class PushButton; -+ class Label; -+ class Meter; -+ class IconWidget; -+ class SignalPlotter; -+} // namespace Plasma -+ -+class Job; -+ -+ -+class JobWidget : public QGraphicsWidget -+{ -+ Q_OBJECT -+ -+ public: -+ explicit JobWidget(Job *job, Plasma::ExtenderItem *parent); -+ ~JobWidget(); -+ -+ void poppedUp(bool shown); -+ -+ Job *job() const; -+ -+ protected: -+ void resizeEvent(QGraphicsSceneResizeEvent *event); -+ void timerEvent(QTimerEvent *event); -+ void showEvent(QShowEvent *event); -+ void hideEvent(QHideEvent *event); -+ -+ private Q_SLOTS: -+ void detailsClicked(); -+ void destroyExtenderItem(); -+ void scheduleUpdateJob(); -+ void updateJobState(); -+ -+ private: -+ void updateLabels(); -+ void updateJob(); -+ -+ Plasma::ExtenderItem *m_extenderItem; -+ QWeakPointerm_job; -+ -+ Plasma::Meter *m_meter; -+ Plasma::Label *m_fromNameLabel; -+ Plasma::Label *m_fromLabel; -+ Plasma::Label *m_toNameLabel; -+ Plasma::Label *m_toLabel; -+ Plasma::Label *m_totalBytesLabel; -+ Plasma::Label *m_dirCountLabel; -+ Plasma::Label *m_fileCountLabel; -+ Plasma::Label *m_eta; -+ Plasma::IconWidget *m_details; -+ Plasma::SignalPlotter *m_plotter; -+ -+ QGraphicsGridLayout *m_layout; -+ -+ QString labelName0; -+ QString labelName1; -+ QString label0; -+ QString label1; -+ -+ int m_updateTimerId; -+ -+ bool m_extenderItemDestroyed; -+}; -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/notificationgroup.cpp b/plasma/generic/applets/notifications/ui/notificationgroup.cpp -new file mode 100644 -index 0000000..f27e2c3 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationgroup.cpp -@@ -0,0 +1,239 @@ -+/*************************************************************************** -+ * notificationgroup.cpp * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "notificationgroup.h" -+#include "../core/notification.h" -+#include "notificationwidget.h" -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+ -+NotificationGroup::NotificationGroup(Plasma::Extender *parent, uint groupId) -+ : Plasma::ExtenderGroup(parent, groupId) -+{ -+ setTransient(true); -+ config().writeEntry("type", "notification"); -+ setName("notifications"); -+ setTitle(i18n("Notifications")); -+ setIcon("dialog-information"); -+ showCloseButton(); -+ -+ -+ m_notificationBar = new Plasma::TabBar(this); -+ m_notificationBar->nativeWidget()->setMaximumWidth(400); -+ m_notificationBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); -+ m_notificationBar->addTab(KIcon("dialog-information"), i18nc("Show all notifications", "All")); -+ connect(m_notificationBar, SIGNAL(currentChanged(int)), this, SLOT(tabSwitched(int))); -+ -+ -+ QGraphicsWidget *widget = new QGraphicsWidget(this); -+ QGraphicsLinearLayout *tabsLayout = new QGraphicsLinearLayout(Qt::Horizontal, widget); -+ widget->setContentsMargins(0, 4, 0, 0); -+ tabsLayout->setContentsMargins(0, 0, 0, 0); -+ tabsLayout->addStretch(); -+ tabsLayout->addItem(m_notificationBar); -+ tabsLayout->addStretch(); -+ -+ setWidget(widget); -+ setCollapsed(true); -+ setAutoCollapse(false); -+} -+ -+NotificationGroup::~NotificationGroup() -+{ -+ m_extenderItemsForNotification.clear(); -+ m_notificationForExtenderItems.clear(); -+ qDeleteAll(m_notifications); -+} -+ -+ -+void NotificationGroup::addNotification(Notification *notification) -+{ -+ connect(notification, SIGNAL(notificationDestroyed(Notification*)), this, SLOT(removeNotification(Notification*))); -+ -+ NotificationWidget *notificationWidget = new NotificationWidget(notification, this); -+ notificationWidget->setTitleBarVisible(false); -+ Plasma::ExtenderItem *extenderItem = new ExtenderItem(extender()); -+ extenderItem->setGroup(this, QPointF(0,0)); -+ extenderItem->setTransient(true); -+ extenderItem->config().writeEntry("type", "notification"); -+ extenderItem->setWidget(notificationWidget); -+ extenderItem->setIcon(QIcon()); -+ extenderItem->showCloseButton(); -+ connect(extenderItem, SIGNAL(destroyed(Plasma::ExtenderItem*)), this, SLOT(extenderItemDestroyed(Plasma::ExtenderItem*))); -+ connect(notificationWidget, SIGNAL(destroyed()), extenderItem, SLOT(deleteLater())); -+ -+ if (!notification->summary().isEmpty()) { -+ extenderItem->setTitle(notification->summary()); -+ } else { -+ extenderItem->setTitle(i18n("Notification from %1", notification->applicationName())); -+ } -+ -+ m_extenderItemsForNotification[notification] = extenderItem; -+ m_notificationForExtenderItems[extenderItem] = notification; -+ m_notifications.append(notification); -+ m_notificationsForApp[notification->applicationName()].insert(notification); -+ m_appForNotification[notification] = notification->applicationName(); -+ -+ if (!m_currentFilter.isNull() && m_currentFilter != notification->applicationName()) { -+ extenderItem->setMaximumHeight(0); -+ extenderItem->setVisible(false); -+ } -+ -+ //adjust tabbar -+ bool found = false; -+ for (int i = 0; i < m_notificationBar->count(); ++i) { -+ if (m_notificationBar->tabText(i) == notification->applicationName()) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ m_notificationBar->addTab(notification->applicationIcon(), notification->applicationName()); -+ if (m_notificationBar->count() > 2) { -+ setCollapsed(false); -+ setAutoCollapse(true); -+ } -+ } -+ -+ if (items().count() == 1) { -+ //ensure the notifications group is the last item -+ Plasma::ExtenderGroup *jobGroup = extender()->group("jobGroup"); -+ if (jobGroup && jobGroup->isVisible()) { -+ if (extender()->appearance() == Plasma::Extender::TopDownStacked) { -+ setExtender(extender(), QPointF(0,0)); -+ } else { -+ setExtender(extender(), jobGroup->geometry().bottomLeft()); -+ } -+ } -+ } -+ -+ notificationWidget->layout()->activate(); -+} -+ -+void NotificationGroup::extenderItemDestroyed(Plasma::ExtenderItem *object) -+{ -+ if (m_extenderItemsForNotification.isEmpty()) { -+ // either we aren't tracking this notification or else we're being deleted -+ return; -+ } -+ -+ Notification *n = m_notificationForExtenderItems.value(object); -+ -+ if (n) { -+ m_notificationForExtenderItems.remove(object); -+ removeNotification(n); -+ n->deleteLater(); -+ } -+} -+ -+void NotificationGroup::removeNotification(Notification *notification) -+{ -+ if (m_extenderItemsForNotification.isEmpty()) { -+ // either we aren't tracking this notification or else we're being deleted -+ return; -+ } -+ -+ Plasma::ExtenderItem *item = m_extenderItemsForNotification.value(notification); -+ if (item) { -+ m_notificationForExtenderItems.remove(item); -+ } -+ -+ m_extenderItemsForNotification.remove(notification); -+ m_notifications.removeAll(notification); -+ QString applicationName = m_appForNotification.value(notification); -+ -+ if (applicationName.isEmpty()) { -+ return; -+ } -+ -+ m_appForNotification.remove(notification); -+ -+ if (m_notificationsForApp.contains(applicationName)) { -+ m_notificationsForApp[applicationName].remove(notification); -+ if (m_notificationsForApp[applicationName].isEmpty()) { -+ m_notificationsForApp.remove(applicationName); -+ } -+ } -+ -+ //clear tabbar -+ for (int i = 1; i < m_notificationBar->count(); ++i) { -+ if (!m_notificationsForApp.contains(m_notificationBar->tabText(i))) { -+ if (i == m_notificationBar->currentIndex()) { -+ m_notificationBar->setCurrentIndex(0); -+ } -+ m_notificationBar->removeTab(i); -+ //2 tabs means just "all" and a single application, no need to display it -+ if (m_notificationBar->count() <= 2) { -+ setCollapsed(true); -+ setAutoCollapse(false); -+ } -+ } -+ } -+ -+ if (m_notifications.count() == 0) { -+ emit scrollerEmpty(); -+ return; -+ } -+} -+ -+ -+void NotificationGroup::filterNotificationsByOwner(const QString &owner) -+{ -+ foreach (Notification *notification, m_notifications) { -+ Plasma::ExtenderItem *item = m_extenderItemsForNotification.value(notification); -+ -+ if (!item || item->group() != this) { -+ continue; -+ } -+ -+ if (owner.isNull() || notification->applicationName() == owner) { -+ item->setMaximumHeight(QWIDGETSIZE_MAX); -+ item->setVisible(true); -+ } else { -+ item->setMaximumHeight(0); -+ item->setVisible(false); -+ } -+ } -+ -+ m_currentFilter = owner; -+} -+ -+void NotificationGroup::tabSwitched(int index) -+{ -+ if (index > 0) { -+ filterNotificationsByOwner(m_notificationBar->tabText(index)); -+ } else { -+ filterNotificationsByOwner(QString()); -+ } -+} -+ -+ -+#include "notificationgroup.moc" -+ -diff --git a/plasma/generic/applets/notifications/ui/notificationgroup.h b/plasma/generic/applets/notifications/ui/notificationgroup.h -new file mode 100644 -index 0000000..ffa2112 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationgroup.h -@@ -0,0 +1,85 @@ -+/*************************************************************************** -+ * notificationgroup.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONGROUP_H -+#define NOTIFICATIONGROUP_H -+ -+ -+#include -+#include -+ -+ -+#include -+ -+class QGraphicsLinearLayout; -+ -+namespace Plasma -+{ -+ class ExtenderItem; -+ class TabBar; -+ class Extender; -+} -+ -+class NotificationWidget; -+class Notification; -+ -+class NotificationGroup : public Plasma::ExtenderGroup -+{ -+ Q_OBJECT -+ -+public: -+ NotificationGroup(Plasma::Extender *parent, uint groupId = 0); -+ ~NotificationGroup(); -+ -+ void addNotification(Notification *notification); -+ -+ void filterNotificationsByOwner(const QString &owner); -+ -+ -+public Q_SLOTS: -+ void removeNotification(Notification *notification); -+ -+protected Q_SLOTS: -+ void tabSwitched(int index); -+ void extenderItemDestroyed(Plasma::ExtenderItem *object); -+ -+Q_SIGNALS: -+ void scrollerEmpty(); -+ -+private: -+ Plasma::TabBar *m_notificationBar; -+ -+ //housekeeping data structures -+ QListm_notifications; -+ -+ //Those two are kept on both ways since we are not sure the thing -+ //contained in the hash is still valid so we couldn't obtain the -+ //info to remove the proper key, unless both ways are stored -+ QHash > m_notificationsForApp; -+ QHash m_appForNotification; -+ -+ QHashm_extenderItemsForNotification; -+ QHashm_notificationForExtenderItems; -+ -+ QString m_currentFilter; -+}; -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/notifications.cpp b/plasma/generic/applets/notifications/ui/notifications.cpp -new file mode 100644 -index 0000000..eea1d72 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notifications.cpp -@@ -0,0 +1,434 @@ -+/*************************************************************************** -+ * applet.cpp * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2008 Sebastian Sauer * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "notifications.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "config-notifications.h" -+#ifdef HAVE_LIBXSS // Idle detection. -+#include -+#include -+#include -+#include -+#endif // HAVE_LIBXSS -+ -+#include "../core/notificationsmanager.h" -+#include "../core/notification.h" -+#include "../core/completedjobnotification.h" -+#include "busywidget.h" -+#include "jobwidget.h" -+#include "jobtotalswidget.h" -+#include "notificationgroup.h" -+#include "notificationstack.h" -+#include "stackdialog.h" -+ -+ -+K_EXPORT_PLASMA_APPLET(notifications, Notifications) -+ -+ -+Notifications::Notifications(QObject *parent, const QVariantList &arguments) -+ : Plasma::PopupApplet(parent, arguments), -+ m_jobSummaryWidget(0), -+ m_autoHidePopup(true), -+ m_notificationStack(0), -+ m_notificationStackDialog(0), -+ m_standaloneJobSummaryWidget(0), -+ m_standaloneJobSummaryDialog(0), -+ m_busyWidget(0) -+{ -+ m_manager = new Manager(this); -+ -+ setPopupIcon(QIcon()); -+ setPassivePopup(true); -+ setAspectRatioMode(Plasma::IgnoreAspectRatio); -+ setBackgroundHints(NoBackground); -+ setHasConfigurationInterface(true); -+ setMinimumSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall); -+} -+ -+Notifications::~Notifications() -+{ -+ // stop listening to the manager -+ disconnect(m_manager, 0, this, 0); -+ if (m_notificationStackDialog) { -+ disconnect(m_notificationStackDialog, 0, this, 0); -+ } -+ -+ foreach (Notification *notification, m_manager->notifications()) { -+ // we don't want a destroyed managed after the destruction of manager -+ disconnect(notification, 0, this, 0); -+ } -+ -+ //has to be deleted before the manager because it will access it -+ delete m_busyWidget; -+ delete m_notificationStackDialog; -+ delete m_standaloneJobSummaryDialog; -+} -+ -+void Notifications::init() -+{ -+ extender()->setEmptyExtenderMessage(i18n("No notifications and no jobs")); -+ -+ m_busyWidget = new BusyWidget(this, m_manager); -+ connect(m_busyWidget, SIGNAL(clicked()), this, SLOT(togglePopup())); -+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(this); -+ setContentsMargins(0, 0, 0, 0); -+ lay->setContentsMargins(0, 0, 0, 0); -+ lay->addItem(m_busyWidget); -+ -+ configChanged(); -+ setStatus(Plasma::PassiveStatus); -+} -+ -+void Notifications::configChanged() -+{ -+ KConfigGroup cg = config(); -+ -+ m_autoHidePopup = cg.readEntry("AutoHidePopup", true); -+ if (m_notificationStackDialog) { -+ m_notificationStackDialog->setAutoHide(m_autoHidePopup); -+ } -+ -+ if (cg.readEntry("ShowJobs", true)) { -+ createJobGroups(); -+ -+ m_manager->registerJobProtocol(); -+ connect(m_manager, SIGNAL(jobAdded(Job*)), -+ this, SLOT(addJob(Job*)), Qt::UniqueConnection); -+ connect(m_manager, SIGNAL(jobRemoved(Job*)), -+ this, SLOT(finishJob(Job*)), Qt::UniqueConnection); -+ } else { -+ delete extender()->group("jobGroup"); -+ m_manager->unregisterJobProtocol(); -+ disconnect(m_manager, SIGNAL(jobAdded(Job*)), -+ this, SLOT(addJob(Job*))); -+ disconnect(m_manager, SIGNAL(jobRemoved(Job*)), -+ this, SLOT(finishJob(Job*))); -+ } -+ -+ if (cg.readEntry("ShowNotifications", true)) { -+ m_manager->registerNotificationProtocol(); -+ connect(m_manager, SIGNAL(notificationAdded(Notification*)), -+ this, SLOT(addNotification(Notification*)), Qt::UniqueConnection); -+ } else { -+ m_manager->unregisterNotificationProtocol(); -+ disconnect(m_manager, SIGNAL(notificationAdded(Notification*)), -+ this, SLOT(addNotification(Notification*))); -+ } -+} -+ -+void Notifications::syncNotificationBarNeeded() -+{ -+ if (!m_manager) { -+ return; -+ } -+ -+ if (m_manager->notifications().isEmpty()) { -+ if (extender()->item("notifications")) { -+ //don't let him in the config file -+ extender()->item("notifications")->destroy(); -+ } -+ } else if (!extender()->item("notifications")) { -+ m_notificationGroup = new NotificationGroup(extender()); -+ } -+} -+ -+Manager *Notifications::manager() const -+{ -+ return m_manager; -+} -+ -+void Notifications::createConfigurationInterface(KConfigDialog *parent) -+{ -+ if (!m_notificationInterface) { -+ KConfigGroup cg = config(); -+ m_notificationInterface = new QWidget(); -+ -+ m_notificationUi.setupUi(m_notificationInterface.data()); -+ -+ m_notificationUi.showJobs->setChecked(cg.readEntry("ShowJobs", true)); -+ m_notificationUi.showNotifications->setChecked(cg.readEntry("ShowNotifications", true)); -+ -+ m_notificationUi.autoHide->setChecked(config().readEntry("AutoHidePopup", true)); -+ -+ connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted())); -+ connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); -+ -+ parent->addPage(m_notificationInterface.data(), i18n("Information"), -+ "preferences-desktop-notification", -+ i18n("Choose which information to show")); -+ -+ connect(m_notificationUi.showNotifications, SIGNAL(stateChanged(int)), parent, SLOT(settingsModified())); -+ connect(m_notificationUi.showJobs, SIGNAL(stateChanged(int)), parent, SLOT(settingsModified())); -+ connect(m_notificationUi.autoHide, SIGNAL(stateChanged(int)), parent, SLOT(settingsModified())); -+ } -+} -+ -+void Notifications::configAccepted() -+{ -+ //TODO put in a single page -+ //cg.writeEntry("AutoHidePopup", m_autoHideUi.autoHide->isChecked()); -+ -+ KConfigGroup cg = config(); -+ cg.writeEntry("ShowJobs", m_notificationUi.showJobs->isChecked()); -+ cg.writeEntry("ShowNotifications", m_notificationUi.showNotifications->isChecked()); -+ cg.writeEntry("AutoHidePopup", m_notificationUi.autoHide->isChecked()); -+ -+ emit configNeedsSaving(); -+} -+ -+void Notifications::addNotification(Notification *notification) -+{ -+ syncNotificationBarNeeded(); -+ -+ //At this point we are sure the pointer is valid -+ m_notificationGroup.data()->addNotification(notification); -+ -+ -+ if (isPopupShowing()) { -+ return; -+ } -+ -+ if (!m_notificationStack) { -+ m_notificationStack = new NotificationStack(this); -+ if (containment() && containment()->corona()) { -+ containment()->corona()->addOffscreenWidget(m_notificationStack); -+ } -+ m_notificationStackDialog = new StackDialog; -+ m_notificationStackDialog->setNotificationStack(m_notificationStack); -+ m_notificationStackDialog->setApplet(this); -+ connect(m_notificationStack, SIGNAL(stackEmpty()), m_notificationStackDialog, SLOT(hide())); -+ connect(m_notificationStack, SIGNAL(showRequested()), m_notificationStackDialog, SLOT(perhapsShow())); -+ m_notificationStackDialog->setAutoHide(m_autoHidePopup); -+ -+ if (m_standaloneJobSummaryDialog) { -+ m_notificationStackDialog->setWindowToTile(m_standaloneJobSummaryDialog); -+ } -+ } -+ -+ -+ m_notificationStack->addNotification(notification); -+ m_notificationStackDialog->syncToGraphicsWidget(); -+ -+ if (containment() && containment()->corona()) { -+ if (!m_notificationStackDialog->isVisible()) { -+ m_notificationStack->setCurrentNotification(notification); -+ } -+ -+ KWindowSystem::setOnAllDesktops(m_notificationStackDialog->winId(), true); -+ m_notificationStackDialog->perhapsShow(); -+ } -+ -+ Plasma::Animation *pulse = Plasma::Animator::create(Plasma::Animator::PulseAnimation, m_busyWidget); -+ pulse->setTargetWidget(m_busyWidget); -+ pulse->start(QAbstractAnimation::DeleteWhenStopped); -+} -+ -+void Notifications::addJob(Job *job) -+{ -+ Plasma::ExtenderGroup *group = extender()->group("jobGroup"); -+ -+ Plasma::ExtenderItem *extenderItem = new Plasma::ExtenderItem(extender()); -+ extenderItem->setTransient(true); -+ extenderItem->config().writeEntry("type", "job"); -+ extenderItem->setWidget(new JobWidget(job, extenderItem)); -+ -+ extenderItem->setGroup(group); -+ -+ if (group) { -+ group->setCollapsed(group->items().count() < 2); -+ } -+ -+ if (isPopupShowing()) { -+ return; -+ } -+ -+ //show the tiny standalone overview -+ if (!m_standaloneJobSummaryWidget) { -+ m_standaloneJobSummaryDialog = new Plasma::Dialog(); -+ KWindowSystem::setType(m_standaloneJobSummaryDialog->winId(), NET::Dock); -+ if (m_notificationStackDialog) { -+ m_notificationStackDialog->setWindowToTile(m_standaloneJobSummaryDialog); -+ } -+ -+ m_standaloneJobSummaryWidget = new JobTotalsWidget(m_manager->jobTotals(), this); -+ if (containment() && containment()->corona()) { -+ containment()->corona()->addOffscreenWidget(m_standaloneJobSummaryWidget); -+ } -+ m_standaloneJobSummaryDialog->setGraphicsWidget(m_standaloneJobSummaryWidget); -+ //FIXME:sizing hack and layout issues.. -+ m_standaloneJobSummaryWidget->resize(m_standaloneJobSummaryWidget->size().width(), 32); -+ m_standaloneJobSummaryWidget->setMaximumHeight(32); -+ m_standaloneJobSummaryWidget->setMinimumHeight(32); -+ m_standaloneJobSummaryWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); -+ } -+ -+ m_standaloneJobSummaryDialog->syncToGraphicsWidget(); -+ KWindowSystem::setState(m_standaloneJobSummaryDialog->winId(), NET::KeepBelow); -+ -+ if (containment() && containment()->corona()) { -+ m_standaloneJobSummaryDialog->move(containment()->corona()->popupPosition(this, m_standaloneJobSummaryDialog->size())); -+ m_standaloneJobSummaryDialog->show(); -+ Plasma::WindowEffects::slideWindow(m_standaloneJobSummaryDialog, location()); -+ -+ KWindowSystem::setOnAllDesktops(m_standaloneJobSummaryDialog->winId(), true); -+ KWindowSystem::clearState(m_standaloneJobSummaryDialog->winId(), NET::KeepAbove|NET::StaysOnTop); -+ -+ KWindowSystem::setState(m_standaloneJobSummaryDialog->winId(), NET::SkipTaskbar|NET::SkipPager); -+ KWindowSystem::raiseWindow(m_standaloneJobSummaryDialog->winId()); -+ KWindowSystem::setOnAllDesktops(m_standaloneJobSummaryDialog->winId(), true); -+ } -+} -+ -+void Notifications::initExtenderItem(Plasma::ExtenderItem *extenderItem) -+{ -+ if (extenderItem->name() == "jobGroup") { -+ m_jobSummaryWidget = new JobTotalsWidget(m_manager->jobTotals(), extenderItem); -+ extenderItem->setWidget(m_jobSummaryWidget); -+ Plasma::ExtenderGroup *group = qobject_cast(extenderItem); -+ if (group) { -+ extenderItem->setCollapsed(!group->isGroupCollapsed()); -+ } -+ return; -+ } -+ -+ if (extenderItem->config().readEntry("type", QString()) == "job") { -+ extenderItem->setWidget(new JobWidget(0, extenderItem)); -+ } else { -+ //unknown type, this should never happen -+ extenderItem->destroy(); -+ } -+ -+} -+ -+void Notifications::popupEvent(bool show) -+{ -+ if (m_busyWidget) { -+ m_busyWidget->suppressToolTips(show); -+ } -+ -+ //decide about showing the tiny progressbar or not -+ if (m_standaloneJobSummaryDialog) { -+ if (show || !m_manager->jobs().isEmpty()) { -+ if (!show) { -+ KWindowSystem::raiseWindow(m_standaloneJobSummaryDialog->winId()); -+ KWindowSystem::setState(m_standaloneJobSummaryDialog->winId(), NET::SkipTaskbar|NET::SkipPager); -+ KWindowSystem::setState(m_standaloneJobSummaryDialog->winId(), NET::KeepBelow); -+ } else { -+ m_standaloneJobSummaryDialog->hide(); -+ } -+ } -+ } -+ -+ if (m_notificationStackDialog && show) { -+ m_notificationStackDialog->hide(); -+ } -+ -+ Plasma::ExtenderGroup * jobGroup = extender()->group("jobGroup"); -+ if (!jobGroup) { -+ return; -+ } -+ -+ foreach (Plasma::ExtenderItem *item, jobGroup->items()) { -+ JobWidget *job = dynamic_cast(item->widget()); -+ if (job) { -+ job->poppedUp(show); -+ } -+ } -+} -+ -+void Notifications::finishJob(Job *job) -+{ -+ //finished all jobs? hide the mini progressbar -+ if (m_standaloneJobSummaryDialog && m_manager->jobs().isEmpty()) { -+ m_standaloneJobSummaryDialog->hide(); -+ } -+ -+ //create a fake notification -+ CompletedJobNotification *notification = new CompletedJobNotification(this); -+ notification->setJob(job); -+ m_manager->addNotification(notification); -+ -+ Plasma::ExtenderGroup *group = extender()->group("jobGroup"); -+ if (group) { -+ // < 3 because the second still hasn't been removed from the extendergroup -+ group->setCollapsed(!group->isGroupCollapsed() && group->items().count() < 3); -+ } -+} -+ -+void Notifications::open(const QString &url) -+{ -+ //kDebug() << "open " << url; -+ QProcess::startDetached("kde-open", QStringList() << url); -+} -+ -+void Notifications::createJobGroups() -+{ -+ if (!extender()->hasItem("jobGroup")) { -+ Plasma::ExtenderGroup *extenderGroup = new Plasma::ExtenderGroup(extender()); -+ extenderGroup->setName("jobGroup"); -+ initExtenderItem(extenderGroup); -+ extenderGroup->setAutoHide(true); -+ } else if (extender()->group("jobGroup")) { -+ extender()->group("jobGroup")->setAutoHide(true); -+ } -+} -+ -+ -+#include "notifications.moc" -diff --git a/plasma/generic/applets/notifications/ui/notifications.h b/plasma/generic/applets/notifications/ui/notifications.h -new file mode 100644 -index 0000000..827b28e ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notifications.h -@@ -0,0 +1,101 @@ -+/*************************************************************************** -+ * applet.h * -+ * * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONS_H -+#define NOTIFICATIONS_H -+ -+#include -+ -+#include "ui_notificationsconfig.h" -+ -+ -+namespace Plasma -+{ -+class ExtenderItem; -+class TabBar; -+class Dialog; -+} -+ -+class NotificationWidget; -+class StackDialog; -+ -+ -+class Job; -+class JobTotalsWidget; -+class Manager; -+class Notification; -+class NotificationGroup; -+class NotificationStack; -+class BusyWidget; -+ -+class Notifications : public Plasma::PopupApplet -+{ -+ Q_OBJECT -+ -+public: -+ explicit Notifications(QObject *parent, const QVariantList &arguments = QVariantList()); -+ ~Notifications(); -+ -+ void init(); -+ Manager *manager() const; -+ -+protected: -+ void createConfigurationInterface(KConfigDialog *parent); -+ void initExtenderItem(Plasma::ExtenderItem *extenderItem); -+ void configChanged(); -+ -+ void popupEvent(bool show); -+ -+private slots: -+ void configAccepted(); -+ void addNotification(Notification *notification); -+ void addJob(Job *job); -+ void finishJob(Job *job); -+ void open(const QString &url); -+ void syncNotificationBarNeeded(); -+ -+private: -+ void createJobGroups(); -+ -+ Manager *m_manager; -+ static int s_managerUsage; -+ -+ QWeakPointer m_notificationInterface; -+ QDateTime m_lastActivity; -+ -+ JobTotalsWidget *m_jobSummaryWidget; -+ bool m_autoHidePopup; -+ -+ QWeakPointer m_notificationGroup; -+ NotificationStack *m_notificationStack; -+ StackDialog *m_notificationStackDialog; -+ JobTotalsWidget *m_standaloneJobSummaryWidget; -+ Plasma::Dialog *m_standaloneJobSummaryDialog; -+ -+ BusyWidget *m_busyWidget; -+ -+ Ui::NotificationsConfig m_notificationUi; -+}; -+ -+ -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/notificationsconfig.ui b/plasma/generic/applets/notifications/ui/notificationsconfig.ui -new file mode 100644 -index 0000000..aaa6a82 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationsconfig.ui -@@ -0,0 +1,114 @@ -+ -+ -+ NotificationsConfig -+ -+ -+ -+ 0 -+ 0 -+ 213 -+ 236 -+ -+ -+ -+ -+ QFormLayout::ExpandingFieldsGrow -+ -+ -+ -+ -+ -+ 75 -+ true -+ -+ -+ -+ Pop Up Notices -+ -+ -+ -+ -+ -+ -+ Application notifications -+ -+ -+ showNotifications -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ File transfers and other jobs -+ -+ -+ showJobs -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Vertical -+ -+ -+ QSizePolicy::Fixed -+ -+ -+ -+ 20 -+ 6 -+ -+ -+ -+ -+ -+ -+ -+ -+ 75 -+ true -+ -+ -+ -+ Popup -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Automatically hide -+ -+ -+ autoHide -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/plasma/generic/applets/notifications/ui/notificationstack.cpp b/plasma/generic/applets/notifications/ui/notificationstack.cpp -new file mode 100644 -index 0000000..f0fc52e ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationstack.cpp -@@ -0,0 +1,233 @@ -+/*************************************************************************** -+ * notificationstack.cpp * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "notificationstack.h" -+#include "../core/notification.h" -+#include "notificationwidget.h" -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+NotificationStack::NotificationStack(QGraphicsItem *parent) -+ : QGraphicsWidget(parent), -+ m_size(4), -+ m_underMouse(false) -+{ -+ m_mainLayout = new QGraphicsLinearLayout(Qt::Vertical, this); -+ m_canDismissTimer = new QTimer(this); -+ m_canDismissTimer->setSingleShot(true); -+ -+ m_delayedRemoveTimer = new QTimer(this); -+ m_delayedRemoveTimer->setSingleShot(true); -+ connect(m_delayedRemoveTimer, SIGNAL(timeout()), this, SLOT(popNotification())); -+ -+ setAcceptsHoverEvents(true); -+} -+ -+NotificationStack::~NotificationStack() -+{ -+} -+ -+void NotificationStack::addNotification(Notification *notification) -+{ -+ m_canDismissTimer->start(1000); -+ connect(notification, SIGNAL(notificationDestroyed(Notification*)), this, SLOT(removeNotification(Notification*)), Qt::UniqueConnection); -+ connect(notification, SIGNAL(expired(Notification*)), this, SLOT(delayedRemoveNotification(Notification*)), Qt::UniqueConnection); -+ connect(notification, SIGNAL(changed(Notification*)), this, SLOT(notificationChanged(Notification*)), Qt::UniqueConnection); -+ -+ NotificationWidget *notificationWidget = new NotificationWidget(notification, this); -+ notificationWidget->installEventFilter(this); -+ notificationWidget->setAcceptsHoverEvents(this); -+ connect(notificationWidget, SIGNAL(actionTriggered(Notification*)), this, SLOT(removeNotification(Notification*))); -+ -+ m_notificationWidgets[notification] = notificationWidget; -+ m_notifications.append(notification); -+ -+ if (m_notifications.size() > 1) { -+ notificationWidget->setCollapsed(true, false); -+ } else { -+ m_currentNotificationWidget = notificationWidget; -+ } -+ -+ if (m_notifications.size() > m_size) { -+ bool found = false; -+ -+ //try to kill the oldest notification of the same app -+ foreach (Notification *notif, m_notifications) { -+ if (notif->applicationName() == notification->applicationName()) { -+ m_notificationWidgets[notif]->deleteLater(); -+ m_notificationWidgets.remove(notif); -+ m_notifications.removeAll(notif); -+ found = true; -+ break; -+ } -+ } -+ //or kill the oldest one -+ if (!found) { -+ Notification *notif = m_notifications.first(); -+ m_notificationWidgets[notif]->deleteLater(); -+ m_notificationWidgets.remove(notif); -+ m_notifications.pop_front(); -+ } -+ } -+ -+ m_mainLayout->insertItem(0, notificationWidget); -+ m_mainLayout->activate(); -+ updateGeometry(); -+ resize(size().width(), effectiveSizeHint(Qt::MinimumSize).height()); -+ emit updateRequested(); -+} -+ -+void NotificationStack::notificationChanged(Notification *notification) -+{ -+ //if it was gone away put in on the stack again -+ if (!m_notificationWidgets.contains(notification)) { -+ addNotification(notification); -+ } -+ emit showRequested(); -+} -+ -+void NotificationStack::removeNotification(Notification *notification) -+{ -+ NotificationWidget *nw = m_notificationWidgets.value(notification); -+ if (nw) { -+ nw->deleteLater(); -+ } -+ m_mainLayout->removeItem(nw); -+ m_notificationWidgets.remove(notification); -+ m_notifications.removeAll(notification); -+ -+ if (m_notifications.count() > 0) { -+ setCurrentNotification(m_notifications.first()); -+ } -+ -+ if (m_notifications.count() == 0) { -+ emit stackEmpty(); -+ } -+ -+ updateGeometry(); -+ resize(size().width(), sizeHint(Qt::MinimumSize, QSizeF()).height()); -+ emit updateRequested(); -+} -+ -+void NotificationStack::delayedRemoveNotification(Notification *notification) -+{ -+ m_notificationsToRemove.append(notification); -+ if (!m_underMouse) { -+ m_delayedRemoveTimer->start(1000); -+ } -+} -+ -+void NotificationStack::setCurrentNotification(Notification *notification) -+{ -+ if (m_notificationWidgets.contains(notification)) { -+ if (m_currentNotificationWidget) { -+ m_currentNotificationWidget.data()->setCollapsed(true); -+ } -+ m_currentNotificationWidget = m_notificationWidgets.value(notification); -+ m_currentNotificationWidget.data()->setCollapsed(false); -+ } -+} -+ -+void NotificationStack::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ m_underMouse = true; -+ m_delayedRemoveTimer->stop(); -+} -+ -+void NotificationStack::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ m_underMouse = false; -+ m_delayedRemoveTimer->start(1000); -+} -+ -+void NotificationStack::mousePressEvent(QGraphicsSceneMouseEvent *event) -+{ -+ event->accept(); -+} -+ -+void NotificationStack::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ if (!m_canDismissTimer->isActive() && -+ QPointF(event->buttonDownScenePos(event->button()) - event->scenePos()).manhattanLength() < KGlobalSettings::dndEventDelay()) { -+ emit hideRequested(); -+ } -+} -+ -+NotificationWidget *NotificationStack::currentNotificationWidget() const -+{ -+ if (m_currentNotificationWidget) { -+ return m_currentNotificationWidget.data(); -+ } else { -+ return 0; -+ } -+} -+ -+bool NotificationStack::eventFilter(QObject *watched, QEvent *event) -+{ -+ NotificationWidget *nw = qobject_cast(watched); -+ -+ if (!nw) { -+ return false; -+ } -+ -+ if (event->type() == QEvent::GraphicsSceneHoverEnter) { -+ if (m_currentNotificationWidget && m_currentNotificationWidget.data() == nw) { -+ return false; -+ } else if (m_currentNotificationWidget) { -+ m_currentNotificationWidget.data()->setCollapsed(true); -+ } -+ nw->setCollapsed(false); -+ m_currentNotificationWidget = nw; -+ m_canDismissTimer->start(1000); -+ } else if (event->type() == QEvent::GraphicsSceneMove) { -+ emit updateRequested(); -+ } -+ -+ -+ return false; -+} -+ -+void NotificationStack::popNotification() -+{ -+ if (m_notificationsToRemove.isEmpty()) { -+ return; -+ } -+ -+ Notification *notif = m_notificationsToRemove.first(); -+ removeNotification(notif); -+ m_notificationsToRemove.pop_front(); -+ m_delayedRemoveTimer->start(1000); -+} -+ -+ -+#include "notificationstack.moc" -diff --git a/plasma/generic/applets/notifications/ui/notificationstack.h b/plasma/generic/applets/notifications/ui/notificationstack.h -new file mode 100644 -index 0000000..783e5ae ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationstack.h -@@ -0,0 +1,81 @@ -+/*************************************************************************** -+ * notificationscroller.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONSTACK_H -+#define NOTIFICATIONSTACK_H -+ -+#include -+ -+class QGraphicsLinearLayout; -+class QTimer; -+ -+class NotificationWidget; -+ -+class Notification; -+ -+class NotificationStack : public QGraphicsWidget -+{ -+ Q_OBJECT -+ -+public: -+ NotificationStack(QGraphicsItem *parent = 0); -+ ~NotificationStack(); -+ -+ void addNotification(Notification *notification); -+ -+ //TODO:accessor -+ void setCurrentNotification(Notification *notification); -+ -+ NotificationWidget *currentNotificationWidget() const; -+ -+protected: -+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event); -+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); -+ void mousePressEvent(QGraphicsSceneMouseEvent *event); -+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); -+ bool eventFilter(QObject *watched, QEvent *event); -+ -+public Q_SLOTS: -+ void removeNotification(Notification *notification); -+ void delayedRemoveNotification(Notification *notification); -+ -+private Q_SLOTS: -+ void popNotification(); -+ void notificationChanged(Notification *notification); -+ -+Q_SIGNALS: -+ void stackEmpty(); -+ void updateRequested(); -+ void hideRequested(); -+ void showRequested(); -+ -+private: -+ QList m_notifications; -+ QList m_notificationsToRemove; -+ QHash m_notificationWidgets; -+ QGraphicsLinearLayout *m_mainLayout; -+ int m_size; -+ bool m_underMouse; -+ QWeakPointer m_currentNotificationWidget; -+ QTimer *m_delayedRemoveTimer; -+ QTimer *m_canDismissTimer; -+}; -+ -+#endif -diff --git a/plasma/generic/applets/notifications/ui/notificationwidget.cpp b/plasma/generic/applets/notifications/ui/notificationwidget.cpp -new file mode 100644 -index 0000000..02ed38f ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationwidget.cpp -@@ -0,0 +1,486 @@ -+/*************************************************************************** -+ * notificationwidget.cpp * -+ * * -+ * Copyright (C) 2008 Dmitry Suzdalev * -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU Library General Public License as * -+ * published by the Free Software Foundation; either version 2 of the * -+ * License, or (at your option) any later version. * -+ * * -+ * 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 Library General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU Library 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 "notificationwidget.h" -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+class NotificationWidgetPrivate -+{ -+public: -+ NotificationWidgetPrivate(NotificationWidget *q) -+ : q(q), -+ destroyOnClose(true), -+ autoDelete(false), -+ collapsed(false), -+ icon(0), -+ actionsWidget(0), -+ signalMapper(new QSignalMapper(q)) -+ { -+ } -+ -+ void setTextFields(const QString &applicationName, const QString &summary, const QString &message); -+ void completeDetach(); -+ void updateActions(); -+ void updateNotification(); -+ void buttonClicked(); -+ void hideFinished(); -+ QRectF bigIconRect() const; -+ -+ NotificationWidget *q; -+ -+ QWeakPointer notification; -+ bool destroyOnClose; -+ bool autoDelete; -+ bool collapsed; -+ -+ QString message; -+ Plasma::TextBrowser *messageLabel; -+ Plasma::Label *title; -+ Plasma::IconWidget *closeButton; -+ Plasma::IconWidget *icon; -+ QGraphicsLinearLayout *titleLayout; -+ QGraphicsLinearLayout *mainLayout; -+ QGraphicsGridLayout *bodyLayout; -+ QGraphicsWidget *body; -+ QGraphicsWidget *iconPlaceSmall; -+ QGraphicsWidget *iconPlaceBig; -+ QGraphicsWidget *actionsWidget; -+ QHash actions; -+ QStringList actionOrder; -+ QPropertyAnimation *hideAnimation; -+ QPropertyAnimation *iconAnimation; -+ QParallelAnimationGroup *animationGroup; -+ -+ QSignalMapper *signalMapper; -+}; -+ -+NotificationWidget::NotificationWidget(Notification *notification, QGraphicsWidget *parent) -+ : QGraphicsWidget(parent), -+ d(new NotificationWidgetPrivate(this)) -+{ -+ setFlag(QGraphicsItem::ItemHasNoContents, true); -+ setMinimumWidth(300); -+ -+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); -+ -+ -+ d->iconPlaceSmall = new QGraphicsWidget(this); -+ d->iconPlaceSmall->setMinimumSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall); -+ d->iconPlaceSmall->setMaximumSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall); -+ d->icon = new Plasma::IconWidget(this); -+ d->icon->setAcceptHoverEvents(false); -+ d->icon->setAcceptedMouseButtons(Qt::NoButton); -+ -+ d->title = new Plasma::Label(this); -+ d->title->setWordWrap(false); -+ d->title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); -+ d->title->setAlignment(Qt::AlignCenter); -+ -+ d->closeButton = new Plasma::IconWidget(this); -+ d->closeButton->setSvg("widgets/configuration-icons", "close"); -+ d->closeButton->setMaximumSize(d->closeButton->sizeFromIconSize(KIconLoader::SizeSmall)); -+ d->closeButton->setMinimumSize(d->closeButton->maximumSize()); -+ connect(d->closeButton, SIGNAL(clicked()), notification, SLOT(deleteLater())); -+ -+ d->titleLayout = new QGraphicsLinearLayout(Qt::Horizontal); -+ d->titleLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); -+ d->titleLayout->addItem(d->iconPlaceSmall); -+ d->titleLayout->addItem(d->title); -+ d->titleLayout->addItem(d->closeButton); -+ -+ -+ -+ d->body = new QGraphicsWidget(this); -+ d->body->setContentsMargins(0,0,0,0); -+ d->body->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); -+ d->bodyLayout = new QGraphicsGridLayout(d->body); -+ d->bodyLayout->setSpacing(0); -+ d->bodyLayout->setContentsMargins(0,0,0,0); -+ -+ d->messageLabel = new Plasma::TextBrowser(d->body); -+ d->messageLabel->setPreferredWidth(0); -+ d->messageLabel->nativeWidget()->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); -+ d->messageLabel->nativeWidget()->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); -+ d->messageLabel->nativeWidget()->setAlignment(Qt::AlignLeft|Qt::AlignVCenter); -+ d->messageLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); -+ connect(d->messageLabel->nativeWidget(), SIGNAL(urlClick(QString)), -+ notification, SLOT(linkActivated(QString))); -+ -+ d->iconPlaceBig = new QGraphicsWidget(this); -+ d->iconPlaceBig->setMaximumHeight(KIconLoader::SizeLarge); -+ d->iconPlaceBig->setMinimumHeight(KIconLoader::SizeLarge); -+ d->iconPlaceBig->setMaximumWidth(KIconLoader::SizeLarge); -+ d->iconPlaceBig->setMinimumWidth(KIconLoader::SizeLarge); -+ d->iconPlaceBig->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); -+ d->bodyLayout->addItem(d->iconPlaceBig, 0, 0, Qt::AlignCenter); -+ d->bodyLayout->addItem(d->messageLabel, 0, 1, Qt::AlignCenter); -+ -+ d->mainLayout = new QGraphicsLinearLayout(Qt::Vertical, this); -+ d->mainLayout->setSpacing(0); -+ d->mainLayout->addItem(d->titleLayout); -+ d->mainLayout->addItem(d->body); -+ -+ d->notification = notification; -+ -+ connect(d->signalMapper, SIGNAL(mapped(QString)), -+ notification, SLOT(triggerAction(QString))); -+ connect(notification, SIGNAL(changed()), -+ this, SLOT(updateNotification())); -+ connect(notification, SIGNAL(destroyed()), -+ this, SLOT(deleteLater())); -+ -+ d->hideAnimation = new QPropertyAnimation(this, "bodyHeight", this); -+ d->hideAnimation->setDuration(250); -+ connect(d->hideAnimation, SIGNAL(finished()), this, SLOT(hideFinished())); -+ -+ d->iconAnimation = new QPropertyAnimation(d->icon, "geometry", d->icon); -+ d->iconAnimation->setDuration(250); -+ -+ d->animationGroup = new QParallelAnimationGroup(this); -+ d->animationGroup->addAnimation(d->hideAnimation); -+ d->animationGroup->addAnimation(d->iconAnimation); -+ -+ d->updateNotification(); -+ -+ d->mainLayout->activate(); -+ updateGeometry(); -+} -+ -+NotificationWidget::~NotificationWidget() -+{ -+ delete d; -+} -+ -+void NotificationWidget::setCollapsed(bool collapse, bool animate) -+{ -+ if (collapse == d->collapsed) { -+ return; -+ } -+ -+ setTitleBarVisible(true); -+ -+ //use this weird way to make easy to animate -+ if (animate) { -+ setMinimumHeight(-1); -+ if (collapse) { -+ d->hideAnimation->setStartValue(d->body->size().height()); -+ d->hideAnimation->setEndValue(0); -+ -+ d->iconAnimation->setStartValue(d->icon->geometry()); -+ d->iconAnimation->setEndValue(d->iconPlaceSmall->geometry()); -+ d->animationGroup->start(); -+ } else { -+ d->body->setVisible(true); -+ d->hideAnimation->setStartValue(d->body->size().height()); -+ d->body->setMaximumHeight(-1); -+ d->hideAnimation->setEndValue(d->body->effectiveSizeHint(Qt::PreferredSize).height()); -+ -+ d->iconAnimation->setStartValue(d->icon->geometry()); -+ d->iconAnimation->setEndValue(d->bigIconRect()); -+ d->animationGroup->start(); -+ } -+ } else { -+ if (collapse) { -+ //setMaximumHeight(d->titleLayout->geometry().bottom()); -+ d->body->setMinimumHeight(0); -+ d->body->setMaximumHeight(0); -+ d->body->hide(); -+ setMinimumHeight(-1); -+ d->icon->setGeometry(d->iconPlaceSmall->geometry()); -+ } else { -+ d->body->show(); -+ d->body->setMaximumHeight(-1); -+ d->body->setMinimumHeight(-1); -+ d->body->setMaximumHeight(d->body->effectiveSizeHint(Qt::PreferredSize).height()); -+ d->body->setMinimumHeight(d->body->maximumHeight()); -+ updateGeometry(); -+ d->mainLayout->invalidate(); -+ setMinimumHeight(sizeHint(Qt::PreferredSize, QSizeF()).height()); -+ -+ d->icon->setGeometry(d->bigIconRect()); -+ } -+ } -+ -+ if (collapse) { -+ d->messageLabel->nativeWidget()->setTextInteractionFlags(Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard); -+ } else { -+ d->messageLabel->nativeWidget()->setTextInteractionFlags(Qt::LinksAccessibleByMouse); -+ } -+ -+ d->body->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); -+ -+ d->collapsed = collapse; -+} -+ -+Notification *NotificationWidget::notification() const -+{ -+ return d->notification.data(); -+} -+ -+qreal NotificationWidget::bodyHeight() const -+{ -+ return d->body->maximumHeight(); -+} -+ -+void NotificationWidget::setBodyHeight(const qreal height) -+{ -+ d->body->setMaximumHeight(height); -+ d->body->setMinimumHeight(height); -+ updateGeometry(); -+ d->mainLayout->invalidate(); -+ setMinimumHeight(sizeHint(Qt::PreferredSize, QSizeF()).height()); -+} -+ -+bool NotificationWidget::isCollapsed() const -+{ -+ return d->collapsed; -+} -+ -+void NotificationWidget::setTitleBarVisible(bool visible) -+{ -+ if (visible) { -+ d->iconPlaceSmall->show(); -+ d->title->show(); -+ d->closeButton->show(); -+ d->titleLayout->setMaximumHeight(QWIDGETSIZE_MAX); -+ } else { -+ d->iconPlaceSmall->hide(); -+ d->title->hide(); -+ d->closeButton->hide(); -+ d->titleLayout->setMaximumHeight(0); -+ } -+} -+ -+bool NotificationWidget::isTitleBarVisible() const -+{ -+ return d->title->isVisible(); -+} -+ -+void NotificationWidget::resizeEvent(QGraphicsSceneResizeEvent *event) -+{ -+ QGraphicsWidget::resizeEvent(event); -+ if (d->icon && !d->collapsed && d->animationGroup->state() != QAbstractAnimation::Running) { -+ d->icon->setGeometry(d->bigIconRect()); -+ } -+} -+ -+QRectF NotificationWidgetPrivate::bigIconRect() const -+{ -+ return q->mapFromScene(iconPlaceBig->mapToScene(iconPlaceBig->boundingRect())).boundingRect(); -+} -+ -+void NotificationWidgetPrivate::setTextFields(const QString &applicationName, -+ const QString &summary, const QString &message) -+{ -+ if (!summary.isEmpty()) { -+ title->setText(summary); -+ } else { -+ title->setText(i18n("Notification from %1", applicationName)); -+ } -+ -+ -+ QString processed = message.trimmed(); -+ -+ /*if there is a < that is not closed as a tag, replace it with an entity*/ -+ processed = processed.replace(QRegExp("<(?![^<]*>)"), "<"); -+ processed.replace('\n', "
"); -+ -+ QFontMetricsF fm(messageLabel->font()); -+ qreal maxLine = messageLabel->rect().width(); -+ -+ QString parsed; -+ -+ QString::const_iterator i = processed.begin(); -+ bool inTag = false; -+ QString word; -+ QString sentence; -+ -+ while (i != processed.end()) { -+ QChar c = *i; -+ -+ if (c == '<') { -+ inTag = true; -+ sentence.append(word); -+ parsed.append(fm.elidedText(sentence, Qt::ElideRight, maxLine*4.6)); -+ sentence = QString(); -+ word = QString(); -+ word.append(c); -+ } else if (c == '>') { -+ word.append(c); -+ if (!sentence.isEmpty()) { -+ parsed.append(fm.elidedText(sentence, Qt::ElideRight, maxLine*4.6)); -+ sentence.clear(); -+ } -+ inTag = false; -+ parsed.append(word); -+ word = QString(); -+ } else if (c == ' ') { -+ word.append(c); -+ if (inTag) { -+ parsed.append(word); -+ } else { -+ sentence.append(word); -+ } -+ word = QString(); -+ } else { -+ word.append(c); -+ } -+ -+ ++i; -+ } -+ -+ sentence.append(word); -+ parsed.append(fm.elidedText(sentence, Qt::ElideRight, maxLine*4.6)); -+ -+ messageLabel->setText(QLatin1String("") + parsed + QLatin1String("")); -+ -+ if (!collapsed) { -+ icon->setGeometry(bigIconRect()); -+ } -+} -+ -+void NotificationWidgetPrivate::completeDetach() -+{ -+ actions.clear(); -+ actionOrder.clear(); -+ -+ delete actionsWidget; -+ actionsWidget = 0; -+} -+ -+void NotificationWidgetPrivate::updateActions() -+{ -+ if (actions.isEmpty() || actionsWidget) { -+ return; -+ } -+ -+ actionsWidget = new QGraphicsWidget(body); -+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(actionsWidget); -+ layout->setOrientation(Qt::Vertical); -+ layout->setContentsMargins(0, 0, 0, 0); -+ layout->addStretch(); -+ actionsWidget->setContentsMargins(0, 0, 0, 0); -+ -+ foreach (const QString &actionId, actionOrder) { -+ Plasma::PushButton *button = new Plasma::PushButton(actionsWidget); -+ QString &action = actions[actionId]; -+ button->setText(action); -+ button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); -+ //TODO: we need smaller buttons but I don't like this method of accomplishing it. -+ button->setPreferredHeight(button->minimumHeight() - 6); -+ -+ q->connect(button, SIGNAL(clicked()), signalMapper, SLOT(map())); -+ q->connect(button, SIGNAL(clicked()), q, SLOT(buttonClicked())); -+ signalMapper->setMapping(button, actionId); -+ -+ layout->addItem(button); -+ } -+ layout->addStretch(); -+ layout->activate(); -+ -+ if (actionsWidget->size().width() > q->size().width() * 0.4) { -+ layout->setOrientation(Qt::Horizontal); -+ bodyLayout->addItem(actionsWidget, 1, 0, 1, 2, Qt::AlignCenter); -+ } else { -+ bodyLayout->addItem(actionsWidget, 0, 2, Qt::AlignCenter); -+ } -+} -+ -+void NotificationWidgetPrivate::buttonClicked() -+{ -+ //a decsion has already been taken -+ if (actionsWidget) { -+ notification.data()->deleteLater(); -+ } -+ emit q->actionTriggered(notification.data()); -+} -+ -+void NotificationWidgetPrivate::updateNotification() -+{ -+ if (!notification) { -+ return; -+ } -+ -+ -+ //set text fields and icon -+ setTextFields(notification.data()->applicationName(), notification.data()->summary(), notification.data()->message()); -+ icon->setIcon(notification.data()->applicationIcon()); -+ messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); -+ -+ //set the actions provided -+ actions = notification.data()->actions(); -+ actionOrder = notification.data()->actionOrder(); -+ updateActions(); -+ -+ if (!notification.data()->image().isNull()) { -+ -+ icon->setIcon(QPixmap::fromImage(notification.data()->image())); -+ -+ QSize imageSize = notification.data()->image().size(); -+ -+ if (imageSize.width() > KIconLoader::SizeLarge || imageSize.height() > KIconLoader::SizeLarge) { -+ imageSize.scale(KIconLoader::SizeLarge, KIconLoader::SizeLarge, Qt::KeepAspectRatio); -+ } -+ -+ icon->setMaximumIconSize(QSizeF(qMin((int)KIconLoader::SizeLarge, imageSize.width()), -+ qMin((int)KIconLoader::SizeLarge, imageSize.height()))); -+ } -+ -+ -+ //FIXME: this sounds wrong -+ q->setPreferredHeight(mainLayout->effectiveSizeHint(Qt::MinimumSize).height()); -+} -+ -+void NotificationWidgetPrivate::hideFinished() -+{ -+ body->setVisible(!collapsed); -+ body->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false); -+} -+ -+#include "notificationwidget.moc" -diff --git a/plasma/generic/applets/notifications/ui/notificationwidget.h b/plasma/generic/applets/notifications/ui/notificationwidget.h -new file mode 100644 -index 0000000..7c1a436 ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/notificationwidget.h -@@ -0,0 +1,72 @@ -+/*************************************************************************** -+ * notificationwidget.h * -+ * * -+ * Copyright (C) 2008 Dmitry Suzdalev * -+ * Copyright (C) 2008 Rob Scheepmaker * -+ * Copyright (C) 2008 Jason Stubbs * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU Library General Public License as * -+ * published by the Free Software Foundation; either version 2 of the * -+ * License, or (at your option) any later version. * -+ * * -+ * 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 Library General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU Library 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 . * -+ ***************************************************************************/ -+ -+#ifndef NOTIFICATIONWIDGET_H -+#define NOTIFICATIONWIDGET_H -+ -+#include -+ -+#include "../core/notification.h" -+ -+class NotificationWidgetPrivate; -+ -+/** -+ * A graphics item, representing notification message. -+ */ -+class NotificationWidget : public QGraphicsWidget -+{ -+ Q_OBJECT -+ Q_PROPERTY(qreal bodyHeight READ bodyHeight WRITE setBodyHeight) -+ -+public: -+ NotificationWidget(Notification *notification, QGraphicsWidget *parent); -+ ~NotificationWidget(); -+ -+ void setCollapsed(bool collapse, bool animate = true); -+ bool isCollapsed() const; -+ -+ void setTitleBarVisible(bool visible); -+ bool isTitleBarVisible() const; -+ -+ qreal bodyHeight() const; -+ void setBodyHeight(const qreal height); -+ -+ Notification *notification() const; -+ -+protected: -+ void resizeEvent(QGraphicsSceneResizeEvent *event); -+ -+Q_SIGNALS: -+ void actionTriggered(Notification *); -+ -+private: -+ friend class NotificationWidgetPrivate; -+ NotificationWidgetPrivate* const d; -+ -+ Q_PRIVATE_SLOT(d, void updateNotification()) -+ Q_PRIVATE_SLOT(d, void buttonClicked()) -+ Q_PRIVATE_SLOT(d, void hideFinished()) -+}; -+ -+#endif // NOTIFICATIONWIDGET_H -diff --git a/plasma/generic/applets/notifications/ui/stackdialog.cpp b/plasma/generic/applets/notifications/ui/stackdialog.cpp -new file mode 100644 -index 0000000..9be364e ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/stackdialog.cpp -@@ -0,0 +1,446 @@ -+/*************************************************************************** -+ * stacdialog.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#include "stackdialog.h" -+#include "notificationstack.h" -+#include "notificationwidget.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static const uint hideTimeout = 15 * 1000; -+ -+StackDialog::StackDialog(QWidget *parent, Qt::WindowFlags f) -+ : Plasma::Dialog(parent, f), -+ m_applet(0), -+ m_windowToTile(0), -+ m_notificationStack(0), -+ m_view(0), -+ m_drawLeft(true), -+ m_drawRight(true), -+ m_autoHide(true), -+ m_hasCustomPosition(false) -+{ -+ m_background = new Plasma::FrameSvg(this); -+ m_background->setImagePath("widgets/extender-background"); -+ setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); -+ KWindowSystem::setType(winId(), NET::Dock); -+ -+ m_showTimer = new QTimer(this); -+ m_showTimer->setSingleShot(true); -+ m_showTimer->setInterval(0); -+ connect(m_showTimer, SIGNAL(timeout()), this, SLOT(show())); -+ -+ m_hideTimer = new QTimer(this); -+ m_hideTimer->setSingleShot(true); -+ connect(m_hideTimer, SIGNAL(timeout()), this, SLOT(hideRequested())); -+} -+ -+StackDialog::~StackDialog() -+{ -+} -+ -+void StackDialog::setNotificationStack(NotificationStack *stack) -+{ -+ setGraphicsWidget(stack); -+ -+ if (!m_view && layout()) { -+ m_view = qobject_cast(layout()->itemAt(0)->widget()); -+ if (m_view) { -+ m_view->installEventFilter(this); -+ } -+ } -+ -+ if (m_notificationStack) { -+ disconnect(m_notificationStack, 0, this, 0); -+ } -+ -+ m_notificationStack = stack; -+ -+ connect(m_notificationStack, SIGNAL(updateRequested()), this, SLOT(update())); -+ connect(m_notificationStack, SIGNAL(hideRequested()), this, SLOT(hideRequested())); -+} -+ -+NotificationStack *StackDialog::notificartionStack() const -+{ -+ return m_notificationStack; -+} -+ -+void StackDialog::setApplet(Plasma::Applet *applet) -+{ -+ m_applet = applet; -+ adjustPosition(QPoint(-1, -1)); -+} -+ -+Plasma::Applet *StackDialog::applet() const -+{ -+ return m_applet; -+} -+ -+void StackDialog::setWindowToTile(QWidget *widget) -+{ -+ if (m_windowToTile) { -+ m_windowToTile->removeEventFilter(this); -+ delete m_windowToTileAnimation; -+ } -+ -+ m_windowToTile = widget; -+ m_windowToTile->installEventFilter(this); -+ m_windowToTileAnimation = new QPropertyAnimation(m_windowToTile, "pos", this); -+ m_windowToTileAnimation->setDuration(250); -+ m_windowToTileAnimation->setEasingCurve(QEasingCurve::InOutQuad); -+} -+ -+QWidget *StackDialog::windowToTile() const -+{ -+ return m_windowToTile; -+} -+ -+void StackDialog::setAutoHide(const bool autoHide) -+{ -+ m_autoHide = autoHide; -+} -+ -+bool StackDialog::autoHide() const -+{ -+ return m_autoHide; -+} -+ -+void StackDialog::adjustWindowToTilePos() -+{ -+ if (m_applet && m_windowToTile && m_hasCustomPosition) { -+ m_windowToTileAnimation->setStartValue(m_windowToTile->pos()); -+ -+ if (isVisible()) { -+ const QRect realScreenRect = qApp->desktop()->screenGeometry(m_applet->containment()->screen()); -+ if (m_applet->location() == Plasma::TopEdge || (pos().y() - realScreenRect.top()) < m_windowToTile->size().height()) { -+ m_windowToTileAnimation->setEndValue(QPoint(m_windowToTile->pos().x(), geometry().bottom())); -+ } else { -+ m_windowToTileAnimation->setEndValue(QPoint(m_windowToTile->pos().x(), pos().y() - m_windowToTile->size().height())); -+ } -+ } else if (m_applet && m_applet->containment() && m_applet->containment()->corona()) { -+ m_windowToTileAnimation->setEndValue(QPoint(m_applet->containment()->corona()->popupPosition(m_applet, m_windowToTile->size()))); -+ } -+ m_windowToTileAnimation->start(); -+ } -+} -+ -+void StackDialog::paintEvent(QPaintEvent *e) -+{ -+ Plasma::Dialog::paintEvent(e); -+ -+ QPainter painter(this); -+ if (m_notificationStack) { -+ //FIXME: assumption++ -+ QGraphicsLayout *mainLayout = static_cast(m_notificationStack->layout()); -+ -+ if (!m_notificationStack->currentNotificationWidget() || mainLayout->count() < 2) { -+ return; -+ } -+ -+ for (int i = 0; i < mainLayout->count(); ++i) { -+ //assumption++ all items are NotificationWidget -+ NotificationWidget *nw = static_cast(mainLayout->itemAt(i)); -+ -+ //first element -+ if (i == 0 && m_notificationStack->currentNotificationWidget() != nw) { -+ continue; -+ } else if (i == 0) { -+ m_background->setEnabledBorders((Plasma::FrameSvg::EnabledBorders)(Plasma::FrameSvg::AllBorders&~Plasma::FrameSvg::TopBorder)); -+ //last element -+ } else if (i == mainLayout->count()-1 && m_notificationStack->currentNotificationWidget() != nw) { -+ continue; -+ } else if (i == mainLayout->count()-1) { -+ m_background->setEnabledBorders((Plasma::FrameSvg::EnabledBorders)Plasma::FrameSvg::AllBorders&~Plasma::FrameSvg::BottomBorder); -+ //element under the active one -+ } else if (m_notificationStack->currentNotificationWidget()->pos().y() < nw->pos().y()) { -+ m_background->setEnabledBorders((Plasma::FrameSvg::EnabledBorders)Plasma::FrameSvg::AllBorders&~Plasma::FrameSvg::TopBorder); -+ //element over the active one -+ } else if (m_notificationStack->currentNotificationWidget()->pos().y() > nw->pos().y()) { -+ m_background->setEnabledBorders((Plasma::FrameSvg::EnabledBorders)Plasma::FrameSvg::AllBorders&~Plasma::FrameSvg::BottomBorder); -+ //active element -+ } else { -+ m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders); -+ } -+ -+ qreal left, top, right, bottom; -+ m_background->getMargins(left, top, right, bottom); -+ m_background->resizeFrame(QSizeF(size().width(), nw->size().height() + top + bottom)); -+ -+ Plasma::FrameSvg::EnabledBorders borders = m_background->enabledBorders(); -+ -+ if (!m_drawLeft) { -+ borders &= ~Plasma::FrameSvg::LeftBorder; -+ } -+ -+ if (!m_drawRight) { -+ borders &= ~Plasma::FrameSvg::RightBorder; -+ } -+ -+ m_background->setEnabledBorders(borders); -+ -+ const int topMargin = contentsRect().top(); -+ m_background->paintFrame(&painter, QPointF(0, nw->pos().y() - top + topMargin)); -+ } -+ } -+} -+ -+void StackDialog::perhapsShow() -+{ -+ if (m_applet && m_applet->view()) { -+ // we use a timer here because when the stack is going to be shown, the applet is likely -+ // to also be in movement (e.g. from hidden away to now shown to the user) and that will -+ // likely result in an odd geometry for the applet when popupPosition is called on this -+ // dialog. so instead we wait a bit after the show request to allow the applet to find -+ // it's proper place -+ m_showTimer->start(); -+ } -+} -+ -+void StackDialog::showEvent(QShowEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ adjustPosition(adjustedSavedPos()); -+ adjustWindowToTilePos(); -+ -+ if (m_autoHide) { -+ m_hideTimer->start(hideTimeout); -+ } -+ -+ Plasma::Dialog::showEvent(event); -+} -+ -+void StackDialog::hideRequested() -+{ -+ // we have this method because hide() may not always cause a hideEvent, e.g. when -+ // the StackDialog has not been shown yet .. however, we always want to ensure the -+ // show timer is stopped. we also stop it in the hideEvent for completeness and to -+ // catch any direct calls to hide() that may happen -+ m_showTimer->stop(); -+ hide(); -+} -+ -+void StackDialog::hideEvent(QHideEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ m_showTimer->stop(); -+ m_hideTimer->stop(); -+ -+ adjustWindowToTilePos(); -+ -+ m_notificationStack->adjustSize(); -+ Plasma::Dialog::hideEvent(event); -+} -+ -+void StackDialog::resizeEvent(QResizeEvent *event) -+{ -+ Q_UNUSED(event) -+ adjustWindowToTilePos(); -+ Plasma::Dialog::resizeEvent(event); -+ if (m_hasCustomPosition) { -+ adjustPosition(pos()); -+ } else if (m_applet && m_applet->containment() && m_applet->containment()->corona()) { -+ move(m_applet->containment()->corona()->popupPosition(m_applet, size())); -+ } -+} -+ -+void StackDialog::moveEvent(QMoveEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ adjustWindowToTilePos(); -+ Plasma::Dialog::moveEvent(event); -+} -+ -+void StackDialog::enterEvent(QEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ m_hideTimer->stop(); -+} -+ -+void StackDialog::leaveEvent(QEvent *event) -+{ -+ Q_UNUSED(event) -+ -+ if (m_autoHide) { -+ m_hideTimer->start(hideTimeout); -+ } -+ Plasma::Dialog::leaveEvent(event); -+} -+ -+void StackDialog::adjustPosition(const QPoint &pos) -+{ -+ if (!m_applet) { -+ return; -+ } -+ -+ if (pos == QPoint(-1, -1)) { -+ const QPoint popupPosition = m_applet->containment()->corona()->popupPosition(m_applet, size()); -+ move(popupPosition); -+ Plasma::WindowEffects::slideWindow(this, m_applet->location()); -+ m_hasCustomPosition = false; -+ } else { -+ QPoint customPosition = pos; -+ -+ if (m_applet->containment() && -+ m_applet->containment()->corona() && -+ m_notificationStack) { -+ QRect screenRect = m_applet->containment()->corona()->availableScreenRegion(m_applet->containment()->screen()).boundingRect(); -+ -+ customPosition.rx() = qMax(customPosition.x(), screenRect.left()); -+ customPosition.ry() = qMax(customPosition.y(), screenRect.top()); -+ customPosition.rx() = qMin(customPosition.x() + size().width(), screenRect.right()) - size().width(); -+ customPosition.ry() = qMin(customPosition.y() + size().height(), screenRect.bottom()) - size().height(); -+ -+ bool closerToBottom = (customPosition.ry() > (screenRect.height() / 2)); -+ if (!m_lastSize.isNull() && closerToBottom -+ && (m_lastSize.height() > size().height())) { -+ customPosition.ry() += m_lastSize.height() - size().height(); -+ } -+ m_lastSize = size(); -+ } -+ -+ move(customPosition); -+ Plasma::WindowEffects::slideWindow(this, Plasma::Desktop); -+ m_hasCustomPosition = true; -+ } -+} -+ -+void StackDialog::savePosition(const QPoint& pos) -+{ -+ if (!m_applet || !m_applet->containment()) { -+ return; -+ } -+ -+ QByteArray horizSide, vertSide; -+ QPoint pixelsToSave; -+ const QRect realScreenRect = qApp->desktop()->screenGeometry(m_applet->containment()->screen()); -+ -+ int screenRelativeX = pos.x() - realScreenRect.x(); -+ int diffWithRight = realScreenRect.width() - (screenRelativeX + size().width()); -+ if (screenRelativeX < diffWithRight) { -+ horizSide = "l"; -+ pixelsToSave.rx() = screenRelativeX; -+ } else { -+ horizSide = "r"; -+ pixelsToSave.rx() = diffWithRight; -+ } -+ -+ int screenRelativeY = pos.y() - realScreenRect.y(); -+ int diffWithBottom = realScreenRect.height() - (screenRelativeY + size().height()); -+ if (screenRelativeY < diffWithBottom) { -+ vertSide = "t"; -+ pixelsToSave.ry() = screenRelativeY; -+ } else { -+ vertSide = "b"; -+ pixelsToSave.ry() = diffWithBottom; -+ } -+ -+ kDebug() << "Affinity-v" << vertSide; -+ kDebug() << "Affinity-h" << horizSide; -+ kDebug() << "Y: " << pixelsToSave.ry(); -+ kDebug() << "X: " << pixelsToSave.rx(); -+ -+ m_applet->config().writeEntry("customPosition", pixelsToSave); -+ m_applet->config().writeEntry("customPositionAffinityHoriz", horizSide); -+ m_applet->config().writeEntry("customPositionAffinityVert", vertSide); -+} -+ -+QPoint StackDialog::adjustedSavedPos() const -+{ -+ if (!m_applet) { -+ return QPoint(-1, -1); -+ } -+ -+ QPoint pos = m_applet->config().readEntry("customPosition", QPoint(-1, -1)); -+ -+ if (pos != QPoint(-1, -1)) { -+ const QRect realScreenRect = qApp->desktop()->screenGeometry(m_applet->containment()->screen()); -+ QByteArray horizSide = m_applet->config().readEntry("customPositionAffinityHoriz").toLatin1(); -+ QByteArray vertSide = m_applet->config().readEntry("customPositionAffinityVert").toLatin1(); -+ -+ if (horizSide == "l") { -+ pos.rx() += realScreenRect.x(); -+ } else { -+ pos.rx() = realScreenRect.x() + (realScreenRect.width() - pos.rx() - size().width()); -+ } -+ -+ if (vertSide == "t") { -+ pos.ry() += realScreenRect.y(); -+ } else { -+ pos.ry() = realScreenRect.y() + (realScreenRect.height() - pos.ry() - size().height()); -+ } -+ } -+ -+ return pos; -+} -+ -+bool StackDialog::event(QEvent *event) -+{ -+ bool ret = Dialog::event(event); -+ -+ if (event->type() == QEvent::ContentsRectChange) { -+ int left, top, right, bottom; -+ getContentsMargins(&left, &top, &right, &bottom); -+ -+ m_drawLeft = (left != 0); -+ m_drawRight = (right != 0); -+ update(); -+ } -+ -+ return ret; -+} -+ -+bool StackDialog::eventFilter(QObject *watched, QEvent *event) -+{ -+ if (m_windowToTile && watched == m_windowToTile && -+ event->type() == QEvent::Show && isVisible()) { -+ adjustWindowToTilePos(); -+ } else if (watched == m_notificationStack && event->type() == QEvent::GraphicsSceneMousePress) { -+ QGraphicsSceneMouseEvent *me = static_cast(event); -+ m_dragPos = me->pos().toPoint(); -+ } else if (watched == m_notificationStack && event->type() == QEvent::GraphicsSceneMouseMove) { -+ QGraphicsSceneMouseEvent *me = static_cast(event); -+ adjustPosition(me->screenPos() - m_dragPos); -+ } else if (watched == m_notificationStack && event->type() == QEvent::GraphicsSceneMouseRelease) { -+ QGraphicsSceneMouseEvent *me = static_cast(event); -+ adjustPosition(me->screenPos() - m_dragPos); -+ savePosition(me->screenPos() - m_dragPos); -+ } -+ -+ return Plasma::Dialog::eventFilter(watched, event); -+} -+ -+#include "stackdialog.moc" -diff --git a/plasma/generic/applets/notifications/ui/stackdialog.h b/plasma/generic/applets/notifications/ui/stackdialog.h -new file mode 100644 -index 0000000..4360c4a ---- /dev/null -+++ b/plasma/generic/applets/notifications/ui/stackdialog.h -@@ -0,0 +1,99 @@ -+/*************************************************************************** -+ * stacdialog.h * -+ * Copyright (C) 2010 Marco Martin * -+ * * -+ * 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) any later version. * -+ * * -+ * 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, write to the * -+ * Free Software Foundation, Inc., * -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * -+ ***************************************************************************/ -+ -+#ifndef STACKDIALOG_H -+#define STACKDIALOG_H -+ -+#include -+ -+#include -+ -+class QPropertyAnimation; -+class QTimer; -+ -+namespace Plasma -+{ -+ class Applet; -+ class FrameSvg; -+} -+ -+class NotificationStack; -+ -+ -+class StackDialog : public Plasma::Dialog -+{ -+ Q_OBJECT -+public: -+ StackDialog(QWidget *parent = 0, Qt::WindowFlags f = Qt::Window); -+ ~StackDialog(); -+ -+ void setNotificationStack(NotificationStack *stack); -+ NotificationStack *notificartionStack() const; -+ -+ void setApplet(Plasma::Applet *applet); -+ Plasma::Applet *applet() const; -+ -+ void setWindowToTile(QWidget *widget); -+ QWidget *windowToTile() const; -+ -+ void setAutoHide(const bool autoHide); -+ bool autoHide() const; -+ -+public Q_SLOTS: -+ void perhapsShow(); -+ -+protected: -+ void adjustWindowToTilePos(); -+ -+ void paintEvent(QPaintEvent *e); -+ void showEvent(QShowEvent *event); -+ void hideEvent(QHideEvent *event); -+ void enterEvent(QEvent *event); -+ void leaveEvent(QEvent *event); -+ void resizeEvent(QResizeEvent *event); -+ void moveEvent(QMoveEvent *event); -+ bool event(QEvent *event); -+ bool eventFilter(QObject *watched, QEvent *event); -+ void adjustPosition(const QPoint &pos = QPoint(-1, -1)); -+ void savePosition(const QPoint &pos); -+ QPoint adjustedSavedPos() const; -+ -+private Q_SLOTS: -+ void hideRequested(); -+ -+private: -+ Plasma::Applet *m_applet; -+ QWidget *m_windowToTile; -+ QPropertyAnimation *m_windowToTileAnimation; -+ QPoint m_dragPos; -+ QSize m_lastSize; -+ -+ Plasma::FrameSvg *m_background; -+ NotificationStack *m_notificationStack; -+ QTimer *m_showTimer; -+ QTimer *m_hideTimer; -+ QGraphicsView *m_view; -+ bool m_drawLeft; -+ bool m_drawRight; -+ bool m_autoHide; -+ bool m_hasCustomPosition; -+}; -+ -+#endif diff --git a/kde-base/plasma-workspace/files/plasma-workspace-4.10.1-noplasmalock.patch b/kde-base/plasma-workspace/files/plasma-workspace-4.10.1-noplasmalock.patch deleted file mode 100644 index 2380d20..0000000 --- a/kde-base/plasma-workspace/files/plasma-workspace-4.10.1-noplasmalock.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/plasma/screensaver/CMakeLists.txt b/plasma/screensaver/CMakeLists.txt -index 514c856..9dcb5f4 100644 ---- a/plasma/screensaver/CMakeLists.txt -+++ b/plasma/screensaver/CMakeLists.txt -@@ -1,6 +1,3 @@ - add_subdirectory(containments) --if(NOT WIN32) --add_subdirectory(shell) --endif(NOT WIN32) - - diff --git a/kde-base/plasma-workspace/metadata.xml b/kde-base/plasma-workspace/metadata.xml deleted file mode 100644 index 3b3fc4f..0000000 --- a/kde-base/plasma-workspace/metadata.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - -kde - - Enable JSON support via dev-libs/qjson - Enable Qalculate runner using sci-libs/libqalculate - - diff --git a/kde-base/plasma-workspace/plasma-workspace-4.11.2-r2.ebuild b/kde-base/plasma-workspace/plasma-workspace-4.11.2-r2.ebuild deleted file mode 100644 index 4ed968e..0000000 --- a/kde-base/plasma-workspace/plasma-workspace-4.11.2-r2.ebuild +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 1999-2013 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: $ - -EAPI=5 - -DECLARATIVE_REQUIRED="always" -KDE_HANDBOOK="optional" -KMNAME="kde-workspace" -KMMODULE="plasma" -PYTHON_COMPAT=( python2_{6,7} ) -OPENGL_REQUIRED="always" -inherit python-single-r1 kde4-meta - -DESCRIPTION="Plasma: KDE desktop framework" -KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~x86 ~amd64-linux ~x86-linux" -IUSE="debug gps json python qalculate semantic-desktop" - -REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )" - -COMMONDEPEND=" - dev-libs/libdbusmenu-qt - >=dev-qt/qtcore-4.8.4-r3:4 - !kde-misc/ktouchpadenabler - $(add_kdebase_dep kactivities) - $(add_kdebase_dep kdelibs 'semantic-desktop?') - $(add_kdebase_dep kdepimlibs) - $(add_kdebase_dep kephal) - $(add_kdebase_dep ksysguard) - $(add_kdebase_dep libkworkspace) - $(add_kdebase_dep libplasmaclock) - $(add_kdebase_dep libplasmagenericshell) - $(add_kdebase_dep libtaskmanager) - x11-libs/libX11 - x11-libs/libXcomposite - x11-libs/libXdamage - x11-libs/libXext - x11-libs/libXfixes - x11-libs/libXi - x11-libs/libXrender - gps? ( >=sci-geosciences/gpsd-2.37 ) - json? ( dev-libs/qjson ) - python? ( - ${PYTHON_DEPS} - >=dev-python/PyQt4-4.4.0[X,${PYTHON_USEDEP}] - $(add_kdebase_dep pykde4 "${PYTHON_USEDEP}") - ) - qalculate? ( sci-libs/libqalculate ) - semantic-desktop? ( - dev-libs/soprano - $(add_kdebase_dep nepomuk-core) - ) -" -DEPEND="${COMMONDEPEND} - dev-libs/boost - x11-proto/compositeproto - x11-proto/damageproto - x11-proto/fixesproto - x11-proto/renderproto -" -RDEPEND="${COMMONDEPEND} - $(add_kdebase_dep plasma-runtime) -" - -KMEXTRA=" - appmenu/ - ktouchpadenabler/ - statusnotifierwatcher/ -" -KMEXTRACTONLY=" - kcheckpass/ - krunner/dbus/org.freedesktop.ScreenSaver.xml - krunner/dbus/org.kde.krunner.App.xml - ksmserver/org.kde.KSMServerInterface.xml - ksmserver/screenlocker/ - libs/kephal/ - libs/kworkspace/ - libs/taskmanager/ - libs/plasmagenericshell/ - libs/ksysguard/ - libs/kdm/kgreeterplugin.h - ksysguard/ -" - -KMLOADLIBS="libkworkspace libplasmaclock libplasmagenericshell libtaskmanager" - -PATCHES=( "${FILESDIR}/${PN}-4.10.1-noplasmalock.patch" "${FILESDIR}/oldnotify.patch" ) - -pkg_setup() { - if use python ; then - python-single-r1_pkg_setup - fi - kde4-meta_pkg_setup -} - -src_unpack() { - if use handbook; then - KMEXTRA+=" doc/plasma-desktop" - fi - - kde4-meta_src_unpack -} - -src_configure() { - mycmakeargs=( - $(cmake-utils_use_with gps libgps) - $(cmake-utils_use_with json QJSON) - $(cmake-utils_use_with python PythonLibrary) - $(cmake-utils_use_with qalculate) - $(cmake-utils_use_with semantic-desktop Akonadi) - $(cmake-utils_use_with semantic-desktop NepomukCore) - $(cmake-utils_use_with semantic-desktop Soprano) - -DWITH_Xmms=OFF - ) - - kde4-meta_src_configure -} - -src_install() { - kde4-meta_src_install - - if use python; then - python_optimize "${ED}" - fi -}