You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
statusbar/qml/main.qml

547 lines
18 KiB
QML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (C) 2021 CutefishOS Team.
*
* Author: Reion Wong <aj@cutefishos.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import Cutefish.StatusBar 1.0
import Cutefish.NetworkManagement 1.0 as NM
import FishUI 1.0 as FishUI
Item {
id: rootItem
property int iconSize: 16
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
property bool darkMode: FishUI.Theme.darkMode
property color textColor: rootItem.darkMode ? "#FFFFFF" : "#000000";
property var fontSize: rootItem.height ? rootItem.height / 3 : 1
property var timeFormat: StatusBar.twentyFourTime ? "HH:mm" : "h:mm ap"
onTimeFormatChanged: {
timeTimer.restart()
}
Rectangle {
id: background
anchors.fill: parent
color: FishUI.Theme.darkMode ? "#4D4D4D" : "#FFFFFF"
opacity: windowHelper.compositing ? FishUI.Theme.darkMode ? 0.5 : 0.7 : 1.0
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.Linear
}
}
}
FishUI.WindowHelper {
id: windowHelper
}
FishUI.PopupTips {
id: popupTips
}
FishUI.DesktopMenu {
id: acticityMenu
MenuItem {
text: qsTr("Close")
onTriggered: acticity.close()
}
}
// Main layout
RowLayout {
anchors.fill: parent
anchors.leftMargin: FishUI.Units.smallSpacing
anchors.rightMargin: FishUI.Units.smallSpacing
spacing: FishUI.Units.smallSpacing / 2
// App name
StandardItem {
id: acticityItem
animationEnabled: true
Layout.fillHeight: true
Layout.preferredWidth: Math.min(rootItem.width / 3,
acticityLayout.implicitWidth + FishUI.Units.largeSpacing)
onClicked: {
if (mouse.button === Qt.RightButton)
acticityMenu.open()
}
RowLayout {
id: acticityLayout
anchors.fill: parent
anchors.leftMargin: FishUI.Units.smallSpacing
anchors.rightMargin: FishUI.Units.smallSpacing
spacing: FishUI.Units.smallSpacing
Image {
id: acticityIcon
width: rootItem.iconSize
height: rootItem.iconSize
sourceSize: Qt.size(rootItem.iconSize,
rootItem.iconSize)
source: acticity.icon ? "image://icontheme/" + acticity.icon : ""
visible: status === Image.Ready
antialiasing: true
smooth: false
}
Label {
id: acticityLabel
text: acticity.title
Layout.fillWidth: true
elide: Qt.ElideRight
color: rootItem.textColor
visible: text
Layout.alignment: Qt.AlignVCenter
font.pointSize: rootItem.fontSize
}
}
}
// App menu
Item {
id: appMenuItem
Layout.fillHeight: true
Layout.fillWidth: true
ListView {
id: appMenuView
anchors.fill: parent
orientation: Qt.Horizontal
spacing: FishUI.Units.smallSpacing
visible: appMenuModel.visible
interactive: false
clip: true
model: appMenuModel
// Initialize the current index
onVisibleChanged: {
if (!visible)
appMenuView.currentIndex = -1
}
delegate: StandardItem {
id: _menuItem
width: _actionText.width + FishUI.Units.largeSpacing
height: ListView.view.height
checked: appMenuApplet.currentIndex === index
onClicked: {
appMenuApplet.trigger(_menuItem, index)
checked = Qt.binding(function() {
return appMenuApplet.currentIndex === index
})
}
Text {
id: _actionText
anchors.centerIn: parent
color: rootItem.textColor
font.pointSize: rootItem.fontSize
text: {
var text = activeMenu
text = text.replace(/([^&]*)&(.)([^&]*)/g, function (match, p1, p2, p3) {
return p1.concat(p2, p3)
})
return text
}
}
// QMenu opens on press, so we'll replicate that here
MouseArea {
anchors.fill: parent
hoverEnabled: appMenuApplet.currentIndex !== -1
onPressed: parent.clicked(null)
onEntered: parent.clicked(null)
}
}
AppMenuModel {
id: appMenuModel
onRequestActivateIndex: appMenuApplet.requestActivateIndex(appMenuView.currentIndex)
Component.onCompleted: {
appMenuView.model = appMenuModel
}
}
AppMenuApplet {
id: appMenuApplet
model: appMenuModel
}
Component.onCompleted: {
appMenuApplet.buttonGrid = appMenuView
// Handle left and right shortcut keys.
appMenuApplet.requestActivateIndex.connect(function (index) {
var idx = Math.max(0, Math.min(appMenuView.count - 1, index))
var button = appMenuView.itemAtIndex(index)
if (button) {
button.clicked(null)
}
});
// Handle mouse movement.
appMenuApplet.mousePosChanged.connect(function (x, y) {
var item = itemAt(x, y)
if (item)
item.clicked(null)
});
}
}
}
// System tray(Right)
ListView {
id: trayView
orientation: Qt.Horizontal
layoutDirection: Qt.RightToLeft
interactive: false
clip: true
spacing: FishUI.Units.smallSpacing / 2
property real itemWidth: rootItem.iconSize + FishUI.Units.largeSpacing
Layout.fillHeight: true
Layout.preferredWidth: (itemWidth + (count - 1) * FishUI.Units.smallSpacing) * count
model: SystemTrayModel {
id: trayModel
}
moveDisplaced: Transition {
NumberAnimation {
properties: "x, y"
duration: 200
easing.type: Easing.InOutQuad
}
}
delegate: StandardItem {
id: _trayItem
property bool darkMode: rootItem.darkMode
property int dragItemIndex: index
property bool dragStarted: false
width: trayView.itemWidth
height: ListView.view.height
animationEnabled: false
onDarkModeChanged: updateTimer.restart()
Drag.active: _trayItem.mouseArea.drag.active
Drag.dragType: Drag.Automatic
Drag.supportedActions: Qt.MoveAction
Drag.hotSpot.x: iconItem.width / 2
Drag.hotSpot.y: iconItem.height / 2
Drag.onDragStarted: {
dragStarted = true
}
Drag.onDragFinished: {
dragStarted = false
}
onPositionChanged: {
if (_trayItem.mouseArea.pressed) {
_trayItem.mouseArea.drag.target = iconItem
iconItem.grabToImage(function(result) {
_trayItem.Drag.imageSource = result.url
})
} else {
_trayItem.mouseArea.drag.target = null
}
}
onReleased: {
_trayItem.mouseArea.drag.target = null
}
DropArea {
anchors.fill: parent
enabled: true
onEntered: {
if (drag.source)
trayModel.move(drag.source.dragItemIndex,
_trayItem.dragItemIndex)
}
}
Timer {
id: updateTimer
interval: 10
onTriggered: iconItem.updateIcon()
}
FishUI.IconItem {
id: iconItem
anchors.centerIn: parent
width: rootItem.iconSize
height: width
source: model.iconName ? model.iconName : model.icon
antialiasing: true
smooth: false
visible: !dragStarted
}
onClicked: {
var pos = trayModel.popupPosition(_trayItem, mouse.x, mouse.y)
if (mouse.button === Qt.LeftButton) {
trayModel.leftButtonClick(model.id, pos.x, pos.y)
} else if (mouse.button === Qt.RightButton) {
trayModel.rightButtonClick(model.id, _trayItem, pos.x, pos.y)
} else if (mouse.button === Qt.MiddleButton) {
trayModel.middleButtonClick(model.id, pos.x, pos.y)
}
}
popupText: model.toolTip ? model.toolTip : model.title
}
}
StandardItem {
id: controler
checked: controlCenter.visible
animationEnabled: true
Layout.fillHeight: true
Layout.preferredWidth: _controlerLayout.implicitWidth + FishUI.Units.largeSpacing
onClicked: {
toggleDialog()
}
function toggleDialog() {
if (controlCenter.visible)
controlCenter.close()
else {
// 先初始化用户可能会通过Alt鼠标左键移动位置
controlCenter.position = Qt.point(0, 0)
controlCenter.position = mapToGlobal(0, 0)
controlCenter.open()
}
}
RowLayout {
id: _controlerLayout
anchors.fill: parent
anchors.leftMargin: FishUI.Units.smallSpacing
anchors.rightMargin: FishUI.Units.smallSpacing
spacing: FishUI.Units.largeSpacing
Image {
id: volumeIcon
visible: controlCenter.defaultSink
source: "qrc:/images/" + (rootItem.darkMode ? "dark/" : "light/") + controlCenter.volumeIconName + ".svg"
width: rootItem.iconSize
height: width
sourceSize: Qt.size(width, height)
asynchronous: true
Layout.alignment: Qt.AlignCenter
antialiasing: true
smooth: false
}
Image {
id: wirelessIcon
width: rootItem.iconSize
height: width
sourceSize: Qt.size(width, height)
source: activeConnection.wirelessIcon ? "qrc:/images/" + (rootItem.darkMode ? "dark/" : "light/") + activeConnection.wirelessIcon + ".svg" : ""
asynchronous: true
Layout.alignment: Qt.AlignCenter
visible: enabledConnections.wirelessHwEnabled &&
enabledConnections.wirelessEnabled &&
activeConnection.wirelessName &&
wirelessIcon.status === Image.Ready
antialiasing: true
smooth: false
}
// Battery Item
RowLayout {
visible: battery.available
Image {
id: batteryIcon
height: rootItem.iconSize
width: height + 6
sourceSize: Qt.size(width, height)
source: "qrc:/images/" + (rootItem.darkMode ? "dark/" : "light/") + battery.iconSource
Layout.alignment: Qt.AlignCenter
antialiasing: true
smooth: false
}
Label {
text: battery.chargePercent + "%"
font.pointSize: rootItem.fontSize
color: rootItem.textColor
visible: battery.showPercentage
}
}
Image {
id: shutdownIcon
width: rootItem.iconSize
height: width
sourceSize: Qt.size(width, height)
source: "qrc:/images/" + (rootItem.darkMode ? "dark/" : "light/") + "system-shutdown-symbolic.svg"
asynchronous: true
Layout.alignment: Qt.AlignCenter
visible: !batteryIcon.visible
antialiasing: true
smooth: false
}
}
}
// Pop-up notification center and calendar
StandardItem {
id: datetimeItem
animationEnabled: true
Layout.fillHeight: true
Layout.preferredWidth: _dateTimeLayout.implicitWidth + FishUI.Units.smallSpacing
onClicked: {
process.startDetached("cutefish-notificationd", ["-s"])
}
RowLayout {
id: _dateTimeLayout
anchors.fill: parent
// Image {
// width: rootItem.iconSize
// height: width
// sourceSize: Qt.size(width, height)
// source: "qrc:/images/" + (rootItem.darkMode ? "dark/" : "light/") + "notification-symbolic.svg"
// asynchronous: true
// Layout.alignment: Qt.AlignCenter
// antialiasing: true
// smooth: false
// }
Label {
id: timeLabel
Layout.alignment: Qt.AlignCenter
font.pointSize: rootItem.fontSize
color: rootItem.textColor
Timer {
id: timeTimer
interval: 1000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
timeLabel.text = new Date().toLocaleTimeString(Qt.locale(), StatusBar.twentyFourTime ? rootItem.timeFormat
: Locale.ShortFormat)
}
}
}
}
}
}
MouseArea {
id: _sliding
anchors.fill: parent
z: -1
property int startY: -1
property bool activated: false
onActivatedChanged: {
// TODO
// if (activated)
// acticity.move()
}
onPressed: {
startY = mouse.y
}
onReleased: {
startY = -1
}
onDoubleClicked: {
acticity.toggleMaximize()
}
onMouseYChanged: {
if (startY === parseInt(mouse.y)) {
activated = false
return
}
// Up
if (startY > parseInt(mouse.y)) {
activated = false
return
}
if (mouse.y > rootItem.height)
activated = true
else
activated = false
}
}
// Components
ControlCenter {
id: controlCenter
}
NM.ActiveConnection {
id: activeConnection
}
NM.EnabledConnections {
id: enabledConnections
}
NM.Handler {
id: nmHandler
}
}