melawy-plasma-plasmoid-Menu.../DeepinMenu.Classic/contents/ui/MenuRepresentation.qml

891 lines
34 KiB
QML

/*
* SPDX-FileCopyrightText: zayronxio
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents3
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.kicker as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
//import org.kde.plasma.private.shell
import org.kde.plasma.private.sessions as Sessions
import org.kde.kwindowsystem
import org.kde.kquickcontrolsaddons
import org.kde.plasma.private.quicklaunch
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import org.kde.plasma.plasma5support as P5Support
import org.kde.kcmutils as KCM
import Qt5Compat.GraphicalEffects
Item {
id: main
property var locale: Qt.locale()
property int sizeImage: Kirigami.Units.iconSizes.large * 2
property int menuPos: 0
property int showApps: Plasmoid.configuration.viewUser ? 0 : 1
onVisibleChanged: {
root.visible = !root.visible
}
PlasmaExtras.Menu {
id: contextMenu
PlasmaExtras.MenuItem {
action: Plasmoid.internalAction("configure")
}
}
Plasmoid.status: root.visible ? PlasmaCore.Types.RequiresAttentionStatus : PlasmaCore.Types.PassiveStatus
PlasmaCore.Dialog {
id: root
objectName: "popupWindow"
flags: Qt.WindowStaysOnTopHint
//flags: Qt.Dialog | Qt.FramelessWindowHint
location: PlasmaCore.Types.Floating
hideOnWindowDeactivate: true
property int iconSize: Kirigami.Units.iconSizes.large
property int cellSizeHeight: iconSize
+ Kirigami.Units.gridUnit * 2
+ (2 * Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom,
highlightItemSvg.margins.left + highlightItemSvg.margins.right))
property int cellSizeWidth: cellSizeHeight
property bool searching: (searchField.text != "")
property bool showFavorites
onVisibleChanged: {
if (visible) {
root.showFavorites = Plasmoid.configuration.showFavoritesFirst
var pos = popupPosition(width, height);
x = pos.x;
y = pos.y;
reset();
animation1.start()
}else{
rootItem.opacity = 0
}
}
onHeightChanged: {
var pos = popupPosition(width, height);
x = pos.x;
y = pos.y;
}
onWidthChanged: {
var pos = popupPosition(width, height);
x = pos.x;
y = pos.y;
}
function toggle(){
main.visible = !main.visible
}
function reset() {
searchField.text = "";
if(showFavorites)
globalFavoritesGrid.tryActivate(0,0)
else
mainColumn.visibleGrid.tryActivate(0,0)
}
function popupPosition(width, height) {
var screenAvail = kicker.availableScreenRect;
var screen = kicker.screenGeometry;
var panelH = kicker.height
var panelW = kicker.width
var horizMidPoint = screen.x + (screen.width / 2);
var vertMidPoint = screen.y + (screen.height / 2);
var appletTopLeft = parent.mapToGlobal(0, 0);
var offset = Kirigami.Units.smallSpacing * 2;
if (Plasmoid.configuration.displayPosition === 1) {
horizMidPoint = screen.x + (screen.width / 2);
vertMidPoint = screen.y + (screen.height / 2);
x = horizMidPoint - width / 2;
y = vertMidPoint - height / 2;
}
else if (Plasmoid.configuration.displayPosition === 2) {
horizMidPoint = screen.x + (screen.width / 2);
vertMidPoint = screen.y + (screen.height / 2);
x = horizMidPoint - width / 2;
// y = screen.y + screen.height - height - offset - panelH - Kirigami.Units.gridUnit;
// y = screen.y + screen.height - height - offset - panelH - Kirigami.Units.gridUnit / 2;
y = screen.y + screen.height - height - offset - panelH - Kirigami.Units.largeSpacing * 1.5;
}
else {
switch (plasmoid.location) {
case PlasmaCore.Types.BottomEdge:
var y = appletTopLeft.y - height - offset
var x = appletTopLeft.x
break;
case PlasmaCore.Types.TopEdge:
x = appletTopLeft.x < screen.width - width ? appletTopLeft.x + panelW - Kirigami.Units.gridUnit / 3 : screen.width - width;
y = appletTopLeft.y + kicker.height + Kirigami.Units.gridUnit
break;
case PlasmaCore.Types.LeftEdge:
x = appletTopLeft.x + panelW + Kirigami.Units.gridUnit / 2;
y = appletTopLeft.y < screen.height - height ? appletTopLeft.y : appletTopLeft.y - height + iconUser.height / 2;
break;
case PlasmaCore.Types.RightEdge:
x = appletTopLeft.x - width - Kirigami.Units.gridUnit / 2;
y = appletTopLeft.y < screen.height - height ? appletTopLeft.y : screen.height - height - Kirigami.Units.gridUnit / 5;
break;
default:
return;
}
}
return Qt.point(x, y);
}
FocusScope {
id: rootItem
Layout.minimumWidth: Kirigami.Units.gridUnit*30
Layout.maximumWidth: minimumWidth
Layout.minimumHeight: (root.cellSizeHeight * Plasmoid.configuration.numberRows) + searchField.implicitHeight + (Plasmoid.configuration.viewUser ? main.sizeImage*0.5 : Kirigami.Units.gridUnit * 1.5 ) + Kirigami.Units.gridUnit * 5
Layout.maximumHeight: (root.cellSizeHeight * Plasmoid.configuration.numberRows) + searchField.implicitHeight + (Plasmoid.configuration.viewUser ? main.sizeImage*0.5 : Kirigami.Units.gridUnit * 1.5 ) + Kirigami.Units.gridUnit * 5
focus: true
Sessions.SessionManagement {
id: sm
}
Sessions.SessionsModel {
id: sessionsModel
}
KCoreAddons.KUser { id: kuser }
Logic { id: logic }
OpacityAnimator { id: animation1; target: rootItem; from: 0; to: 1; easing.type: Easing.InOutQuad; }
P5Support.DataSource {
id: executable
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(sourceName, exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
if (cmd) {
connectSource(cmd)
}
}
signal exited(string cmd, int exitCode, int exitStatus, string stdout, string stderr)
}
PlasmaExtras.Highlight {
id: delegateHighlight
visible: false
z: -1 // otherwise it shows ontop of the icon/label and tints them slightly
}
Kirigami.Heading {
id: dummyHeading
visible: false
width: 0
level: 5
}
TextMetrics {
id: headingMetrics
font: dummyHeading.font
}
Item {
id : headingSvg
width: parent.height + backgroundSvg.margins.bottom + backgroundSvg.margins.top
//height: root.cellSizeHeight * Plasmoid.configuration.numberRows + Kirigami.Units.gridUnit * 2 + backgroundSvg.margins.bottom - 1 //<>+ paginationBar.height
height: parent.width*.4 + backgroundSvg.margins.left
}
RowLayout {
id: rowSearchField
width: parent.width*.4
anchors{
top: parent.top
topMargin: Kirigami.Units.gridUnit*1
left: parent.left
leftMargin: (parent.width*.6 - width)/2
margins: Kirigami.Units.smallSpacing
}
PlasmaComponents3.TextField {
id: searchField
Layout.fillWidth: true
placeholderText: i18n("Type here to search ...")
topPadding: 10
bottomPadding: 10
leftPadding: ((parent.width - width)/2) + Kirigami.Units.iconSizes.small*2
text: ""
font.pointSize: Kirigami.Theme.defaultFont.pointSize
onTextChanged: {
runnerModel.query = text;
}
Keys.onPressed: (event)=> {
if (event.key === Qt.Key_Escape) {
event.accepted = true;
if(root.searching){
searchField.clear()
} else {
root.toggle()
}
}
if (event.key === Qt.Key_Down || event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
event.accepted = true;
if(root.showFavorites)
globalFavoritesGrid.tryActivate(0,0)
else
mainColumn.visibleGrid.tryActivate(0,0)
}
}
function backspace() {
if (!root.visible) {
return;
}
focus = true;
text = text.slice(0, -1);
}
function appendText(newText) {
if (!root.visible) {
return;
}
focus = true;
text = text + newText;
}
Kirigami.Icon {
source: 'search'
anchors {
left: searchField.left
verticalCenter: searchField.verticalCenter
leftMargin: Kirigami.Units.smallSpacing * 2
}
height: Kirigami.Units.iconSizes.small
width: height
}
}
Item {
Layout.fillWidth: true
}
}
Item {
id: selectorAppsFavsOrAll
width: (parent.width - places.width)*.85
height: 30
anchors.left: parent.left
anchors.leftMargin: 15
anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.gridUnit*1.5
Row {
height: parent.height
width: parent.width
Rectangle {
id: baseIcon
color: Kirigami.Theme.textColor
opacity: 0.35
height: 24
width: height
radius: height/2
anchors.verticalCenter: parent.verticalCenter
Row {
width: parent.width*.8
height: 24
spacing: height/6
anchors.horizontalCenter: parent.horizontalCenter
Repeater {
model: ListModel {
ListElement { name: "one" }
ListElement { name: "two" }
ListElement { name: "three" }
}
Rectangle {
color: Kirigami.Theme.textColor
width: parent.width/5
height: width
radius: height/2
anchors.verticalCenter: parent.verticalCenter
}
}
}
MouseArea {
width: parent.width
height: parent.height
anchors.centerIn: baseIcon
onClicked: {
var apps = showApps
showApps = apps === 0 ? 1 : 0
}
}
}
Text {
height: selectorAppsFavsOrAll.height
text: showApps === 0 ? i18n("All apps") : i18n("Favorites")
font.pixelSize: 12
anchors.left: parent.left
anchors.leftMargin: baseIcon.width*1.5
color: Kirigami.Theme.textColor
verticalAlignment: Text.AlignVCenter
MouseArea {
width: parent.width
height: parent.height
anchors.centerIn: parent
onClicked: {
var apps = showApps
showApps = apps === 0 ? 1 : 0
}
}
}
Kirigami.Icon {
id: arrow
source: showApps === 1 ? "arrow-left" : "arrow-right"
width: 22
height: 22
anchors.right: parent.right
anchors.rightMargin: width
MouseArea {
width: parent.width
height: parent.height
anchors.centerIn: parent
onClicked: {
var apps = showApps
showApps = apps === 0 ? 1 : 0
}
}
}
}
}
ItemGridView {
id: globalFavoritesGrid
visible: showApps === 0
anchors {
top: rowSearchField.bottom
topMargin: Kirigami.Units.gridUnit * 2
}
dragEnabled: true
dropEnabled: true
width: rootItem.width*.6
height: root.cellSizeHeight * Plasmoid.configuration.numberRows
focus: true
cellWidth: root.width*.6
cellHeight: 48
iconSize: 32
onKeyNavUp: searchField.focus = true
Keys.onPressed:(event)=> {
if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){
searchField.focus = true;
return
}
if (event.key === Qt.Key_Tab) {
event.accepted = true;
searchField.focus = true
}
}
}
PlasmaCore.Dialog {
id: dialog
width: main.sizeImage*.85
height: width
visible: root.visible
y: root.y + sizeImage/3
x: root.x + root.width*.68
objectName: "popupWindowIcon"
//flags: Qt.WindowStaysOnTopHint
type: "Notification"
location: PlasmaCore.Types.Floating
hideOnWindowDeactivate: false
backgroundHints: PlasmaCore.Dialog.NoBackground
mainItem: Rectangle {
width: main.sizeImage*.7
height: width
color: 'transparent'
Rectangle {
id: mask
width: parent.width
height: parent.height
visible: false
radius: height/2
}
Image {
id: iconUser
source: kuser.faceIconUrl
cache: false
visible: source !== "" && Plasmoid.configuration.viewUser
width: parent.width
height: parent.height
fillMode: Image.PreserveAspectFit
layer.enabled:true
state: "hide"
states: [
State {
name: "show"
when: dialog.visible
PropertyChanges { target: iconUser; y: 0; opacity: 1; }
},
State {
name: "hide"
when: !dialog.visible
PropertyChanges { target: iconUser; y: sizeImage/3 ; opacity: 0; }
}
]
transitions: Transition {
PropertyAnimation { properties: "opacity,y"; easing.type: Easing.InOutQuad; }
}
layer.effect: OpacityMask {
maskSource: mask
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: KCM.KCMLauncher.openSystemSettings("kcm_users")
}
}
}
}
Column {
id: greetingUser
width: headingSvg.height*.8
height: 20
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: dialog.height + Kirigami.Units.largeSpacing * 2
Item {
width: textuser.implicitWidth
height: textuser.implicitHeight
visible: true
anchors.top: parent.top
anchors.left: parent.left
Text {
width: parent.width
height: 20
id: textuser
text: i18n("Hi, ")+ kuser.fullName
font.bold: true
font.pixelSize: 16
color: Kirigami.Theme.textColor
}
}
}
Column {
id: places
width: headingSvg.height*.8
height: parent.height - dialog.height / 2 - Kirigami.Units.gridUnit * 5.5
anchors.right: parent.right
anchors.bottom: parent.bottom
ListModel {
id: placeModel
ListElement {
type: "place"
label: "Home"
icon: "user-home-symbolic"
command: "xdg-open $HOME"
}
ListElement {
type: "place"
label: "Downloads"
icon: "folder-downloads-symbolic"
command: "xdg-open $(xdg-user-dir DOWNLOAD)"
}
ListElement {
type: "place"
label: "Documents"
icon: "folder-documents-symbolic"
command: "xdg-open $(xdg-user-dir DOCUMENTS)"
}
ListElement {
type: "place"
label: "Music"
icon: "folder-music-symbolic"
command: "xdg-open $(xdg-user-dir MUSIC)"
}
ListElement {
type: "place"
label: "Pictures"
icon: "folder-pictures-symbolic"
command: "xdg-open $(xdg-user-dir PICTURES)"
}
ListElement {
type: "place"
label: "Videos"
icon: "folder-videos-symbolic"
command: "xdg-open $(xdg-user-dir VIDEOS)"
}
ListElement {
type: "separator"
label: ""
icon: ""
command: ""
}
ListElement {
type: "shortcut"
label: "System Preferences"
icon: "systemsettings"
command: "xdg-open systemsettings://"
}
ListElement {
type: "shortcut"
label: "Personalization"
icon: "preferences-desktop-theme-global"
command: "xdg-open systemsettings://kcm_colors"
}
ListElement {
type: "shortcut"
label: "Devices and Printers"
icon: "preferences-devices-printer"
command: "xdg-open systemsettings://kcm_printer_manager"
}
ListElement {
type: "shortcut"
label: "Update Software"
icon: "software-updates-updates"
command: "plasma-discover --mode update"
}
ListElement {
type: "shortcut"
label: "Help and Support"
icon: "system-help"
command: "xdg-open https://discuss.kde.org/?source=vinyl-launcher"
}
}
Component {
id: placeDelegate
Item {
property double lineSpacing: 2.0
property double textLineSpacing: 1.9
height: Kirigami.Units.iconSizes.small * lineSpacing
width: parent.width
Column {
Row {
Text {
property var i18nDomain: (type === "place") ?
"xdg-user-dirs" :
"plasma_applet_DeepinMenu.Classic"
verticalAlignment: Text.AlignVCenter
height: Kirigami.Units.iconSizes.small * textLineSpacing
leftPadding: Kirigami.Units.iconSizes.small * textLineSpacing +
Kirigami.Units.largeSpacing
font.pointSize: Kirigami.Theme.defaultFont.pointSize
color: Kirigami.Theme.textColor
text: (label !== "") ? i18nd(i18nDomain, label) : model.label
Kirigami.Icon {
source: model.icon
height: Kirigami.Units.iconSizes.small * textLineSpacing
width: Kirigami.Units.iconSizes.small * textLineSpacing
color: Kirigami.Theme.textColor
}
MouseArea {
width: parent.width
height: parent.height
anchors.centerIn: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
executable.exec(command);
}
}
}
}
}
}
}
Component {
id: lineSeparator
Rectangle {
width: parent.width
height: Kirigami.Units.iconSizes.small * 3
color: "transparent"
KSvg.SvgItem {
anchors.verticalCenter: parent.verticalCenter
imagePath: "widgets/line"
elementId: "horizontal-line"
width: parent.width
height: 1
}
}
}
Column {
width: parent.width
height: parent.height
ListView {
id: placesView
width: parent.width
height: parent.height
model: placeModel
delegate: placeDelegate
}
}
}
RowLayout {
id: shutdownIcons
spacing: Kirigami.Units.largeSpacing
anchors.bottom: parent.bottom
anchors.bottomMargin: Kirigami.Units.largeSpacing * 4
anchors.right: parent.right
anchors.rightMargin: parent.width*.2 - width/2
// PlasmaComponents3.ToolButton {
// icon.name: "configure"
// onClicked: logic.openUrl("file:///usr/share/applications/systemsettings.desktop")
// ToolTip.delay: 1000
// ToolTip.timeout: 1000
// ToolTip.visible: hovered
// ToolTip.text: i18n("System Preferences")
// }
PlasmaComponents3.ToolButton {
height: Kirigami.Units.iconSizes.small * 1.5
icon.name: "system-lock-screen-symbolic"
//onClicked: pmEngine.performOperation("lockScreen")
//enabled: pmEngine.data["Sleep States"]["LockScreen"]
onClicked: sm.lock()
ToolTip.delay: 200
ToolTip.timeout: 1000
ToolTip.visible: hovered
ToolTip.text: i18n("Lock Screen")
}
PlasmaComponents3.ToolButton {
height: Kirigami.Units.iconSizes.small * 1.5
icon.name: "system-switch-user-symbolic"
onClicked: sm.switchUser()
ToolTip.delay: 200
ToolTip.timeout: 1000
ToolTip.visible: hovered
ToolTip.text: i18n("Switch User")
}
PlasmaComponents3.ToolButton {
height: Kirigami.Units.iconSizes.small * 1.5
icon.name: "system-shutdown-symbolic"
// onClicked: sm.requestShutdown()
onClicked: sm.requestLogoutPrompt()
ToolTip.delay: 200
ToolTip.timeout: 1000
ToolTip.visible: hovered
ToolTip.text: i18n("Shutdown")
}
}
Item {
id: mainGrids
visible: !globalFavoritesGrid.visible
anchors {
top: rowSearchField.bottom
topMargin: Kirigami.Units.gridUnit * 2
//left: parent.left
//right: parent.right
}
width: rootItem.width
height: root.cellSizeHeight * Plasmoid.configuration.numberRows
Item {
id: mainColumn
//width: root.cellSize * Plasmoid.configuration.numberColumns + Kirigami.Units.gridUnit
width: rootItem.width
height: root.cellSizeHeight * Plasmoid.configuration.numberRows
property Item visibleGrid: allAppsGrid
function tryActivate(row, col) {
if (visibleGrid) {
visibleGrid.tryActivate(row, col);
}
}
ItemGridView {
id: allAppsGrid
//width: root.cellSize * Plasmoid.configuration.numberColumns + Kirigami.Units.gridUnit
width: rootItem.width*.6
Layout.maximumWidth: rootItem.width*.6
height: root.cellSizeHeight * Plasmoid.configuration.numberRows
cellWidth: root.width*.6
cellHeight: 48
iconSize: 32
enabled: (opacity == 1) ? 1 : 0
z: enabled ? 5 : -1
dropEnabled: false
dragEnabled: false
opacity: root.searching ? 0 : 1
onOpacityChanged: {
if (opacity == 1) {
//allAppsGrid.scrollBar.flickableItem.contentY = 0;
mainColumn.visibleGrid = allAppsGrid;
}
}
onKeyNavUp: searchField.focus = true
}
ItemMultiGridView {
id: runnerGrid
width: rootItem.width*.6
height: root.cellSizeHeight * Plasmoid.configuration.numberRows
cellWidth: root.width*.6
cellHeight: 48
enabled: (opacity == 1.0) ? 1 : 0
z: enabled ? 5 : -1
model: runnerModel
grabFocus: true
opacity: root.searching ? 1.0 : 0.0
onOpacityChanged: {
if (opacity == 1.0) {
mainColumn.visibleGrid = runnerGrid;
}
}
onKeyNavUp: searchField.focus = true
}
Keys.onPressed: (event)=> {
if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){
searchField.focus = true;
return
}
if (event.key === Qt.Key_Tab) {
event.accepted = true;
searchField.focus = true
} else if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if(root.searching)
searchField.backspace();
else
searchField.focus = true
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
if(root.searching){
searchField.clear()
} else {
root.toggle()
}
} else if (event.text !== "") {
event.accepted = true;
searchField.appendText(event.text);
showApps = 1
}
}
}
}
Keys.onPressed: (event)=> {
if(event.modifiers & Qt.ControlModifier ||event.modifiers & Qt.ShiftModifier){
searchField.focus = true;
return
}
if (event.key === Qt.Key_Escape) {
event.accepted = true;
if (root.searching) {
reset();
} else {
root.visible = false;
}
return;
}
if (searchField.focus) {
return;
}
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
searchField.backspace();
} else if (event.text !== "") {
event.accepted = true;
searchField.appendText(event.text);
}
}
}
function setModels(){
globalFavoritesGrid.model = globalFavorites
allAppsGrid.model = rootModel.modelForRow(0);
}
Component.onCompleted: {
rootModel.refreshed.connect(setModels)
reset();
rootModel.refresh();
}
}
}