Merge branch 'mart/quicksettings'

This commit is contained in:
Marco Martin 2017-09-04 18:24:53 +02:00
commit 7c4bb9bac1
6 changed files with 306 additions and 293 deletions

View file

@ -29,7 +29,7 @@ MouseArea {
//actionsLayout.height*2 because the text is centered
//TODO: center the whole block not only the text
height: Math.max(messageLayout.height, icon.height) + background.margins.top + background.margins.bottom + (expanded ? actionsLayout.height*2 : 0)
height: Math.max(units.gridUnit * 3, Math.max(messageLayout.height, icon.height)) + (expanded ? actionsLayout.height*2 : 0)
width: parent.width
anchors.bottomMargin: 10
drag.axis: Drag.XAxis
@ -39,12 +39,19 @@ MouseArea {
property string source: model.source
property var actions: model.actions
opacity: 1 - Math.abs(x) / (width/2)
Behavior on x {
NumberAnimation {
easing.type: Easing.InOutQuad
duration: units.longDuration
}
}
Behavior on height {
NumberAnimation {
easing.type: Easing.InOutQuad
duration: units.longDuration
}
}
onReleased: {
if (drag.active) {
@ -66,22 +73,18 @@ MouseArea {
}
PlasmaCore.FrameSvgItem {
Rectangle {
id: background
imagePath: "widgets/background"
anchors {
fill: parent
rightMargin: -notificationItem.width
leftMargin: units.gridUnit
}
colorGroup: PlasmaCore.ColorScope.colorGroup
anchors.fill: parent
color: Qt.rgba(PlasmaCore.ColorScope.textColor.r, PlasmaCore.ColorScope.textColor.g, PlasmaCore.ColorScope.textColor.b, notificationItem.pressed ? 0.5 : 0.2)
}
PlasmaComponents.ToolButton {
id: closeButton
anchors {
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
leftMargin: units.gridUnit / 2
rightMargin: units.gridUnit
}
iconSource: "window-close"
flat: false
@ -90,52 +93,32 @@ MouseArea {
}
}
PlasmaComponents.Label {
id: appLabel
anchors.leftMargin: units.gridUnit * 3
color: PlasmaCore.ColorScope.textColor
text: model.appName
}
Column {
ColumnLayout {
id: messageLayout
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
right: icon.left
leftMargin: units.gridUnit * 3
left: icon.right
right: notificationItem.expanded ? actionsLayout.left : closeButton.left
leftMargin: units.gridUnit
rightMargin: units.gridUnit
}
PlasmaComponents.Label {
id: summaryLabel
anchors.right: parent.right
width: messageLayout.width - appLabel.width
horizontalAlignment: Qt.AlignRight
Layout.fillWidth: true
verticalAlignment: Qt.AlignVCenter
text: summary + (!notificationItem.expanded && body ? "..." : "")
wrapMode: Text.WordWrap
text: model.appName + " " + summary
elide: Text.ElideRight
}
PlasmaComponents.Label {
id: bodyLabel
anchors {
right: parent.right
left: parent.left
}
visible: height > 0
height: notificationItem.expanded && body != undefined && body ? implicitHeight : 0
clip: true
horizontalAlignment: Qt.AlignRight
Layout.fillWidth: true
visible: text.length > 0
opacity: 0.8
verticalAlignment: Qt.AlignVCenter
text: body
wrapMode: Text.WordWrap
Behavior on height {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
@ -143,21 +126,21 @@ MouseArea {
PlasmaCore.IconItem {
id: icon
anchors {
right: notificationItem.right
verticalCenter: parent.verticalCenter
}
x: units.gridUnit
width: units.iconSizes.medium
height: width
source: appIcon && appIcon.length > 0 ? appIcon : "preferences-desktop-notification"
colorGroup: PlasmaCore.ColorScope.colorGroup
}
Flow {
Column {
id: actionsLayout
anchors {
left: messageLayout.left
right: messageLayout.right
top: messageLayout.bottom
topMargin: units.smallSpacing
right: closeButton.left
rightMargin: units.gridUnit
verticalCenter: parent.verticalCenter
}
opacity: notificationItem.expanded && notificationItem.actions && notificationItem.actions.count > 0 ? 1 : 0
Behavior on opacity {
@ -177,34 +160,4 @@ MouseArea {
}
}
}
states: [
State {
name: "large"
when: appLabel.width + bodyLabel.paintedWidth < messageLayout.width
AnchorChanges {
target: appLabel
anchors {
verticalCenter: parent.verticalCenter
top: undefined
left: parent.left
}
}
PropertyChanges {
}
},
State {
name: "compact"
when: notificationItem.state != "large"
AnchorChanges {
target: appLabel
anchors {
verticalCenter: undefined
top: messageLayout.top
left: parent.left
}
}
}
]
}

View file

@ -28,9 +28,12 @@ Item {
id: root
property int notificationId: 0
Layout.minimumHeight: notificationView.contentHeight
Layout.maximumHeight: notificationView.contentHeight + units.gridUnit
//todo: size of first item
Layout.minimumHeight: units.gridUnit * 4
Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground
Plasmoid.switchWidth: 500
Plasmoid.switchHeight: 500
function addNotification(source, data, actions) {
// Do not show duplicated notifications
@ -119,28 +122,75 @@ Item {
}
PlasmaCore.FrameSvgItem {
PlasmaComponents.Label {
anchors.centerIn: parent
opacity: 0.4
visible: notificationsModel.count == 0
imagePath: "widgets/background"
width: childrenRect.width + margins.left + margins.right
height: childrenRect.height + margins.top + margins.bottom
text: i18n("No recent notifications")
}
Plasmoid.compactRepresentation: PlasmaCore.SvgItem {
id: notificationSvgItem
anchors.centerIn: parent
width: units.roundToIconSize(Math.min(parent.width, parent.height))
height: width
svg: PlasmaCore.Svg {
imagePath: "icons/notification"
colorGroup: PlasmaCore.ColorScope.colorGroup
}
elementId: {
if (notificationsModel.count > 0) {
return "notification-empty"
}
return "notification-disabled"
}
PlasmaComponents.Label {
anchors.centerIn: parent
text: i18n("No recent notifications")
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
visible: notificationsModel.count > 0
text: notificationsModel.count
}
}
ListModel {
id: notificationsModel
ListElement {
source: "call1Source"
appIcon: "call-start"
summary: "Missed call from Joe"
appName: "Phone"
body: "Called at 8:42 from +41 56 373 37 31"
actions: []
}
ListElement {
source: "im1Source"
appIcon: "im-google"
appName: "Message"
summary: "July: Hey! Are you around?"
actions: []
}
ListElement {
source: "im2Source"
appIcon: "im-google"
appName: "Message"
summary: "July: Hello?"
actions: []
}
}
ListView {
ListView {
id: notificationView
spacing: units.smallSpacing
anchors.fill: parent
spacing: units.largeSpacing
anchors {
fill: parent
leftMargin: units.largeSpacing
rightMargin: units.largeSpacing
}
interactive: false
cacheBuffer: 2000
cacheBuffer: 200000
z: 1
verticalLayoutDirection: ListView.BottomToTop

View file

@ -35,6 +35,32 @@ Item {
Layout.minimumHeight: flow.implicitHeight + units.largeSpacing*2
property int screenBrightness
readonly property int maximumScreenBrightness: pmSource.data["PowerDevil"] ? pmSource.data["PowerDevil"]["Maximum Screen Brightness"] || 0 : 0
onScreenBrightnessChanged: {
var service = pmSource.serviceForSource("PowerDevil");
var operation = service.operationDescription("setBrightness");
operation.brightness = screenBrightness;
operation.silent = true
service.startOperationCall(operation);
}
PlasmaCore.DataSource {
id: pmSource
engine: "powermanagement"
connectedSources: ["PowerDevil"]
onSourceAdded: {
if (source === "PowerDevil") {
disconnectSource(source);
connectSource(source);
}
}
onDataChanged: {
root.screenBrightness = pmSource.data["PowerDevil"]["Screen Brightness"];
}
}
ListModel {
id: settingsModel
@ -42,7 +68,7 @@ Item {
text: "Settings"
icon: "configure"
enabled: false
settingsCommand: "active-settings"
settingsCommand: "plasma-settings"
toggleFunction: ""
delegate: ""
}
@ -69,26 +95,13 @@ Item {
text: "Wireless"
icon: "network-wireless-on"
enabled: true
settingsCommand: "active-settings -m org.kde.plasma.phone.settings.wifi"
settingsCommand: "plasmawindowed org.kde.plasma.networkmanagement"
}
ListElement {
text: "Alarms"
icon: "korgac"
enabled: false
settingsCommand: ""
}
ListElement {
text: "Notifications"
icon: "preferences-desktop-notification"
enabled: true
settingsCommand: ""
}
ListElement {
text: "Brightness"
icon: "video-display-brightness"
enabled: false
settingsCommand: "active-settings -m org.kde.active.settings.powermanagement"
delegate: "BrightnessDelegate"
settingsCommand: "ktimer"
}
ListElement {
text: "Flashlight"
@ -126,5 +139,32 @@ Item {
properties: "x,y"
}
}
RowLayout {
width: flow.width
PlasmaCore.IconItem {
Layout.preferredWidth: units.iconSizes.small
Layout.preferredHeight: Layout.preferredWidth
//TODO: needs brightness
source: "contrast"
}
PlasmaComponents.Slider {
id: brightnessSlider
Layout.fillWidth: true
value: root.screenBrightness
onValueChanged: {
if (pressed) {
root.screenBrightness = value
}
}
minimumValue: maximumValue > 100 ? 1 : 0
maximumValue: root.maximumScreenBrightness
}
PlasmaCore.IconItem {
Layout.preferredWidth: units.iconSizes.small
Layout.preferredHeight: Layout.preferredWidth
//TODO: needs brightness
source: "contrast"
}
}
}
}

View file

@ -28,7 +28,7 @@ FullScreenPanel {
id: window
property int offset: 0
property int overShoot: units.gridUnit * 2
property int peekHeight
color: "transparent"
property alias contents: contentArea.data
@ -36,107 +36,124 @@ FullScreenPanel {
width: Screen.width
height: Screen.height
property alias fixedArea: fixedArea
function open() {
mouseArea.state = "open";
window.visible = true;
peekAnim.running = true;
}
function close() {
mouseArea.state = "closed";
closeAnim.running = true;
}
function updateState() {
var delta = offset - mouseArea.startOffset;
if (delta > units.gridUnit * 8) {
mouseArea.state = "open";
} else if (delta < -units.gridUnit * 8) {
mouseArea.state = "closed";
} else {
mouseArea.state = mouseArea.startState;
if (offset < peekHeight / 2) {
close();
} else if (offset < peekHeight) {
open();
} else if (mainFlickable.contentY < 0) {
openAnim.running = true;
}
mouseArea.startState = mouseArea.state;
}
onActiveChanged: {
if (!active) {
close();
}
}
onVisibleChanged: {
if (visible) {
mouseArea.state = "draggingFromClosed";
mouseArea.startOffset = units.gridUnit * 4;
window.width = Screen.width;
window.height = Screen.height;
window.requestActivate();
}
}
MouseArea {
id: mouseArea
y: 0
width: Screen.width
height: Screen.height
//clip: true
state: "closed"
drag.filterChildren: true
property int oldMouseY: 0
property int startOffset: units.iconSizes.large;
property int startMouseY: 0
property string startState: "closed"
onPressed: {
startMouseY = mouse.y;
if (startMouseY < contentArea.height - units.iconSizes.large) {
return;
}
startState = state;
startOffset = window.offset;
oldMouseY = mouse.y;
state = "draggingFromOpen";
window.offset = startOffset;
SequentialAnimation {
id: closeAnim
PropertyAnimation {
target: window
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "offset"
from: window.offset
to: 0
}
onPositionChanged: {
if (startMouseY < contentArea.height - units.iconSizes.large) {
return;
}
var factor = (mouse.y - oldMouseY > 0) ? (1 - Math.max(0, (slidingArea.y + overShoot) / overShoot)) : 1
window.offset = window.offset + (mouse.y - oldMouseY) * factor;
oldMouseY = mouse.y;
}
onReleased: {
if (startMouseY < contentArea.height - units.iconSizes.large) {
return;
}
if (Math.abs(window.offset - mouseArea.startOffset) < units.gridUnit &&
slidingArea.y + slidingArea.height < mouse.y) {
mouseArea.state = "closed";
} else {
window.updateState();
ScriptAction {
script: {
window.visible = false;
}
}
}
PropertyAnimation {
id: peekAnim
target: window
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "offset"
from: window.offset
to: window.peekHeight
}
PropertyAnimation {
id: openAnim
target: window
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "offset"
from: window.offset
to: contentArea.height
}
Rectangle {
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.6 * Math.min(1, offset/contentArea.height))
}
PlasmaCore.ColorScope {
anchors.fill: parent
y: Math.min(0, -height + window.offset)
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
Rectangle {
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.6-Math.abs(slidingArea.y/slidingArea.height))
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: contentArea.height - mainFlickable.contentY
color: PlasmaCore.ColorScope.backgroundColor
}
PlasmaCore.ColorScope {
id: slidingArea
width: parent.width
height: parent.height/1.5
y: Math.min(0, -height + window.offset)
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
Rectangle {
anchors.fill: parent
Flickable {
id: mainFlickable
anchors.fill: parent
Binding {
target: mainFlickable
property: "contentY"
value: -window.offset + contentArea.height
when: !mainFlickable.moving && !mainFlickable.dragging && !mainFlickable.flicking
}
//no loop as those 2 values compute to exactly the same
onContentYChanged: window.offset = -contentY + contentArea.height
contentWidth: window.width
contentHeight: window.height*2
bottomMargin: window.height
onMovementEnded: window.updateState();
onFlickEnded: window.updateState();
Item {
width: window.width
height: window.height*2
Item {
id: contentArea
anchors {
fill: parent
topMargin: overShoot
left: parent.left
right: parent.right
}
height: children[0].implicitHeight
}
color: PlasmaCore.ColorScope.backgroundColor
Rectangle {
height: units.gridUnit
anchors {
left: parent.left
right: parent.right
top: parent.bottom
top: contentArea.bottom
}
gradient: Gradient {
GradientStop {
@ -153,69 +170,25 @@ FullScreenPanel {
}
}
}
MouseArea {
anchors {
left: parent.left
right: parent.right
top: contentArea.bottom
}
height: window.height
onClicked: window.close();
}
}
}
//FIXME: this empty mousearea is a workaround on https://bugreports.qt.io/browse/QTBUG-46545
MouseArea {
z: -1
anchors.fill: parent
onClicked: {
if (mouseArea.startMouseY < contentArea.height - units.iconSizes.large) {
return;
}
mouseArea.state = "closed";
//window.visible = false;
Item {
id: fixedArea
anchors {
left: parent.left
right: parent.right
top: parent.top
}
height: childrenRect.height
}
states: [
State {
name: "closed"
PropertyChanges {
target: window
offset: 0
}
},
State {
name: "open"
PropertyChanges {
target: window
offset: slidingArea.height - overShoot
}
},
State {
name: "draggingFromOpen"
},
State {
name: "draggingFromClosed"
PropertyChanges {
target: window
offset: units.gridUnit * 4
}
}
]
transitions: [
Transition {
to: "draggingFromOpen"
},
Transition {
SequentialAnimation {
PropertyAnimation {
target: window
duration: units.longDuration
easing.type: Easing.InOutQuad
properties: "offset"
}
ScriptAction {
script: {
if (mouseArea.state == "closed") {
window.visible = false;
}
}
}
}
}
]
}
}

View file

@ -36,7 +36,6 @@ PlasmaCore.ColorScope {
property Item toolBox
property int buttonHeight: width/4
property bool reorderingApps: false
property QtObject expandedApplet
property var layoutManager: LayoutManager
Containment.onAppletAdded: {
@ -44,17 +43,14 @@ PlasmaCore.ColorScope {
LayoutManager.save();
}
Connections {
target: expandedApplet
onExpandedChanged: {
if (!expanded) {
slidingPanel.close();
}
}
}
function addApplet(applet, x, y) {
if (applet.pluginName == "org.kde.phone.quicksettings") {
applet.parent = quickSettingsParent;
quickSettingsParent.applet = applet;
applet.anchors.fill = quickSettingsParent;
applet.visible = true;
return;
}
var container = appletContainerComponent.createObject(appletIconsRow)
print("Applet added: " + applet + " " + applet.title)
container.width = units.iconSizes.medium
@ -65,7 +61,11 @@ PlasmaCore.ColorScope {
applet.anchors.fill = container;
applet.visible = true;
container.visible = true;
if (applet.pluginName == "org.kde.phone.notifications") {
applet.fullRepresentationItem.parent = notificationsParent;
notificationsParent.applet = applet;
applet.fullRepresentationItem.anchors.fill = notificationsParent;
}
}
Component.onCompleted: {
@ -101,23 +101,6 @@ PlasmaCore.ColorScope {
Layout.fillHeight: true
Layout.minimumWidth: applet && applet.compactRepresentationItem ? Math.max(applet.compactRepresentationItem.Layout.minimumWidth, appletIconsRow.height) : appletIconsRow.height
Layout.maximumWidth: Layout.minimumWidth
MouseArea {
anchors.fill: parent
z: 999
onClicked: {
if (root.expandedApplet != applet) {
//temp var needed for oldExpandedApplet not to catch one expandedChanged too much by our Connections
var oldExpandedApplet = root.expandedApplet;
root.expandedApplet = applet;
applet.expanded = true;
appletsStack.replace(applet.fullRepresentationItem);
if (oldExpandedApplet) {
oldExpandedApplet.expanded = false;
}
}
}
}
}
}
@ -139,10 +122,6 @@ PlasmaCore.ColorScope {
height: root.height
color: PlasmaCore.ColorScope.backgroundColor
//used as is needed somebody to filter events
MouseArea {
anchors.fill: parent
}
Loader {
id: strengthLoader
height: parent.height
@ -185,15 +164,8 @@ PlasmaCore.ColorScope {
anchors {
bottom: parent.bottom
right: parent.right
bottomMargin: slidingPanel.visible ? parent.height : 0
}
height: slidingPanel.visible ? units.iconSizes.large : parent.height
Behavior on height {
PropertyAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
height: parent.height
}
Rectangle {
@ -220,7 +192,6 @@ PlasmaCore.ColorScope {
var factor = 1;
slidingPanel.offset = slidingPanel.offset + (mouse.y - oldMouseY) * factor;
oldMouseY = mouse.y;
root.expandedApplet.expanded = true;
}
onReleased: slidingPanel.updateState();
}
@ -229,24 +200,47 @@ PlasmaCore.ColorScope {
id: slidingPanel
width: plasmoid.availableScreenRect.width
height: plasmoid.availableScreenRect.height
peekHeight: quickSettingsParent.height + notificationsParent.minimumHeight + root.height
contents: Item {
id: panelContents
anchors.fill: parent
PlasmaComponents.PageStack {
id: appletsStack
implicitHeight: quickSettingsParent.height + notificationsParent.height + root.height
Rectangle {
id: quickSettingsParent
parent: slidingPanel.fixedArea
color: PlasmaCore.ColorScope.backgroundColor
z: 2
anchors {
fill: parent
bottomMargin: units.iconSizes.large
left: parent.left
right: parent.right
}
y: Math.min(0, slidingPanel.offset - height - root.height)
property var applet
height: applet ? applet.fullRepresentationItem.Layout.minimumHeight : 0
Rectangle {
anchors {
left: parent.left
right: parent.right
bottom:parent.bottom
}
height: units.devicePixelRatio
color: PlasmaCore.ColorScope.textColor
opacity: 0.2
visible: slidingPanel.offset < panelContents.height
}
}
}
onVisibleChanged: {
if (visible && !root.expandedApplet) {
var applet = appletIconsRow.children[0].applet;
applet.expanded = true;
appletsStack.replace(applet.fullRepresentationItem);
root.expandedApplet = applet;
Item {
id: notificationsParent
anchors {
left: parent.left
bottom: parent.bottom
right: parent.right
bottomMargin: root.height
}
property var applet
height: applet ? applet.fullRepresentationItem.Layout.maximumHeight : 0
property int minimumHeight: applet ? applet.fullRepresentationItem.Layout.minimumHeight : 0
onHeightChanged: slidingPanel.updateState();
}
}
}

View file

@ -12,7 +12,8 @@ for (var j = 0; j < desktopsArray.length; j++) {
desktopsArray[0].addWidget("org.kde.plasma.analogclock");
var panel = new Panel("org.kde.phone.panel");
panel.addWidget("org.kde.plasma.notifications");
panel.addWidget("org.kde.phone.notifications");
panel.addWidget("org.kde.phone.quicksettings");
panel.addWidget("org.kde.plasma.networkmanagement");
panel.addWidget("org.kde.plasma.battery");
panel.addWidget("org.kde.plasma.volume");
@ -27,4 +28,6 @@ if (screenGeometry(bottomPanel.screen).height > screenGeometry(bottomPanel.scree
else
bottomPanel.height = 60;
createActivity("Activity 2");
if (activities().length < 2) {
createActivity("Activity 2");
}