mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
Rework top panel and improve appearance
This commit is contained in:
parent
2154671058
commit
0ed2053e79
22 changed files with 1326 additions and 1056 deletions
|
|
@ -7,12 +7,16 @@
|
|||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.4
|
||||
import QtQuick.Controls 2.4 as QQC2
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
|
||||
QQC2.Control {
|
||||
id: root
|
||||
|
||||
required property color backgroundColor
|
||||
|
||||
leftPadding: units.largeSpacing
|
||||
topPadding: units.largeSpacing
|
||||
rightPadding: units.largeSpacing
|
||||
|
|
@ -22,9 +26,15 @@ QQC2.Control {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
}
|
||||
PlasmaCore.FrameSvgItem {
|
||||
imagePath: "widgets/panel-background"
|
||||
prefix: "shadow"
|
||||
anchors.fill: container
|
||||
anchors.margins: -PlasmaCore.Units.smallSpacing
|
||||
}
|
||||
Rectangle {
|
||||
id: container
|
||||
color: Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.backgroundColor, {"alpha": 0.85*255})
|
||||
color: backgroundColor
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: PlasmaCore.Units.smallSpacing
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import QtQuick 2.12
|
|||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.12
|
||||
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
|
||||
DrawerBackground {
|
||||
|
|
@ -15,8 +16,12 @@ DrawerBackground {
|
|||
property Item applet
|
||||
property ObjectModel fullRepresentationModel
|
||||
property ListView fullRepresentationView
|
||||
|
||||
backgroundColor: (applet.backgroundHints === PlasmaCore.Types.NoBackground) ? "transparent" : Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.backgroundColor, {"alpha": 0.8*255})
|
||||
visible: shouldBeVisible
|
||||
|
||||
property bool shouldBeVisible: applet && (applet.status != PlasmaCore.Types.HiddenStatus && applet.status != PlasmaCore.Types.PassiveStatus)
|
||||
|
||||
height: parent.height
|
||||
width: visible ? quickSettings.width : 0
|
||||
Layout.minimumHeight: applet && applet.switchHeight
|
||||
|
|
|
|||
|
|
@ -20,5 +20,6 @@ FullContainer {
|
|||
id: historyModel
|
||||
showExpired: true
|
||||
showDismissed: true
|
||||
expandUnread: true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
147
containments/panel/package/contents/ui/IndicatorsRow.qml
Normal file
147
containments/panel/package/contents/ui/IndicatorsRow.qml
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQml.Models 2.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
|
||||
import org.kde.plasma.workspace.components 2.0 as PlasmaWorkspace
|
||||
import org.kde.taskmanager 0.1 as TaskManager
|
||||
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||
|
||||
import "LayoutManager.js" as LayoutManager
|
||||
|
||||
import "indicators" as Indicators
|
||||
|
||||
Item {
|
||||
id: indicatorsRow
|
||||
required property var colorGroup
|
||||
required property bool showGradientBackground
|
||||
required property bool showDropShadow
|
||||
required property color backgroundColor
|
||||
|
||||
property alias colorScopeColor: icons.backgroundColor
|
||||
property alias applets: appletIconsRow
|
||||
|
||||
PlasmaCore.DataSource {
|
||||
id: timeSource
|
||||
engine: "time"
|
||||
connectedSources: ["Local"]
|
||||
interval: 60 * 1000
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: icons
|
||||
visible: showDropShadow
|
||||
cached: true
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 1
|
||||
radius: 4.0
|
||||
samples: 17
|
||||
color: Qt.rgba(0,0,0,0.8)
|
||||
source: icons
|
||||
}
|
||||
|
||||
// screen top panel
|
||||
PlasmaCore.ColorScope {
|
||||
id: icons
|
||||
z: 1
|
||||
colorGroup: indicatorsRow.colorGroup
|
||||
anchors.fill: parent
|
||||
|
||||
// background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: backgroundColor
|
||||
}
|
||||
Rectangle {
|
||||
visible: showGradientBackground
|
||||
anchors.fill: parent
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: "transparent"
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: Qt.rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: strengthLoader
|
||||
height: parent.height
|
||||
width: item ? item.width : 0
|
||||
active: signalStrengthProvider
|
||||
sourceComponent: Indicators.SignalStrength {
|
||||
provider: signalStrengthProvider
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: statusNotifierIndicatorsRow
|
||||
anchors.left: strengthLoader.right
|
||||
height: parent.height
|
||||
Repeater {
|
||||
id: statusNotifierRepeater
|
||||
model: PlasmaCore.SortFilterModel {
|
||||
id: filteredStatusNotifiers
|
||||
filterRole: "Title"
|
||||
sourceModel: PlasmaCore.DataModel {
|
||||
dataSource: statusNotifierSource
|
||||
}
|
||||
}
|
||||
|
||||
delegate: TaskWidget {}
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: clock
|
||||
property bool is24HourTime: plasmoid.nativeInterface.isSystem24HourFormat
|
||||
|
||||
anchors.fill: parent
|
||||
text: Qt.formatTime(timeSource.data.Local.DateTime, is24HourTime ? "h:mm" : "h:mm ap")
|
||||
color: PlasmaCore.ColorScope.textColor
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
font.pixelSize: height / 2
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: appletIconsRow
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: simpleIndicatorsLayout.left
|
||||
}
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: simpleIndicatorsLayout
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
rightMargin: units.smallSpacing
|
||||
}
|
||||
Indicators.Bluetooth { provider: bluetoothProvider }
|
||||
Indicators.Wifi { provider: wifiProvider }
|
||||
Indicators.Volume { provider: volumeProvider }
|
||||
Indicators.Battery { provider: batteryProvider }
|
||||
}
|
||||
}
|
||||
}
|
||||
216
containments/panel/package/contents/ui/SlidingContainer.qml
Normal file
216
containments/panel/package/contents/ui/SlidingContainer.qml
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Marco Martin <notmart@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
NanoShell.FullScreenOverlay {
|
||||
id: window
|
||||
|
||||
property int offset: 0 // slide progress
|
||||
property int openThreshold: PlasmaCore.Units.gridUnit * 2
|
||||
property bool userInteracting: false
|
||||
property bool initiallyOpened: false // whether the panel is already open after a touch release (then don't restrict to collapsed height)
|
||||
|
||||
// height when quicksettings is fully open
|
||||
required property int fullyOpenHeight
|
||||
|
||||
// flickable contentY
|
||||
readonly property int openedContentY: wideScreen || offset > (collapsedHeight + openThreshold) ? -topEmptyAreaHeight : offsetToContentY(collapsedHeight)
|
||||
readonly property int closedContentY: mainFlickable.contentHeight
|
||||
|
||||
readonly property bool wideScreen: width > height || width > units.gridUnit * 45
|
||||
readonly property int drawerWidth: wideScreen ? contentItem.implicitWidth : width
|
||||
|
||||
property int drawerX: 0
|
||||
property alias fixedArea: mainScope
|
||||
property alias flickable: mainFlickable
|
||||
|
||||
color: "transparent"
|
||||
property alias contentItem: contentArea.contentItem
|
||||
property int topPanelHeight
|
||||
property int collapsedHeight
|
||||
property real topEmptyAreaHeight
|
||||
|
||||
property bool appletsShown: false // whether notifications or media player applets are shown
|
||||
|
||||
signal closed
|
||||
|
||||
width: Screen.width
|
||||
height: Screen.height
|
||||
|
||||
onInitiallyOpenedChanged: {
|
||||
if (initiallyOpened) mainFlickable.focus = true;
|
||||
}
|
||||
|
||||
function offsetToContentY(num) { return -num + window.fullyOpenHeight; }
|
||||
function contentYToOffset(num) { return offsetToContentY(num); }
|
||||
|
||||
// avoids binding loops
|
||||
function updateOffset(delta) {
|
||||
// only go to collapsed height for mousearea when not widescreen
|
||||
let maximum = window.wideScreen ? window.fullyOpenHeight : collapsedHeight + openThreshold / 2;
|
||||
offset = Math.max(0, Math.min(maximum, offset + delta));
|
||||
if (!mainFlickable.moving && !mainFlickable.dragging && !mainFlickable.flicking) {
|
||||
mainFlickable.contentY = offsetToContentY(window.offset);
|
||||
}
|
||||
}
|
||||
|
||||
enum MovementDirection {
|
||||
None = 0,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
property int direction: SlidingContainer.MovementDirection.None
|
||||
|
||||
function cancelAnimations() {
|
||||
closeAnim.stop();
|
||||
openAnim.stop();
|
||||
}
|
||||
function open() {
|
||||
cancelAnimations();
|
||||
openAnim.restart();
|
||||
initiallyOpened = true;
|
||||
}
|
||||
function close() {
|
||||
cancelAnimations();
|
||||
closeAnim.restart();
|
||||
initiallyOpened = false;
|
||||
}
|
||||
function updateState() {
|
||||
cancelAnimations();
|
||||
if (window.offset <= 0) {
|
||||
// close immediately, so that we don't have to wait units.longDuration
|
||||
window.visible = false;
|
||||
window.closed();
|
||||
close();
|
||||
} else if (window.direction === SlidingContainer.MovementDirection.None) {
|
||||
if (window.offset < openThreshold) {
|
||||
close();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
} else if (offset > openThreshold && window.direction === SlidingContainer.MovementDirection.Down) {
|
||||
open();
|
||||
} else if (mainFlickable.contentY > openThreshold) {
|
||||
close();
|
||||
} else {
|
||||
open();
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: updateStateTimer
|
||||
interval: 0
|
||||
onTriggered: updateState()
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
PropertyAnimation {
|
||||
id: closeAnim
|
||||
target: mainFlickable
|
||||
properties: "contentY"
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
to: window.closedContentY
|
||||
onFinished: {
|
||||
window.visible = false;
|
||||
window.closed();
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
id: openAnim
|
||||
target: mainFlickable
|
||||
properties: "contentY"
|
||||
duration: PlasmaCore.Units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
to: window.openedContentY
|
||||
}
|
||||
|
||||
// fullscreen background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.75)
|
||||
opacity: (appletsShown ? 0.85 : 0.6) * Math.max(0, Math.min(1, offset / window.collapsedHeight))
|
||||
Behavior on opacity { // smooth opacity changes
|
||||
NumberAnimation { duration: 70 }
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaCore.ColorScope {
|
||||
id: mainScope
|
||||
colorGroup: PlasmaCore.Theme.ViewColorGroup
|
||||
anchors.fill: parent
|
||||
|
||||
Flickable {
|
||||
id: mainFlickable
|
||||
anchors.fill: parent
|
||||
|
||||
property real oldContentY
|
||||
contentY: contentHeight
|
||||
|
||||
onContentYChanged: {
|
||||
if (contentY === oldContentY) {
|
||||
window.direction = SlidingContainer.MovementDirection.None;
|
||||
} else {
|
||||
window.direction = contentY > oldContentY ? SlidingContainer.MovementDirection.Up : SlidingContainer.MovementDirection.Down;
|
||||
}
|
||||
window.offset = contentYToOffset(contentY);
|
||||
oldContentY = contentY;
|
||||
|
||||
// close panel immediately after panel is not shown, and the flickable is not being dragged
|
||||
if (initiallyOpened && window.offset <= 0 && !mainFlickable.dragging && !closeAnim.running && !openAnim.running) {
|
||||
window.updateState();
|
||||
focus = false;
|
||||
}
|
||||
}
|
||||
|
||||
boundsMovement: Flickable.StopAtBounds
|
||||
contentWidth: window.width
|
||||
contentHeight: window.height
|
||||
bottomMargin: window.height
|
||||
onMovementStarted: {
|
||||
window.cancelAnimations();
|
||||
window.userInteracting = true;
|
||||
}
|
||||
onFlickStarted: window.userInteracting = true;
|
||||
onMovementEnded: {
|
||||
window.userInteracting = false;
|
||||
window.updateState();
|
||||
}
|
||||
onFlickEnded: {
|
||||
window.userInteracting = true;
|
||||
window.updateState();
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: dismissArea
|
||||
z: 2
|
||||
width: parent.width
|
||||
height: mainFlickable.contentHeight
|
||||
onClicked: window.close();
|
||||
|
||||
// actual sliding contents
|
||||
PlasmaComponents.Control {
|
||||
id: contentArea
|
||||
z: 1
|
||||
x: drawerX
|
||||
width: drawerWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
NanoShell.FullScreenOverlay {
|
||||
id: window
|
||||
|
||||
property int offset: 0
|
||||
property int openThreshold
|
||||
property bool userInteracting: false
|
||||
readonly property bool wideScreen: width > height || width > units.gridUnit * 45
|
||||
readonly property int drawerWidth: wideScreen ? contentItem.implicitWidth : width
|
||||
property int drawerX: 0
|
||||
property alias fixedArea: mainScope
|
||||
property alias flickable: mainFlickable
|
||||
|
||||
color: "transparent"
|
||||
property alias contentItem: contentArea.contentItem
|
||||
property int headerHeight
|
||||
property real topEmptyAreaHeight
|
||||
|
||||
signal closed
|
||||
|
||||
width: Screen.width
|
||||
height: Screen.height
|
||||
|
||||
enum MovementDirection {
|
||||
None = 0,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
property int direction: SlidingPanel.MovementDirection.None
|
||||
|
||||
function cancelAnimations() {
|
||||
closeAnim.stop();
|
||||
openAnim.stop();
|
||||
}
|
||||
function open() {
|
||||
cancelAnimations();
|
||||
window.showFullScreen();
|
||||
openAnim.restart();
|
||||
}
|
||||
function close() {
|
||||
cancelAnimations();
|
||||
closeAnim.restart();
|
||||
}
|
||||
function updateState() {
|
||||
cancelAnimations();
|
||||
if (window.offset <= -headerHeight) {
|
||||
// close immediately, so that we don't have to wait units.longDuration
|
||||
window.visible = false;
|
||||
window.closed();
|
||||
} else if (window.direction === SlidingPanel.MovementDirection.None) {
|
||||
if (offset < openThreshold) {
|
||||
close();
|
||||
} else {
|
||||
openAnim.restart();
|
||||
}
|
||||
} else if (offset > openThreshold && window.direction === SlidingPanel.MovementDirection.Down) {
|
||||
openAnim.restart();
|
||||
} else if (mainFlickable.contentY > openThreshold) {
|
||||
close();
|
||||
} else {
|
||||
openAnim.restart();
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: updateStateTimer
|
||||
interval: 0
|
||||
onTriggered: updateState()
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
if (!active) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
/*onVisibleChanged: {
|
||||
if (visible) {
|
||||
window.width = Screen.width;
|
||||
window.height = Screen.height;
|
||||
window.requestActivate();
|
||||
}
|
||||
}*/
|
||||
|
||||
SequentialAnimation {
|
||||
id: closeAnim
|
||||
PropertyAnimation {
|
||||
target: window
|
||||
duration: units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
properties: "offset"
|
||||
from: window.offset
|
||||
to: -headerHeight
|
||||
}
|
||||
ScriptAction {
|
||||
script: {
|
||||
window.visible = false;
|
||||
window.closed();
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
id: openAnim
|
||||
target: window
|
||||
duration: units.longDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
properties: "offset"
|
||||
from: window.offset
|
||||
to: contentArea.height - topEmptyAreaHeight
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: parent.height - headerHeight // don't layer on top panel indicators (area is darkened separately)
|
||||
color: "black"
|
||||
opacity: 0.6 * Math.min(1, offset/contentArea.height)
|
||||
|
||||
Rectangle {
|
||||
height: headerHeight
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.top
|
||||
}
|
||||
color: "black"
|
||||
opacity: 0.2
|
||||
}
|
||||
Rectangle {
|
||||
height: units.smallSpacing
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: Qt.rgba(0, 0, 0, 0.0)
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.5
|
||||
color: Qt.rgba(0, 0, 0, 0.4)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PlasmaCore.ColorScope {
|
||||
id: mainScope
|
||||
anchors.fill: parent
|
||||
|
||||
Flickable {
|
||||
id: mainFlickable
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: headerHeight
|
||||
}
|
||||
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: {
|
||||
if (contentY === oldContentY) {
|
||||
window.direction = SlidingPanel.MovementDirection.None;
|
||||
} else {
|
||||
window.direction = contentY > oldContentY ? SlidingPanel.MovementDirection.Up : SlidingPanel.MovementDirection.Down;
|
||||
}
|
||||
window.offset = -contentY + contentArea.height
|
||||
oldContentY = contentY;
|
||||
}
|
||||
property real oldContentY
|
||||
boundsMovement: Flickable.StopAtBounds
|
||||
contentWidth: window.width
|
||||
contentHeight: window.height*2 - headerHeight*2
|
||||
bottomMargin: window.height
|
||||
onMovementStarted: {
|
||||
window.cancelAnimations();
|
||||
window.userInteracting = true;
|
||||
}
|
||||
onFlickStarted: window.userInteracting = true;
|
||||
onMovementEnded: {
|
||||
window.userInteracting = false;
|
||||
window.updateState();
|
||||
}
|
||||
onFlickEnded: {
|
||||
window.userInteracting = true;
|
||||
window.updateState();
|
||||
}
|
||||
MouseArea {
|
||||
id: dismissArea
|
||||
z: 2
|
||||
width: parent.width
|
||||
height: mainFlickable.contentHeight
|
||||
onClicked: window.close();
|
||||
PlasmaComponents.Control {
|
||||
id: contentArea
|
||||
z: 1
|
||||
y: 0
|
||||
x: drawerX
|
||||
width: drawerWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
@ -11,31 +12,27 @@ import org.kde.plasma.core 2.0 as PlasmaCore
|
|||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.workspace.components 2.0 as PW
|
||||
|
||||
import "providers"
|
||||
|
||||
RowLayout {
|
||||
visible: pmSource.data["Battery"]["Has Cumulative"]
|
||||
required property BatteryProvider provider
|
||||
visible: provider.isVisible
|
||||
|
||||
PW.BatteryIcon {
|
||||
id: battery
|
||||
Layout.preferredWidth: height
|
||||
Layout.fillHeight: true
|
||||
hasBattery: true
|
||||
percent: pmSource.data["Battery"]["Percent"]
|
||||
pluggedIn: pmSource.data["AC Adapter"] ? pmSource.data["AC Adapter"]["Plugged in"] : false
|
||||
percent: provider.percent
|
||||
pluggedIn: provider.pluggedIn
|
||||
|
||||
height: batteryLabel.height
|
||||
width: batteryLabel.height
|
||||
|
||||
PlasmaCore.DataSource {
|
||||
id: pmSource
|
||||
engine: "powermanagement"
|
||||
connectedSources: ["Battery", "AC Adapter"]
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: batteryLabel
|
||||
text: i18n("%1%", battery.percent)
|
||||
text: i18n("%1%", provider.percent)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
color: PlasmaCore.ColorScope.textColor
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com
|
||||
SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2013-2017 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
|
|
@ -11,38 +12,17 @@ import org.kde.plasma.core 2.0 as PlasmaCore
|
|||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.bluezqt 1.0 as BluezQt
|
||||
|
||||
import "providers"
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: connectionIcon
|
||||
required property BluetoothProvider provider
|
||||
|
||||
property bool deviceConnected : false
|
||||
|
||||
source: deviceConnected ? "preferences-system-bluetooth-activated" : "preferences-system-bluetooth";
|
||||
source: provider.icon;
|
||||
colorGroup: PlasmaCore.ColorScope.colorGroup
|
||||
|
||||
visible: BluezQt.Manager.bluetoothOperational
|
||||
visible: provider.isVisible
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
function updateStatus()
|
||||
{
|
||||
var connectedDevices = [];
|
||||
|
||||
for (var i = 0; i < BluezQt.Manager.devices.length; ++i) {
|
||||
var device = BluezQt.Manager.devices[i];
|
||||
if (device.connected) {
|
||||
connectedDevices.push(device);
|
||||
}
|
||||
}
|
||||
deviceConnected = connectedDevices.length > 0;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
BluezQt.Manager.deviceAdded.connect(updateStatus);
|
||||
BluezQt.Manager.deviceRemoved.connect(updateStatus);
|
||||
BluezQt.Manager.deviceChanged.connect(updateStatus);
|
||||
BluezQt.Manager.bluetoothBlockedChanged.connect(updateStatus);
|
||||
BluezQt.Manager.bluetoothOperationalChanged.connect(updateStatus);
|
||||
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
@ -7,34 +8,19 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import MeeGo.QOfono 0.2
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
|
||||
import "providers"
|
||||
|
||||
Item {
|
||||
// we can't use SignalStrengthProvider as the var type as it would import ofono (which may cause it to break if ofono is not installed)
|
||||
required property QtObject provider
|
||||
|
||||
width: strengthIcon.height + strengthLabel.width
|
||||
Layout.minimumWidth: strengthIcon.height + strengthLabel.width
|
||||
|
||||
OfonoManager {
|
||||
id: ofonoManager
|
||||
}
|
||||
|
||||
OfonoNetworkRegistration {
|
||||
id: netreg
|
||||
Component.onCompleted: {
|
||||
netreg.scan()
|
||||
}
|
||||
|
||||
modemPath: ofonoManager.modems.length ? ofonoManager.modems[0] : ""
|
||||
}
|
||||
|
||||
OfonoSimManager {
|
||||
id: simManager
|
||||
modemPath: ofonoManager.modems.length ? ofonoManager.modems[0] : ""
|
||||
}
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: strengthIcon
|
||||
colorGroup: PlasmaCore.ColorScope.colorGroup
|
||||
|
|
@ -43,12 +29,7 @@ Item {
|
|||
width: height
|
||||
height: parent.height
|
||||
|
||||
source: netreg.strength == 100 ? "network-mobile-100"
|
||||
: netreg.strength >= 80 ? "network-mobile-80"
|
||||
: netreg.strength >= 60 ? "network-mobile-60"
|
||||
: netreg.strength >= 40 ? "network-mobile-40"
|
||||
: netreg.strength >= 20 ? "network-mobile-20"
|
||||
: "network-mobile-0"
|
||||
source: provider.icon
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
|
|
@ -56,7 +37,7 @@ Item {
|
|||
anchors.left: strengthIcon.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: simManager.pinRequired !== OfonoSimManager.NoPin ? i18n("Sim locked") : netreg.name
|
||||
text: provider.label
|
||||
color: PlasmaCore.ColorScope.textColor
|
||||
font.pixelSize: parent.height / 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <eespidev@gmail.com>
|
||||
SPDX-FileCopyrightText: 2019 Aditya Mehra <Aix.m@outlook.com>
|
||||
SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org>
|
||||
|
||||
|
|
@ -11,152 +12,17 @@ import org.kde.plasma.core 2.0 as PlasmaCore
|
|||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.volume 0.1
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
import "providers"
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: paIcon
|
||||
required property VolumeProvider provider
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
property bool volumeFeedback: true
|
||||
property int maxVolumeValue: Math.round(100 * PulseAudio.NormalVolume / 100.0)
|
||||
property int volumeStep: Math.round(5 * PulseAudio.NormalVolume / 100.0)
|
||||
readonly property string dummyOutputName: "auto_null"
|
||||
source: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink)
|
||||
? iconName(paSinkModel.preferredSink.volume, paSinkModel.preferredSink.muted)
|
||||
: iconName(0, true)
|
||||
source: provider.icon
|
||||
|
||||
colorGroup: PlasmaCore.ColorScope.colorGroup
|
||||
|
||||
visible: paSinkModel.preferredSink && paSinkModel.preferredSink.muted
|
||||
|
||||
function iconName(volume, muted, prefix) {
|
||||
if (!prefix) {
|
||||
prefix = "audio-volume";
|
||||
}
|
||||
var icon = null;
|
||||
var percent = volume / maxVolumeValue;
|
||||
if (percent <= 0.0 || muted) {
|
||||
icon = prefix + "-muted";
|
||||
} else if (percent <= 0.25) {
|
||||
icon = prefix + "-low";
|
||||
} else if (percent <= 0.75) {
|
||||
icon = prefix + "-medium";
|
||||
} else {
|
||||
icon = prefix + "-high";
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
function isDummyOutput(output) {
|
||||
return output && output.name === dummyOutputName;
|
||||
}
|
||||
|
||||
function boundVolume(volume) {
|
||||
return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue));
|
||||
}
|
||||
|
||||
function volumePercent(volume, max){
|
||||
if(!max) {
|
||||
max = PulseAudio.NormalVolume;
|
||||
}
|
||||
return Math.round(volume / max * 100.0);
|
||||
}
|
||||
|
||||
function playFeedback(sinkIndex) {
|
||||
if(!volumeFeedback){
|
||||
return;
|
||||
}
|
||||
if(sinkIndex == undefined) {
|
||||
sinkIndex = paSinkModel.preferredSink.index;
|
||||
}
|
||||
feedback.play(sinkIndex)
|
||||
}
|
||||
|
||||
function increaseVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var volume = boundVolume(paSinkModel.preferredSink.volume + volumeStep);
|
||||
var percent = volumePercent(volume, maxVolumeValue);
|
||||
paSinkModel.preferredSink.muted = percent == 0;
|
||||
paSinkModel.preferredSink.volume = volume;
|
||||
osd.show(percent);
|
||||
playFeedback();
|
||||
|
||||
}
|
||||
|
||||
function decreaseVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var volume = boundVolume(paSinkModel.preferredSink.volume - volumeStep);
|
||||
var percent = volumePercent(volume, maxVolumeValue);
|
||||
paSinkModel.preferredSink.muted = percent == 0;
|
||||
paSinkModel.preferredSink.volume = volume;
|
||||
osd.show(percent);
|
||||
playFeedback();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function muteVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var toMute = !paSinkModel.preferredSink.muted;
|
||||
paSinkModel.preferredSink.muted = toMute;
|
||||
osd.show(toMute ? 0 : volumePercent(paSinkModel.preferredSink.volume, maxVolumeValue));
|
||||
if (!toMute) {
|
||||
playFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
SinkModel {
|
||||
id: paSinkModel
|
||||
}
|
||||
|
||||
VolumeOSD {
|
||||
id: osd
|
||||
}
|
||||
|
||||
VolumeFeedback {
|
||||
id: feedback
|
||||
}
|
||||
|
||||
GlobalActionCollection {
|
||||
// KGlobalAccel cannot transition from kmix to something else, so if
|
||||
// the user had a custom shortcut set for kmix those would get lost.
|
||||
// To avoid this we hijack kmix name and actions. Entirely mental but
|
||||
// best we can do to not cause annoyance for the user.
|
||||
// The display name actually is updated to whatever registered last
|
||||
// though, so as far as user visible strings go we should be fine.
|
||||
// As of 2015-07-21:
|
||||
// componentName: kmix
|
||||
// actions: increase_volume, decrease_volume, mute
|
||||
name: "kmix"
|
||||
displayName: i18n("Audio")
|
||||
|
||||
GlobalAction {
|
||||
objectName: "increase_volume"
|
||||
text: i18n("Increase Volume")
|
||||
shortcut: Qt.Key_VolumeUp
|
||||
onTriggered: increaseVolume()
|
||||
}
|
||||
|
||||
GlobalAction {
|
||||
objectName: "decrease_volume"
|
||||
text: i18n("Decrease Volume")
|
||||
shortcut: Qt.Key_VolumeDown
|
||||
onTriggered: decreaseVolume()
|
||||
}
|
||||
|
||||
GlobalAction {
|
||||
objectName: "mute"
|
||||
text: i18n("Mute")
|
||||
shortcut: Qt.Key_VolumeMute
|
||||
onTriggered: muteVolume()
|
||||
}
|
||||
}
|
||||
visible: provider.isVisible
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2013-2017 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
|
|
@ -11,10 +12,13 @@ import org.kde.plasma.core 2.0 as PlasmaCore
|
|||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
|
||||
|
||||
import "providers"
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: connectionIcon
|
||||
required property WifiProvider provider
|
||||
|
||||
source: connectionIconProvider.connectionIcon
|
||||
source: provider.icon
|
||||
colorGroup: PlasmaCore.ColorScope.colorGroup
|
||||
|
||||
Layout.fillHeight: true
|
||||
|
|
@ -24,23 +28,7 @@ PlasmaCore.IconItem {
|
|||
id: connectingIndicator
|
||||
|
||||
anchors.fill: parent
|
||||
running: connectionIconProvider.connecting
|
||||
running: provider.indicatorRunning
|
||||
visible: running
|
||||
}
|
||||
|
||||
PlasmaNM.NetworkStatus {
|
||||
id: networkStatus
|
||||
}
|
||||
|
||||
PlasmaNM.NetworkModel {
|
||||
id: connectionModel
|
||||
}
|
||||
|
||||
PlasmaNM.Handler {
|
||||
id: handler
|
||||
}
|
||||
|
||||
PlasmaNM.ConnectionIcon {
|
||||
id: connectionIconProvider
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.4
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
import org.kde.plasma.workspace.components 2.0 as PW
|
||||
|
||||
Item {
|
||||
property bool isVisible: pmSource.data["Battery"]["Has Cumulative"]
|
||||
property int percent: pmSource.data["Battery"]["Percent"]
|
||||
property bool pluggedIn: pmSource.data["AC Adapter"] ? pmSource.data["AC Adapter"]["Plugged in"] : false
|
||||
|
||||
property PlasmaCore.DataSource pmSource: PlasmaCore.DataSource {
|
||||
engine: "powermanagement"
|
||||
connectedSources: ["Battery", "AC Adapter"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2013-2017 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.bluezqt 1.0 as BluezQt
|
||||
|
||||
QtObject {
|
||||
property bool isVisible: BluezQt.Manager.bluetoothOperational
|
||||
property string icon: deviceConnected ? "preferences-system-bluetooth-activated" : "preferences-system-bluetooth"
|
||||
|
||||
property bool deviceConnected : false
|
||||
|
||||
function updateStatus() {
|
||||
var connectedDevices = [];
|
||||
|
||||
for (var i = 0; i < BluezQt.Manager.devices.length; ++i) {
|
||||
var device = BluezQt.Manager.devices[i];
|
||||
if (device.connected) {
|
||||
connectedDevices.push(device);
|
||||
}
|
||||
}
|
||||
deviceConnected = connectedDevices.length > 0;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
BluezQt.Manager.deviceAdded.connect(updateStatus);
|
||||
BluezQt.Manager.deviceRemoved.connect(updateStatus);
|
||||
BluezQt.Manager.deviceChanged.connect(updateStatus);
|
||||
BluezQt.Manager.bluetoothBlockedChanged.connect(updateStatus);
|
||||
BluezQt.Manager.bluetoothOperationalChanged.connect(updateStatus);
|
||||
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import MeeGo.QOfono 0.2
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
|
||||
QtObject {
|
||||
property string icon: netreg.strength == 100 ? "network-mobile-100"
|
||||
: netreg.strength >= 80 ? "network-mobile-80"
|
||||
: netreg.strength >= 60 ? "network-mobile-60"
|
||||
: netreg.strength >= 40 ? "network-mobile-40"
|
||||
: netreg.strength >= 20 ? "network-mobile-20"
|
||||
: "network-mobile-0"
|
||||
|
||||
property string label: simManager.pinRequired !== OfonoSimManager.NoPin ? i18n("Sim locked") : netreg.name
|
||||
|
||||
property OfonoManager ofonoManager: OfonoManager {}
|
||||
|
||||
property OfonoNetworkRegistration netreg: OfonoNetworkRegistration {
|
||||
Component.onCompleted: {
|
||||
netreg.scan()
|
||||
}
|
||||
|
||||
modemPath: ofonoManager.modems.length ? ofonoManager.modems[0] : ""
|
||||
}
|
||||
|
||||
property OfonoSimManager simManager: OfonoSimManager {
|
||||
modemPath: ofonoManager.modems.length ? ofonoManager.modems[0] : ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
SPDX-FileCopyrightText: 2019 Aditya Mehra <Aix.m@outlook.com>
|
||||
SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.private.volume 0.1
|
||||
|
||||
QtObject {
|
||||
property bool isVisible: paSinkModel.preferredSink && paSinkModel.preferredSink.muted
|
||||
property string icon: paSinkModel.preferredSink && !isDummyOutput(paSinkModel.preferredSink)
|
||||
? iconName(paSinkModel.preferredSink.volume, paSinkModel.preferredSink.muted)
|
||||
: iconName(0, true)
|
||||
|
||||
property bool volumeFeedback: true
|
||||
property int maxVolumeValue: Math.round(100 * PulseAudio.NormalVolume / 100.0)
|
||||
property int volumeStep: Math.round(5 * PulseAudio.NormalVolume / 100.0)
|
||||
readonly property string dummyOutputName: "auto_null"
|
||||
|
||||
function iconName(volume, muted, prefix) {
|
||||
if (!prefix) {
|
||||
prefix = "audio-volume";
|
||||
}
|
||||
var icon = null;
|
||||
var percent = volume / maxVolumeValue;
|
||||
if (percent <= 0.0 || muted) {
|
||||
icon = prefix + "-muted";
|
||||
} else if (percent <= 0.25) {
|
||||
icon = prefix + "-low";
|
||||
} else if (percent <= 0.75) {
|
||||
icon = prefix + "-medium";
|
||||
} else {
|
||||
icon = prefix + "-high";
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
function isDummyOutput(output) {
|
||||
return output && output.name === dummyOutputName;
|
||||
}
|
||||
|
||||
function boundVolume(volume) {
|
||||
return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue));
|
||||
}
|
||||
|
||||
function volumePercent(volume, max){
|
||||
if(!max) {
|
||||
max = PulseAudio.NormalVolume;
|
||||
}
|
||||
return Math.round(volume / max * 100.0);
|
||||
}
|
||||
|
||||
function playFeedback(sinkIndex) {
|
||||
if(!volumeFeedback){
|
||||
return;
|
||||
}
|
||||
if(sinkIndex == undefined) {
|
||||
sinkIndex = paSinkModel.preferredSink.index;
|
||||
}
|
||||
feedback.play(sinkIndex)
|
||||
}
|
||||
|
||||
function increaseVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var volume = boundVolume(paSinkModel.preferredSink.volume + volumeStep);
|
||||
var percent = volumePercent(volume, maxVolumeValue);
|
||||
paSinkModel.preferredSink.muted = percent == 0;
|
||||
paSinkModel.preferredSink.volume = volume;
|
||||
osd.show(percent);
|
||||
playFeedback();
|
||||
|
||||
}
|
||||
|
||||
function decreaseVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var volume = boundVolume(paSinkModel.preferredSink.volume - volumeStep);
|
||||
var percent = volumePercent(volume, maxVolumeValue);
|
||||
paSinkModel.preferredSink.muted = percent == 0;
|
||||
paSinkModel.preferredSink.volume = volume;
|
||||
osd.show(percent);
|
||||
playFeedback();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function muteVolume() {
|
||||
if (!paSinkModel.preferredSink || isDummyOutput(paSinkModel.preferredSink)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var toMute = !paSinkModel.preferredSink.muted;
|
||||
paSinkModel.preferredSink.muted = toMute;
|
||||
osd.show(toMute ? 0 : volumePercent(paSinkModel.preferredSink.volume, maxVolumeValue));
|
||||
if (!toMute) {
|
||||
playFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
property SinkModel paSinkModel: SinkModel {}
|
||||
|
||||
property VolumeOSD osd: VolumeOSD {}
|
||||
|
||||
property VolumeFeedback feedback: VolumeFeedback {}
|
||||
|
||||
property GlobalActionCollection actionCollection: GlobalActionCollection {
|
||||
// KGlobalAccel cannot transition from kmix to something else, so if
|
||||
// the user had a custom shortcut set for kmix those would get lost.
|
||||
// To avoid this we hijack kmix name and actions. Entirely mental but
|
||||
// best we can do to not cause annoyance for the user.
|
||||
// The display name actually is updated to whatever registered last
|
||||
// though, so as far as user visible strings go we should be fine.
|
||||
// As of 2015-07-21:
|
||||
// componentName: kmix
|
||||
// actions: increase_volume, decrease_volume, mute
|
||||
name: "kmix"
|
||||
displayName: i18n("Audio")
|
||||
|
||||
GlobalAction {
|
||||
objectName: "increase_volume"
|
||||
text: i18n("Increase Volume")
|
||||
shortcut: Qt.Key_VolumeUp
|
||||
onTriggered: increaseVolume()
|
||||
}
|
||||
|
||||
GlobalAction {
|
||||
objectName: "decrease_volume"
|
||||
text: i18n("Decrease Volume")
|
||||
shortcut: Qt.Key_VolumeDown
|
||||
onTriggered: decreaseVolume()
|
||||
}
|
||||
|
||||
GlobalAction {
|
||||
objectName: "mute"
|
||||
text: i18n("Mute")
|
||||
shortcut: Qt.Key_VolumeMute
|
||||
onTriggered: muteVolume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||
SPDX-FileCopyrightText: 2013-2017 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
|
||||
|
||||
Item {
|
||||
visible: false
|
||||
property string icon: connectionIconProvider.connectionIcon
|
||||
property bool indicatorRunning: connectionIconProvider.connecting
|
||||
|
||||
PlasmaNM.NetworkStatus {
|
||||
id: networkStatus
|
||||
}
|
||||
|
||||
PlasmaNM.NetworkModel {
|
||||
id: connectionModel
|
||||
}
|
||||
|
||||
PlasmaNM.Handler {
|
||||
id: handler
|
||||
}
|
||||
|
||||
PlasmaNM.ConnectionIcon {
|
||||
id: connectionIconProvider
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
@ -9,6 +10,8 @@ import QtQuick.Layouts 1.3
|
|||
import QtQml.Models 2.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
|
||||
import org.kde.plasma.plasmoid 2.0
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||
|
|
@ -23,7 +26,7 @@ import "LayoutManager.js" as LayoutManager
|
|||
|
||||
import "quicksettings"
|
||||
import "indicators" as Indicators
|
||||
|
||||
import "indicators/providers" as IndicatorProviders
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
@ -37,7 +40,7 @@ Item {
|
|||
property bool reorderingApps: false
|
||||
property var layoutManager: LayoutManager
|
||||
|
||||
readonly property color backgroundColor: NanoShell.StartupFeedback.visible ? NanoShell.StartupFeedback.backgroundColor : icons.backgroundColor
|
||||
readonly property color backgroundColor: NanoShell.StartupFeedback.visible ? NanoShell.StartupFeedback.backgroundColor : topPanel.colorScopeColor
|
||||
readonly property bool showingApp: !MobileShell.HomeScreenControls.homeScreenVisible
|
||||
|
||||
readonly property bool hasTasks: tasksModel.count > 0
|
||||
|
|
@ -48,7 +51,7 @@ Item {
|
|||
}
|
||||
|
||||
function addApplet(applet, x, y) {
|
||||
var compactContainer = compactContainerComponent.createObject(appletIconsRow)
|
||||
var compactContainer = compactContainerComponent.createObject(topPanel.applets)
|
||||
print("Applet added: " + applet + " " + applet.title)
|
||||
|
||||
applet.parent = compactContainer;
|
||||
|
|
@ -115,138 +118,59 @@ Item {
|
|||
property Item applet
|
||||
visible: applet && (applet.status != PlasmaCore.Types.HiddenStatus && applet.status != PlasmaCore.Types.PassiveStatus)
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: applet && applet.compactRepresentationItem ? Math.max(applet.compactRepresentationItem.Layout.minimumWidth, appletIconsRow.height) : appletIconsRow.height
|
||||
Layout.minimumWidth: applet && applet.compactRepresentationItem ? Math.max(applet.compactRepresentationItem.Layout.minimumWidth, topPanel.applets.height) : topPanel.applets.height
|
||||
Layout.maximumWidth: Layout.minimumWidth
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fullContainerComponent
|
||||
FullContainer {
|
||||
}
|
||||
FullContainer {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fullNotificationsContainerComponent
|
||||
FullNotificationsContainer {
|
||||
}
|
||||
FullNotificationsContainer {}
|
||||
}
|
||||
|
||||
PlasmaCore.DataSource {
|
||||
id: timeSource
|
||||
engine: "time"
|
||||
connectedSources: ["Local"]
|
||||
interval: 60 * 1000
|
||||
// indicator providers
|
||||
IndicatorProviders.BatteryProvider {
|
||||
id: batteryProvider
|
||||
}
|
||||
IndicatorProviders.BluetoothProvider {
|
||||
id: bluetoothProvider
|
||||
}
|
||||
property alias signalStrengthProvider: signalStrengthProviderLoader.item
|
||||
Loader {
|
||||
id: signalStrengthProviderLoader
|
||||
source: Qt.resolvedUrl("indicators/providers/SignalStrengthProvider.qml")
|
||||
}
|
||||
IndicatorProviders.VolumeProvider {
|
||||
id: volumeProvider
|
||||
}
|
||||
IndicatorProviders.WifiProvider {
|
||||
id: wifiProvider
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: icons
|
||||
visible: !showingApp
|
||||
cached: true
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 1
|
||||
radius: 4.0
|
||||
samples: 17
|
||||
color: Qt.rgba(0,0,0,0.8)
|
||||
source: icons
|
||||
}
|
||||
|
||||
// screen top panel
|
||||
PlasmaCore.ColorScope {
|
||||
id: icons
|
||||
// top panel component
|
||||
IndicatorsRow {
|
||||
id: topPanel
|
||||
anchors.fill: parent
|
||||
z: 1
|
||||
colorGroup: showingApp ? PlasmaCore.Theme.HeaderColorGroup : PlasmaCore.Theme.ComplementaryColorGroup
|
||||
//parent: slidingPanel.visible && !slidingPanel.wideScreen ? panelContents : root
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
backgroundColor: !showingApp ? "transparent" : root.backgroundColor
|
||||
showGradientBackground: !showingApp
|
||||
showDropShadow: !showingApp
|
||||
}
|
||||
height: root.height
|
||||
|
||||
// top panel background (background for the rest of the screen in SlidingPanel.qml)
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: showingApp ? root.backgroundColor : "transparent"
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: showingApp ? root.backgroundColor : Qt.rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: strengthLoader
|
||||
height: parent.height
|
||||
width: item ? item.width : 0
|
||||
source: Qt.resolvedUrl("indicators/SignalStrength.qml")
|
||||
}
|
||||
|
||||
Row {
|
||||
id: sniRow
|
||||
anchors.left: strengthLoader.right
|
||||
height: parent.height
|
||||
Repeater {
|
||||
id: statusNotifierRepeater
|
||||
model: PlasmaCore.SortFilterModel {
|
||||
id: filteredStatusNotifiers
|
||||
filterRole: "Title"
|
||||
sourceModel: PlasmaCore.DataModel {
|
||||
dataSource: statusNotifierSource
|
||||
}
|
||||
}
|
||||
|
||||
delegate: TaskWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: clock
|
||||
property bool is24HourTime: plasmoid.nativeInterface.isSystem24HourFormat
|
||||
|
||||
anchors.fill: parent
|
||||
text: Qt.formatTime(timeSource.data.Local.DateTime, is24HourTime ? "h:mm" : "h:mm ap")
|
||||
color: PlasmaCore.ColorScope.textColor
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
font.pixelSize: height / 2
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: appletIconsRow
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: simpleIndicatorsLayout.left
|
||||
}
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
//TODO: pluggable
|
||||
RowLayout {
|
||||
id: simpleIndicatorsLayout
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
rightMargin: units.smallSpacing
|
||||
}
|
||||
Indicators.Bluetooth {}
|
||||
Indicators.Wifi {}
|
||||
Indicators.Volume {}
|
||||
Indicators.Battery {}
|
||||
}
|
||||
}
|
||||
|
||||
// screen top panel background (background for the rest of the screen in SlidingPanel.qml)
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
color: PlasmaCore.Theme.backgroundColor
|
||||
opacity: 0.6 * Math.min(1, slidingPanel.offset/panelContents.height)
|
||||
}
|
||||
|
||||
// initial swipe down
|
||||
MouseArea {
|
||||
z: 99
|
||||
property int oldMouseY: 0
|
||||
|
|
@ -256,13 +180,12 @@ Item {
|
|||
slidingPanel.cancelAnimations();
|
||||
slidingPanel.drawerX = Math.min(Math.max(0, mouse.x - slidingPanel.drawerWidth/2), slidingPanel.width - slidingPanel.contentItem.width)
|
||||
slidingPanel.userInteracting = true;
|
||||
slidingPanel.flickable.contentY = slidingPanel.closedContentY;
|
||||
oldMouseY = mouse.y;
|
||||
slidingPanel.offset = 0//units.gridUnit * 2;
|
||||
slidingPanel.showFullScreen();
|
||||
}
|
||||
onPositionChanged: {
|
||||
slidingPanel.offset = Math.min(slidingPanel.contentItem.height, slidingPanel.offset + (mouse.y - oldMouseY));
|
||||
|
||||
slidingPanel.updateOffset(mouse.y - oldMouseY);
|
||||
oldMouseY = mouse.y;
|
||||
}
|
||||
onReleased: {
|
||||
|
|
@ -275,61 +198,65 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
SlidingPanel {
|
||||
// sliding component
|
||||
SlidingContainer {
|
||||
id: slidingPanel
|
||||
width: plasmoid.availableScreenRect.width
|
||||
height: plasmoid.availableScreenRect.height
|
||||
openThreshold: units.gridUnit * 2
|
||||
headerHeight: root.height
|
||||
topPanelHeight: topPanel.height
|
||||
topEmptyAreaHeight: quickSettings.topEmptyAreaHeight
|
||||
collapsedHeight: quickSettings.collapsedHeight
|
||||
fullyOpenHeight: quickSettings.implicitHeight
|
||||
|
||||
appletsShown: fullRepresentationView.count > 0
|
||||
|
||||
offset: quickSettings.height
|
||||
|
||||
onClosed: quickSettings.closed()
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: panelContents.implicitWidth
|
||||
|
||||
contentItem: MouseArea {
|
||||
// mousearea captures touch presses so that the flickable picks them up for swiping
|
||||
implicitWidth: slidingPanel.width
|
||||
implicitHeight: Math.min(slidingPanel.height, quickSettings.implicitHeight)
|
||||
|
||||
GridLayout {
|
||||
id: panelContents
|
||||
anchors.fill: parent
|
||||
implicitWidth: quickSettings.implicitWidth
|
||||
implicitHeight: Math.min(slidingPanel.height, quickSettings.implicitHeight)
|
||||
|
||||
columns: slidingPanel.wideScreen ? 2 : 1
|
||||
rows: slidingPanel.wideScreen ? 1 : 2
|
||||
|
||||
QuickSettings {
|
||||
QuickSettingsPanel {
|
||||
id: quickSettings
|
||||
property int trueHeight: height + Math.round(Kirigami.Units.gridUnit * 1.5) // add height of bottom bar
|
||||
z: 4
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredWidth: slidingPanel.wideScreen ? Math.min(slidingPanel.width/2, units.gridUnit * 25) : panelContents.width
|
||||
z: 4
|
||||
parentSlidingPanel: slidingPanel
|
||||
onCloseRequested: {
|
||||
slidingPanel.hide()
|
||||
}
|
||||
background: DrawerBackground {}
|
||||
onCloseRequested: slidingPanel.hide()
|
||||
}
|
||||
|
||||
// notifications
|
||||
ListView {
|
||||
id: fullRepresentationView
|
||||
z: 1
|
||||
interactive: width < contentWidth
|
||||
//parent: slidingPanel.wideScreen ? slidingPanel.flickable.contentItem : panelContents
|
||||
|
||||
implicitHeight: units.gridUnit * 20
|
||||
Layout.topMargin: slidingPanel.wideScreen ? 0 : Math.round(Kirigami.Units.gridUnit * 1.5) // add height of bottom bar
|
||||
Layout.preferredWidth: slidingPanel.wideScreen ? Math.min(slidingPanel.width/2, quickSettings.width*fullRepresentationModel.count) : panelContents.width
|
||||
Layout.preferredHeight: Math.min(plasmoid.screenGeometry.height - quickSettings.implicitHeight - bottomBar.height + slidingPanel.topEmptyAreaHeight, implicitHeight)
|
||||
z: 1
|
||||
interactive: count > 0 && width < contentWidth
|
||||
|
||||
//Layout.fillWidth: true
|
||||
clip: slidingPanel.wideScreen
|
||||
y: slidingPanel.wideScreen ? 0 : quickSettings.height - (quickSettings.height + height) * (1-opacity)
|
||||
opacity: slidingPanel.wideScreen ? 1 : fullRepresentationModel.count > 0 && (slidingPanel.offset + slidingPanel.headerHeight)/(quickSettings.height -slidingPanel.topEmptyAreaHeight)
|
||||
Layout.preferredHeight: Math.min(plasmoid.screenGeometry.height - slidingPanel.headerHeight - quickSettings.height - bottomBar.height + slidingPanel.topEmptyAreaHeight, implicitHeight)
|
||||
//leftMargin: slidingPanel.drawerX
|
||||
y: slidingPanel.wideScreen ? 0 : quickSettings.trueHeight
|
||||
opacity: {
|
||||
if (slidingPanel.wideScreen) {
|
||||
return 1;
|
||||
} else {
|
||||
return fullRepresentationModel.count > 0 && slidingPanel.offset / slidingPanel.collapsedHeight;
|
||||
}
|
||||
}
|
||||
preferredHighlightBegin: slidingPanel.drawerX
|
||||
|
||||
implicitHeight: units.gridUnit * 20
|
||||
cacheBuffer: width * 100
|
||||
highlightFollowsCurrentItem: true
|
||||
highlightRangeMode: ListView.StrictlyEnforceRange
|
||||
|
|
@ -346,10 +273,6 @@ Item {
|
|||
z: -1
|
||||
onClicked: slidingPanel.close()
|
||||
}
|
||||
|
||||
//implicitHeight: fullRepresentationLayout.implicitHeight
|
||||
//clip: true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -360,11 +283,11 @@ Item {
|
|||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
backgroundColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.Theme.backgroundColor, {"alpha": 0.8*255})
|
||||
|
||||
parent: slidingPanel.fixedArea
|
||||
opacity: fullRepresentationView.opacity
|
||||
visible: !slidingPanel.wideScreen && fullRepresentationModel.count > 1
|
||||
//height: 40
|
||||
z: 100
|
||||
contentItem: RowLayout {
|
||||
PlasmaComponents.TabBar {
|
||||
|
|
|
|||
|
|
@ -9,23 +9,68 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
|
||||
RowLayout {
|
||||
Item {
|
||||
id: brightnessRoot
|
||||
property alias value: brightnessSlider.value
|
||||
property alias maximumValue: brightnessSlider.to
|
||||
|
||||
signal moved
|
||||
implicitHeight: brightnessRow.implicitHeight
|
||||
|
||||
spacing: units.smallSpacing
|
||||
property int screenBrightness
|
||||
property bool disableBrightnessUpdate: true
|
||||
readonly property int maximumScreenBrightness: pmSource.data["PowerDevil"] ? pmSource.data["PowerDevil"]["Maximum Screen Brightness"] || 0 : 0
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
onScreenBrightnessChanged: {
|
||||
brightnessSlider.value = brightnessRoot.screenBrightness
|
||||
if (!disableBrightnessUpdate) {
|
||||
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: {
|
||||
disableBrightnessUpdate = true;
|
||||
brightnessRoot.screenBrightness = pmSource.data["PowerDevil"]["Screen Brightness"];
|
||||
disableBrightnessUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
brightnessSlider.moved.connect(function() {
|
||||
brightnessRoot.screenBrightness = brightnessSlider.value;
|
||||
});
|
||||
disableBrightnessUpdate = false;
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: brightnessRow
|
||||
spacing: PlasmaCore.Units.smallSpacing * 2
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
|
||||
Kirigami.Icon {
|
||||
color: PlasmaCore.Theme.textColor
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.preferredWidth: units.iconSizes.medium
|
||||
Layout.leftMargin: PlasmaCore.Units.smallSpacing
|
||||
Layout.preferredWidth: Math.round(PlasmaCore.Units.gridUnit * 1.75)
|
||||
Layout.preferredHeight: width
|
||||
source: "low-brightness"
|
||||
}
|
||||
|
|
@ -34,15 +79,19 @@ RowLayout {
|
|||
id: brightnessSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
onMoved: brightnessRoot.moved()
|
||||
value: screenBrightness
|
||||
from: 1
|
||||
to: maximumScreenBrightness
|
||||
}
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
Kirigami.Icon {
|
||||
color: PlasmaCore.Theme.textColor
|
||||
isMask: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
Layout.preferredWidth: units.iconSizes.medium
|
||||
Layout.rightMargin: PlasmaCore.Units.smallSpacing
|
||||
Layout.preferredWidth: Math.round(PlasmaCore.Units.gridUnit * 1.75)
|
||||
Layout.preferredHeight: width
|
||||
source: "high-brightness"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
|
@ -14,6 +15,9 @@ import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
|||
ColumnLayout {
|
||||
id: delegateRoot
|
||||
spacing: units.smallSpacing
|
||||
|
||||
required property var settingsModel
|
||||
|
||||
signal closeRequested
|
||||
signal panelClosed
|
||||
|
||||
|
|
@ -25,34 +29,36 @@ ColumnLayout {
|
|||
required property var toggleFunction
|
||||
property alias labelOpacity: label.opacity
|
||||
|
||||
property color disabledButtonColor: PlasmaCore.Theme.backgroundColor
|
||||
property color disabledPressedButtonColor: Qt.darker(disabledButtonColor, 1.1)
|
||||
property color enabledButtonColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.highlightColor, {"alpha": 0.4*255})
|
||||
property color enabledPressedButtonColor: Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.highlightColor, {"alpha": 0.6*255});
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: units.iconSizes.large + units.smallSpacing
|
||||
Layout.preferredWidth: PlasmaCore.Units.iconSizes.large + PlasmaCore.Units.smallSpacing
|
||||
Layout.minimumHeight: width
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
radius: units.smallSpacing
|
||||
radius: PlasmaCore.Units.smallSpacing
|
||||
border.color: delegateRoot.enabled ?
|
||||
Qt.darker(Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.highlightColor, {}), 1.25) :
|
||||
Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.textColor, {"alpha": 0.2*255})
|
||||
color: {
|
||||
if (delegateRoot.enabled) {
|
||||
return Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.highlightColor, {"alpha": iconMouseArea.pressed ? 0.5*255 : 0.3*255});
|
||||
return iconMouseArea.pressed ? enabledPressedButtonColor : enabledButtonColor
|
||||
} else {
|
||||
if (iconMouseArea.pressed) {
|
||||
return Qt.darker(Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.backgroundColor, {"alpha": 0.9*255}), 1.25);
|
||||
} else {
|
||||
return Kirigami.ColorUtils.adjustColor(PlasmaCore.ColorScope.backgroundColor, {"alpha": 0.3*255});
|
||||
}
|
||||
return iconMouseArea.pressed ? disabledPressedButtonColor : disabledButtonColor
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
Kirigami.Icon {
|
||||
id: icon
|
||||
colorGroup: PlasmaCore.ColorScope.colorGroup
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: units.smallSpacing
|
||||
}
|
||||
color: PlasmaCore.Theme.textColor
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: Math.round(parent.width * 0.6)
|
||||
implicitHeight: width
|
||||
source: delegateRoot.icon
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: iconMouseArea
|
||||
anchors.fill: parent
|
||||
|
|
@ -60,7 +66,7 @@ ColumnLayout {
|
|||
if (delegateRoot.toggle) {
|
||||
delegateRoot.toggle();
|
||||
} else if (delegateRoot.toggleFunction) {
|
||||
root[delegateRoot.toggleFunction]();
|
||||
settingsModel[delegateRoot.toggleFunction]();
|
||||
} else if (delegateRoot.settingsCommand) {
|
||||
NanoShell.StartupFeedback.open(
|
||||
delegateRoot.icon,
|
||||
|
|
@ -88,7 +94,6 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label {
|
||||
id: label
|
||||
|
|
@ -131,7 +136,7 @@ ColumnLayout {
|
|||
plasmoid.nativeInterface.executeCommand(delegateRoot.settingsCommand);
|
||||
closeRequested();
|
||||
} else if (delegateRoot.toggleFunction) {
|
||||
root[delegateRoot.toggleFunction]();
|
||||
settingsModel[delegateRoot.toggleFunction]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,385 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
|
||||
import org.kde.bluezqt 1.0 as BluezQt
|
||||
import org.kde.colorcorrect 0.1 as CC
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
implicitWidth: column.implicitWidth + units.smallSpacing * 6
|
||||
implicitHeight: column.implicitHeight + units.smallSpacing * 2
|
||||
|
||||
signal closeRequested
|
||||
signal closed
|
||||
|
||||
property bool expandedMode: parentSlidingPanel.wideScreen
|
||||
readonly property real expandedRatio: expandedMode ? 1 : Math.max(0, Math.min(1, (parentSlidingPanel.offset - firstRowHeight - parentSlidingPanel.headerHeight) / otherRowsHeight))
|
||||
|
||||
readonly property real topEmptyAreaHeight: parentSlidingPanel.userInteracting
|
||||
? (root.height - collapsedHeight) * (1 - expandedRatio)
|
||||
: (expandedMode ? 0 : root.height - collapsedHeight)
|
||||
|
||||
readonly property real collapsedHeight: firstRowHeight + PlasmaCore.Units.smallSpacing * 2
|
||||
readonly property real firstRowHeight: flow.children[0].height
|
||||
readonly property real otherRowsHeight: column.height - firstRowHeight
|
||||
|
||||
Connections {
|
||||
target: root.parentSlidingPanel
|
||||
function onUserInteractingChanged() {
|
||||
if (!parentSlidingPanel.userInteracting) {
|
||||
if (root.expandedRatio > 0.7) {
|
||||
root.expandedMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property bool screenshotRequested: false
|
||||
|
||||
property NanoShell.FullScreenOverlay parentSlidingPanel
|
||||
property Item background
|
||||
onBackgroundChanged: {
|
||||
background.parent = backgroundParent
|
||||
background.anchors.fill = backgroundParent
|
||||
}
|
||||
|
||||
PlasmaNM.Handler {
|
||||
id: nmHandler
|
||||
}
|
||||
|
||||
PlasmaNM.EnabledConnections {
|
||||
id: enabledConnections
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.Window.window
|
||||
function onVisibilityChanged() {
|
||||
root.expandedMode = parentSlidingPanel.wideScreen;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BluezQt.Manager
|
||||
|
||||
function onBluetoothOperationalChanged() {
|
||||
settingsModel.get(2).enabled = BluezQt.Manager.bluetoothOperational
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAirplane() {
|
||||
print("toggle airplane mode")
|
||||
}
|
||||
|
||||
function toggleTorch() {
|
||||
plasmoid.nativeInterface.toggleTorch()
|
||||
settingsModel.get(6).enabled = plasmoid.nativeInterface.torchEnabled
|
||||
}
|
||||
|
||||
function toggleWifi() {
|
||||
nmHandler.enableWireless(!enabledConnections.wirelessEnabled)
|
||||
settingsModel.get(1).enabled = !enabledConnections.wirelessEnabled
|
||||
}
|
||||
|
||||
function toggleWwan() {
|
||||
nmHandler.enableWwan(!enabledConnections.wwanEnabled)
|
||||
settingsModel.get(3).enabled = !enabledConnections.wwanEnabled
|
||||
}
|
||||
|
||||
function toggleRotation() {
|
||||
const enable = !plasmoid.nativeInterface.autoRotateEnabled
|
||||
plasmoid.nativeInterface.autoRotateEnabled = enable
|
||||
settingsModel.get(9).enabled = enable
|
||||
}
|
||||
|
||||
function toggleBluetooth() {
|
||||
var enable = !BluezQt.Manager.bluetoothOperational;
|
||||
BluezQt.Manager.bluetoothBlocked = !enable;
|
||||
|
||||
for (var i = 0; i < BluezQt.Manager.adapters.length; ++i) {
|
||||
var adapter = BluezQt.Manager.adapters[i];
|
||||
adapter.powered = enable;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleNightColor() {
|
||||
if (compositorAdaptor.active) {
|
||||
compositorAdaptor.activeStaged = false;
|
||||
} else {
|
||||
compositorAdaptor.activeStaged = true;
|
||||
compositorAdaptor.modeStaged = 3; // always on
|
||||
}
|
||||
compositorAdaptor.sendConfigurationAll();
|
||||
settingsModel.get(10).enabled = compositorAdaptor.active;
|
||||
}
|
||||
|
||||
function requestShutdown() {
|
||||
print("Shutdown requested, depends on ksmserver running");
|
||||
var service = pmSource.serviceForSource("PowerDevil");
|
||||
//note the strange camelCasing is intentional
|
||||
var operation = service.operationDescription("requestShutDown");
|
||||
return service.startOperationCall(operation);
|
||||
}
|
||||
|
||||
signal plasmoidTriggered(var applet, var id)
|
||||
Layout.minimumHeight: flow.implicitHeight + units.largeSpacing*2
|
||||
|
||||
property int screenBrightness
|
||||
property bool disableBrightnessUpdate: true
|
||||
readonly property int maximumScreenBrightness: pmSource.data["PowerDevil"] ? pmSource.data["PowerDevil"]["Maximum Screen Brightness"] || 0 : 0
|
||||
|
||||
onScreenBrightnessChanged: {
|
||||
if(!disableBrightnessUpdate) {
|
||||
var service = pmSource.serviceForSource("PowerDevil");
|
||||
var operation = service.operationDescription("setBrightness");
|
||||
operation.brightness = screenBrightness;
|
||||
operation.silent = true
|
||||
service.startOperationCall(operation);
|
||||
}
|
||||
}
|
||||
|
||||
function requestScreenshot() {
|
||||
screenshotRequested = true;
|
||||
root.closeRequested();
|
||||
}
|
||||
|
||||
onClosed: {
|
||||
if (screenshotRequested) {
|
||||
plasmoid.nativeInterface.takeScreenshot();
|
||||
screenshotRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaCore.DataSource {
|
||||
id: pmSource
|
||||
engine: "powermanagement"
|
||||
connectedSources: ["PowerDevil"]
|
||||
onSourceAdded: {
|
||||
if (source === "PowerDevil") {
|
||||
disconnectSource(source);
|
||||
connectSource(source);
|
||||
}
|
||||
}
|
||||
onDataChanged: {
|
||||
disableBrightnessUpdate = true;
|
||||
root.screenBrightness = pmSource.data["PowerDevil"]["Screen Brightness"];
|
||||
disableBrightnessUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
// night color
|
||||
CC.CompositorAdaptor {
|
||||
id: compositorAdaptor
|
||||
}
|
||||
|
||||
//HACK: make the list know about the applet delegate which is a qtobject
|
||||
QtObject {
|
||||
id: nullApplet
|
||||
}
|
||||
Component.onCompleted: {
|
||||
//NOTE: add all in javascript as the static decl of listelements can't have scripts
|
||||
settingsModel.append({
|
||||
"text": i18n("Settings"),
|
||||
"icon": "configure",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings",
|
||||
"toggleFunction": "",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Wifi"),
|
||||
"icon": "network-wireless-signal",
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_wifi",
|
||||
"toggleFunction": "toggleWifi",
|
||||
"enabled": enabledConnections.wirelessEnabled,
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Bluetooth"),
|
||||
"icon": "network-bluetooth",
|
||||
"settingsCommand": "plasma-settings -m kcm_bluetooth",
|
||||
"toggleFunction": "toggleBluetooth",
|
||||
"delegate": "",
|
||||
"enabled": BluezQt.Manager.bluetoothOperational,
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Mobile Data"),
|
||||
"icon": "network-modem",
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_broadband",
|
||||
"toggleFunction": "toggleWwan",
|
||||
"enabled": enabledConnections.wwanEnabled,
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Battery"),
|
||||
"icon": "battery-full",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_power",
|
||||
"toggleFunction": "",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Sound"),
|
||||
"icon": "audio-speakers-symbolic",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings -m kcm_pulseaudio",
|
||||
"toggleFunction": "",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Flashlight"),
|
||||
"icon": "flashlight-on",
|
||||
"enabled": plasmoid.nativeInterface.torchEnabled,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "toggleTorch",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Location"),
|
||||
"icon": "gps",
|
||||
"enabled": false,
|
||||
"settingsCommand": "",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Screenshot"),
|
||||
"icon": "spectacle",
|
||||
"enabled": false,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "requestScreenshot",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Auto-rotate"),
|
||||
"icon": "rotation-allowed",
|
||||
"enabled": plasmoid.nativeInterface.autoRotateEnabled,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "toggleRotation",
|
||||
"applet": null
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Night Color"),
|
||||
"icon": "redshift-status-on",
|
||||
"enabled": compositorAdaptor.active,
|
||||
"settingsCommand": "", // change once night color kcm is added
|
||||
"toggleFunction": "toggleNightColor",
|
||||
"applet": null
|
||||
});
|
||||
|
||||
brightnessSlider.moved.connect(function() {
|
||||
root.screenBrightness = brightnessSlider.value;
|
||||
});
|
||||
disableBrightnessUpdate = false;
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: settingsModel
|
||||
}
|
||||
|
||||
Item {
|
||||
id: backgroundParent
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: firstRowHeight + otherRowsHeight * root.expandedRatio
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: units.smallSpacing
|
||||
}
|
||||
|
||||
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
|
||||
readonly property real columnWidth: Math.floor(width / Math.floor(width / cellSizeHint))
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Flow {
|
||||
id: flow
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: units.smallSpacing + (units.largeSpacing - units.smallSpacing) * root.expandedRatio
|
||||
Layout.rightMargin: units.largeSpacing
|
||||
Layout.topMargin: units.largeSpacing
|
||||
|
||||
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
|
||||
readonly property real columnWidth: Math.floor(width / Math.floor(width / cellSizeHint))
|
||||
spacing: 0
|
||||
Repeater {
|
||||
model: settingsModel
|
||||
delegate: Delegate {
|
||||
id: delegateItem
|
||||
|
||||
//FIXME: why this is needed?
|
||||
width: flow.columnWidth - (y > 0 ? 0 : (flow.columnWidth/Math.floor(flow.width / flow.columnWidth)) * (1 - root.expandedRatio))
|
||||
height: item ? item.implicitHeight : 0
|
||||
|
||||
labelOpacity: y > 0 ? 1 : root.expandedRatio
|
||||
|
||||
opacity: y <= 0 ? 1 : root.expandedRatio
|
||||
transform: Translate {
|
||||
y: otherRowsHeight * (1 - root.expandedRatio)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: delegateItem
|
||||
onCloseRequested: root.closeRequested();
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
onClosed: delegateItem.panelClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
duration: units.shortDuration
|
||||
//Here a linear easing actually looks better
|
||||
//easing.type: Easing.InOutQuad
|
||||
properties: "x,y"
|
||||
}
|
||||
}
|
||||
}
|
||||
BrightnessItem {
|
||||
id: brightnessSlider
|
||||
|
||||
Layout.bottomMargin: units.largeSpacing
|
||||
Layout.leftMargin: units.largeSpacing
|
||||
Layout.rightMargin: units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
|
||||
value: root.screenBrightness
|
||||
maximumValue: root.maximumScreenBrightness
|
||||
opacity: root.expandedRatio
|
||||
transform: Translate {
|
||||
y: otherRowsHeight * (1 - root.expandedRatio)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
onScreenBrightnessChanged: brightnessSlider.value = root.screenBrightness
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
|
||||
import org.kde.bluezqt 1.0 as BluezQt
|
||||
import org.kde.colorcorrect 0.1 as CC
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
|
||||
Item {
|
||||
property alias model: settingsModel
|
||||
property bool screenshotRequested: false
|
||||
|
||||
signal panelClosed()
|
||||
|
||||
onPanelClosed: {
|
||||
if (screenshotRequested) {
|
||||
plasmoid.nativeInterface.takeScreenshot();
|
||||
screenshotRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: settingsModel
|
||||
}
|
||||
|
||||
PlasmaNM.Handler {
|
||||
id: nmHandler
|
||||
}
|
||||
|
||||
PlasmaNM.EnabledConnections {
|
||||
id: enabledConnections
|
||||
}
|
||||
|
||||
// night color
|
||||
CC.CompositorAdaptor {
|
||||
id: compositorAdaptor
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BluezQt.Manager
|
||||
function onBluetoothOperationalChanged() {
|
||||
settingsModel.get(2).enabled = BluezQt.Manager.bluetoothOperational
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAirplane() {
|
||||
print("toggle airplane mode")
|
||||
}
|
||||
|
||||
function toggleTorch() {
|
||||
plasmoid.nativeInterface.toggleTorch()
|
||||
settingsModel.get(6).enabled = plasmoid.nativeInterface.torchEnabled
|
||||
}
|
||||
|
||||
function toggleWifi() {
|
||||
nmHandler.enableWireless(!enabledConnections.wirelessEnabled)
|
||||
settingsModel.get(1).enabled = !enabledConnections.wirelessEnabled
|
||||
}
|
||||
|
||||
function toggleWwan() {
|
||||
nmHandler.enableWwan(!enabledConnections.wwanEnabled)
|
||||
settingsModel.get(3).enabled = !enabledConnections.wwanEnabled
|
||||
}
|
||||
|
||||
function toggleRotation() {
|
||||
const enable = !plasmoid.nativeInterface.autoRotateEnabled
|
||||
plasmoid.nativeInterface.autoRotateEnabled = enable
|
||||
settingsModel.get(9).enabled = enable
|
||||
}
|
||||
|
||||
function toggleBluetooth() {
|
||||
var enable = !BluezQt.Manager.bluetoothOperational;
|
||||
BluezQt.Manager.bluetoothBlocked = !enable;
|
||||
|
||||
for (var i = 0; i < BluezQt.Manager.adapters.length; ++i) {
|
||||
var adapter = BluezQt.Manager.adapters[i];
|
||||
adapter.powered = enable;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleNightColor() {
|
||||
if (compositorAdaptor.active) {
|
||||
compositorAdaptor.activeStaged = false;
|
||||
} else {
|
||||
compositorAdaptor.activeStaged = true;
|
||||
compositorAdaptor.modeStaged = 3; // always on
|
||||
}
|
||||
compositorAdaptor.sendConfigurationAll();
|
||||
settingsModel.get(10).enabled = compositorAdaptor.active;
|
||||
}
|
||||
|
||||
// components needed for quick settings
|
||||
function requestScreenshot() {
|
||||
screenshotRequested = true;
|
||||
root.closeRequested();
|
||||
}
|
||||
|
||||
// initialize quick settings
|
||||
Component.onCompleted: {
|
||||
//NOTE: add all in javascript as the static decl of listelements can't have scripts
|
||||
settingsModel.append({
|
||||
"text": i18n("Settings"),
|
||||
"icon": "configure",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings",
|
||||
"toggleFunction": ""
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Wifi"),
|
||||
"icon": "network-wireless-signal",
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_wifi",
|
||||
"toggleFunction": "toggleWifi",
|
||||
"enabled": enabledConnections.wirelessEnabled
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Bluetooth"),
|
||||
"icon": "network-bluetooth",
|
||||
"settingsCommand": "plasma-settings -m kcm_bluetooth",
|
||||
"toggleFunction": "toggleBluetooth",
|
||||
"delegate": "",
|
||||
"enabled": BluezQt.Manager.bluetoothOperational
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Mobile Data"),
|
||||
"icon": "network-modem",
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_broadband",
|
||||
"toggleFunction": "toggleWwan",
|
||||
"enabled": enabledConnections.wwanEnabled
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Battery"),
|
||||
"icon": "battery-full",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings -m kcm_mobile_power",
|
||||
"toggleFunction": ""
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Sound"),
|
||||
"icon": "audio-speakers-symbolic",
|
||||
"enabled": false,
|
||||
"settingsCommand": "plasma-settings -m kcm_pulseaudio",
|
||||
"toggleFunction": ""
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Flashlight"),
|
||||
"icon": "flashlight-on",
|
||||
"enabled": plasmoid.nativeInterface.torchEnabled,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "toggleTorch"
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Location"),
|
||||
"icon": "gps",
|
||||
"enabled": false,
|
||||
"settingsCommand": ""
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Screenshot"),
|
||||
"icon": "spectacle",
|
||||
"enabled": false,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "requestScreenshot"
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Auto-rotate"),
|
||||
"icon": "rotation-allowed",
|
||||
"enabled": plasmoid.nativeInterface.autoRotateEnabled,
|
||||
"settingsCommand": "",
|
||||
"toggleFunction": "toggleRotation"
|
||||
});
|
||||
settingsModel.append({
|
||||
"text": i18n("Night Color"),
|
||||
"icon": "redshift-status-on",
|
||||
"enabled": compositorAdaptor.active,
|
||||
"settingsCommand": "", // change once night color kcm is added
|
||||
"toggleFunction": "toggleNightColor"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Window 2.2
|
||||
import QtGraphicalEffects 1.12
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.networkmanagement 0.2 as PlasmaNM
|
||||
import org.kde.bluezqt 1.0 as BluezQt
|
||||
import org.kde.colorcorrect 0.1 as CC
|
||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
||||
|
||||
import org.kde.plasma.components 3.0 as PC3
|
||||
|
||||
import "../"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
implicitWidth: column.implicitWidth + PlasmaCore.Units.smallSpacing * 6
|
||||
implicitHeight: column.implicitHeight + PlasmaCore.Units.smallSpacing * 2
|
||||
|
||||
signal closeRequested
|
||||
signal closed
|
||||
|
||||
property bool expandedMode: parentSlidingPanel.wideScreen
|
||||
readonly property real expandedRatio: expandedMode ? 1 : Math.max(0, Math.min(1, (parentSlidingPanel.offset - (parentSlidingPanel.topPanelHeight + firstRowHeight) - parentSlidingPanel.topPanelHeight) / otherRowsHeight + 0.05)) // HACK: add 0.05 to prevent jumping since this height isn't exact
|
||||
|
||||
readonly property real topEmptyAreaHeight: parentSlidingPanel.userInteracting
|
||||
? (root.height - collapsedHeight) * (1 - expandedRatio)
|
||||
: (expandedMode ? 0 : root.height - collapsedHeight)
|
||||
|
||||
readonly property real collapsedHeight: parentSlidingPanel.topPanelHeight + firstRowHeight + PlasmaCore.Units.smallSpacing * 2
|
||||
readonly property real firstRowHeight: flow.children[0].height
|
||||
readonly property real otherRowsHeight: column.implicitHeight - firstRowHeight - parentSlidingPanel.topPanelHeight
|
||||
|
||||
Connections {
|
||||
target: root.parentSlidingPanel
|
||||
function onUserInteractingChanged() {
|
||||
if (!parentSlidingPanel.userInteracting) {
|
||||
if (root.expandedRatio > 0.7) {
|
||||
root.expandedMode = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property NanoShell.FullScreenOverlay parentSlidingPanel
|
||||
|
||||
Connections {
|
||||
target: root.Window.window
|
||||
function onVisibilityChanged() {
|
||||
root.expandedMode = parentSlidingPanel.wideScreen;
|
||||
}
|
||||
}
|
||||
|
||||
signal plasmoidTriggered(var applet, var id)
|
||||
Layout.minimumHeight: flow.implicitHeight + units.largeSpacing*2
|
||||
|
||||
onClosed: quickSettingsModel.panelClosed()
|
||||
|
||||
property QuickSettingsModel quickSettingsModel: QuickSettingsModel {}
|
||||
|
||||
// shadow below panel (only if not widescreen)
|
||||
Rectangle {
|
||||
visible: !parentSlidingPanel.wideScreen
|
||||
anchors.bottom: background.bottom
|
||||
anchors.left: background.left
|
||||
anchors.right: background.right
|
||||
height: PlasmaCore.Units.gridUnit
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: Qt.rgba(0, 0, 0, 0.05)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
// shadow for bottom bar
|
||||
RectangularGlow {
|
||||
z: 1
|
||||
anchors.topMargin: 1
|
||||
anchors.fill: bottomBar
|
||||
cached: true
|
||||
glowRadius: 4
|
||||
spread: 0.2
|
||||
color: Qt.rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
// shadow for whole panel (only if widescreen)
|
||||
RectangularGlow {
|
||||
visible: parentSlidingPanel.wideScreen
|
||||
anchors.topMargin: 1
|
||||
anchors.top: background.top
|
||||
anchors.left: background.left
|
||||
anchors.right: background.right
|
||||
anchors.bottom: bottomBar.bottom
|
||||
cached: true
|
||||
glowRadius: 4
|
||||
spread: 0.2
|
||||
color: Qt.rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
// bottom "handle bar"
|
||||
Rectangle {
|
||||
id: bottomBar
|
||||
anchors.top: background.bottom
|
||||
anchors.left: background.left
|
||||
anchors.right: background.right
|
||||
color: PlasmaCore.Theme.backgroundColor
|
||||
height: Math.round(PlasmaCore.Units.gridUnit * 1.3)
|
||||
z: 1
|
||||
|
||||
Kirigami.Icon {
|
||||
visible: !parentSlidingPanel.wideScreen
|
||||
color: PlasmaCore.Theme.disabledTextColor
|
||||
source: expandedRatio >= 1 ? "go-up-symbolic" : "go-down-symbolic"
|
||||
implicitWidth: PlasmaCore.Units.gridUnit
|
||||
implicitHeight: width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
color: PlasmaCore.Theme.backgroundColor
|
||||
anchors.fill: parent
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
anchors.leftMargin: PlasmaCore.Units.smallSpacing
|
||||
anchors.rightMargin: PlasmaCore.Units.smallSpacing
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
spacing: 0
|
||||
clip: expandedRatio > 0 && expandedRatio < 1 // only clip when necessary to improve performance
|
||||
|
||||
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
|
||||
readonly property real columnWidth: Math.floor(width / Math.floor(width / cellSizeHint))
|
||||
|
||||
IndicatorsRow {
|
||||
id: indicatorsRow
|
||||
z: 1
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: parentSlidingPanel.topPanelHeight
|
||||
colorGroup: PlasmaCore.Theme.NormalColorGroup
|
||||
backgroundColor: "transparent"
|
||||
showGradientBackground: false
|
||||
showDropShadow: false
|
||||
transform: Translate {
|
||||
y: otherRowsHeight * (1 - root.expandedRatio) - PlasmaCore.Units.smallSpacing
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: flow
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: units.smallSpacing + (units.largeSpacing - units.smallSpacing) * root.expandedRatio
|
||||
Layout.rightMargin: units.smallSpacing + (units.largeSpacing - units.smallSpacing) * root.expandedRatio
|
||||
Layout.topMargin: units.largeSpacing
|
||||
|
||||
readonly property real cellSizeHint: units.iconSizes.large + units.smallSpacing * 6
|
||||
readonly property real columns: Math.floor(width / cellSizeHint)
|
||||
readonly property real columnsWhenCollapsed: 1.05 // .05 to account for the fact that we have an overshoot on the panel on first flick, we don't want the movement to be jarring
|
||||
readonly property real columnWidth: Math.floor(width / (columns + (columnsWhenCollapsed - columnsWhenCollapsed * root.expandedRatio)))
|
||||
|
||||
spacing: 0
|
||||
Repeater {
|
||||
model: quickSettingsModel.model
|
||||
delegate: Delegate {
|
||||
id: delegateItem
|
||||
settingsModel: quickSettingsModel
|
||||
width: flow.columnWidth
|
||||
|
||||
labelOpacity: y > 0 ? 1 : root.expandedRatio
|
||||
opacity: y <= 0 ? 1 : root.expandedRatio
|
||||
transform: Translate {
|
||||
y: otherRowsHeight * (1 - root.expandedRatio) - PlasmaCore.Units.smallSpacing * 2
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: delegateItem
|
||||
onCloseRequested: root.closeRequested();
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
onClosed: delegateItem.panelClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
duration: units.shortDuration
|
||||
easing.type: Easing.Linear
|
||||
properties: "x,y"
|
||||
}
|
||||
}
|
||||
}
|
||||
BrightnessItem {
|
||||
id: brightnessSlider
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: units.smallSpacing
|
||||
Layout.bottomMargin: units.smallSpacing
|
||||
Layout.leftMargin: units.largeSpacing
|
||||
Layout.rightMargin: units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
|
||||
opacity: root.expandedRatio
|
||||
transform: Translate {
|
||||
y: otherRowsHeight * (1 - root.expandedRatio) - PlasmaCore.Units.smallSpacing * 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue