main.qml 9.69 KB
Newer Older
Marco Martin's avatar
Marco Martin committed
1
/*
2
3
4
5
6
    SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org>
    SPDX-FileCopyrightText: 2020 Konrad Materka <materka@gmail.com>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/
Marco Martin's avatar
Marco Martin committed
7

Marco Martin's avatar
Marco Martin committed
8
import QtQuick 2.5
Marco Martin's avatar
Marco Martin committed
9
import QtQuick.Layouts 1.1
10
import org.kde.plasma.core 2.1 as PlasmaCore
Marco Martin's avatar
Marco Martin committed
11
import org.kde.plasma.plasmoid 2.0
12
import org.kde.draganddrop 2.0 as DnD
13
import org.kde.kirigami 2.5 as Kirigami
14

15
import "items"
Marco Martin's avatar
Marco Martin committed
16
17

MouseArea {
18
    id: root
Marco Martin's avatar
Marco Martin committed
19

20
    readonly property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical
21

22
23
    Layout.minimumWidth: vertical ? PlasmaCore.Units.iconSizes.small : mainLayout.implicitWidth + PlasmaCore.Units.smallSpacing
    Layout.minimumHeight: vertical ? mainLayout.implicitHeight + PlasmaCore.Units.smallSpacing : PlasmaCore.Units.iconSizes.small
24

Marco Martin's avatar
Marco Martin committed
25
26
    LayoutMirroring.enabled: !vertical && Qt.application.layoutDirection === Qt.RightToLeft
    LayoutMirroring.childrenInherit: true
27

28
    readonly property alias systemTrayState: systemTrayState
29
    readonly property alias itemSize: tasksGrid.itemSize
30
31
    readonly property alias visibleLayout: tasksGrid
    readonly property alias hiddenLayout: expandedRepresentation.hiddenLayout
32
    readonly property bool oneRowOrColumn: tasksGrid.rowsOrColumns == 1
33

34
35
36
37
38
    onWheel: {
        // Don't propagate unhandled wheel events
        wheel.accepted = true;
    }

39
40
41
42
    SystemTrayState {
        id: systemTrayState
    }

43
44
45
46
    //being there forces the items to fully load, and they will be reparented in the popup one by one, this item is *never* visible
    Item {
        id: preloadedStorage
        visible: false
Marco Martin's avatar
Marco Martin committed
47
48
    }

Marco Martin's avatar
Marco Martin committed
49
50
    CurrentItemHighLight {
        location: plasmoid.location
51
        parent: root
Marco Martin's avatar
Marco Martin committed
52
    }
Marco Martin's avatar
Marco Martin committed
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    DnD.DropArea {
        anchors.fill: parent

        preventStealing: true;

        /** Extracts the name of the system tray applet in the drag data if present
         * otherwise returns null*/
        function systemTrayAppletName(event) {
            if (event.mimeData.formats.indexOf("text/x-plasmoidservicename") < 0) {
                return null;
            }
            var plasmoidId = event.mimeData.getDataAsByteArray("text/x-plasmoidservicename");

            if (!plasmoid.nativeInterface.isSystemTrayApplet(plasmoidId)) {
                return null;
            }
            return plasmoidId;
        }

        onDragEnter: {
            if (!systemTrayAppletName(event)) {
                event.ignore();
            }
        }

        onDrop: {
            var plasmoidId = systemTrayAppletName(event);
            if (!plasmoidId) {
                event.ignore();
                return;
            }

            if (plasmoid.configuration.extraItems.indexOf(plasmoidId) < 0) {
                var extraItems = plasmoid.configuration.extraItems;
                extraItems.push(plasmoidId);
                plasmoid.configuration.extraItems = extraItems;
            }
        }
    }

94
    //Main Layout
95
96
97
98
99
100
101
102
103
104
105
    GridLayout {
        id: mainLayout

        rowSpacing: 0
        columnSpacing: 0
        anchors.fill: parent

        flow: vertical ? GridLayout.TopToBottom : GridLayout.LeftToRight

        GridView {
            id: tasksGrid
106

107
108
109
110
111
            Layout.alignment: Qt.AlignCenter

            interactive: false //disable features we don't need
            flow: vertical ? GridView.LeftToRight : GridView.TopToBottom

112
113
            // The icon size to display when not using the auto-scaling setting
            readonly property int smallIconSize: PlasmaCore.Units.iconSizes.smallMedium
114
115
116
117

            // Automatically use autoSize setting when in tablet mode, if it's
            // not already being used
            readonly property bool autoSize: plasmoid.configuration.scaleIconsToFit || Kirigami.Settings.tabletMode
118
119
120
121

            readonly property int gridThickness: root.vertical ? root.width : root.height
            // Should change to 2 rows/columns on a 56px panel (in standard DPI)
            readonly property int rowsOrColumns: autoSize ? 1 : Math.max(1, Math.min(count, Math.floor(gridThickness / (smallIconSize + PlasmaCore.Units.smallSpacing))))
122

123
124
            // Add margins only if the panel is larger than a small icon (to avoid large gaps between tiny icons)
            readonly property int smallSizeCellLength: gridThickness < smallIconSize ? smallIconSize : smallIconSize + PlasmaCore.Units.smallSpacing * 2
125
126
            cellHeight: {
                if (root.vertical) {
127
                    return autoSize ? root.width + PlasmaCore.Units.smallSpacing : smallSizeCellLength
128
                } else {
129
                    return autoSize ? root.height : Math.floor(root.height / rowsOrColumns)
130
131
132
133
                }
            }
            cellWidth: {
                if (root.vertical) {
134
135
                    return autoSize ? root.width : Math.floor(root.width / rowsOrColumns)
                } else {
136
                    return autoSize ? root.height + PlasmaCore.Units.smallSpacing : smallSizeCellLength
137
138
139
140
141
142
143
144
145
146
147
                }
            }

            //depending on the form factor, we are calculating only one dimention, second is always the same as root/parent
            implicitHeight: root.vertical ? cellHeight * Math.ceil(count / rowsOrColumns) : root.height
            implicitWidth: !root.vertical ? cellWidth * Math.ceil(count / rowsOrColumns) : root.width

            readonly property int itemSize: {
                if (autoSize) {
                    const size = Math.min(implicitWidth / rowsOrColumns, implicitHeight / rowsOrColumns)
                    return PlasmaCore.Units.roundToIconSize(Math.min(size, PlasmaCore.Units.iconSizes.enormous))
148
                } else {
149
                    return smallIconSize
150
151
                }
            }
152
153
154
155
156
157
158

            model: PlasmaCore.SortFilterModel {
                sourceModel: plasmoid.nativeInterface.systemTrayModel
                filterRole: "effectiveStatus"
                filterCallback: function(source_row, value) {
                    return value === PlasmaCore.Types.ActiveStatus
                }
Marco Martin's avatar
Marco Martin committed
159
            }
160
161
162
163

            delegate: ItemLoader {}

            add: Transition {
164
                enabled: itemSize > 0
165
166
167
168
169
170

                NumberAnimation {
                    property: "scale"
                    from: 0
                    to: 1
                    easing.type: Easing.InOutQuad
171
                    duration: PlasmaCore.Units.longDuration
172
                }
173
            }
Marco Martin's avatar
Marco Martin committed
174

175
176
177
178
179
180
181
            displaced: Transition {
                //ensure scale value returns to 1.0
                //https://doc.qt.io/qt-5/qml-qtquick-viewtransition.html#handling-interrupted-animations
                NumberAnimation {
                    property: "scale"
                    to: 1
                    easing.type: Easing.InOutQuad
182
                    duration: PlasmaCore.Units.longDuration
183
184
185
186
187
188
189
                }
            }

            move: Transition {
                NumberAnimation {
                    properties: "x,y"
                    easing.type: Easing.InOutQuad
190
                    duration: PlasmaCore.Units.longDuration
191
192
193
194
195
196
197
198
                }
            }
        }

        ExpanderArrow {
            id: expander
            Layout.fillWidth: vertical
            Layout.fillHeight: !vertical
199
            Layout.alignment: vertical ? Qt.AlignVCenter : Qt.AlignHCenter
200
            iconSize: tasksGrid.itemSize
201
            visible: root.hiddenLayout.itemCount > 0
Marco Martin's avatar
Marco Martin committed
202
        }
Marco Martin's avatar
Marco Martin committed
203
204
    }

205
    //Main popup
Marco Martin's avatar
Marco Martin committed
206
207
    PlasmaCore.Dialog {
        id: dialog
Marco Martin's avatar
Marco Martin committed
208
        visualParent: root
209
210
        flags: Qt.WindowStaysOnTopHint
        location: plasmoid.location
211
        hideOnWindowDeactivate: !plasmoid.configuration.pin
212
        visible: systemTrayState.expanded
213
        backgroundHints: (plasmoid.containmentDisplayHints & PlasmaCore.Types.DesktopFullyCovered) ? PlasmaCore.Dialog.SolidBackground : PlasmaCore.Dialog.StandardBackground
214

Marco Martin's avatar
Marco Martin committed
215
        onVisibleChanged: {
216
            systemTrayState.expanded = visible
Marco Martin's avatar
Marco Martin committed
217
        }
Marco Martin's avatar
Marco Martin committed
218
219
        mainItem: ExpandedRepresentation {
            id: expandedRepresentation
220
221

            Keys.onEscapePressed: {
222
                systemTrayState.expanded = false
223
224
            }

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
            // Draws a line between the applet dialog and the panel
            PlasmaCore.SvgItem {
                anchors {
                    top: plasmoid.location == PlasmaCore.Types.BottomEdge ? undefined : parent.top
                    left: plasmoid.location == PlasmaCore.Types.RightEdge ? undefined : parent.left
                    right: plasmoid.location == PlasmaCore.Types.LeftEdge ? undefined : parent.right
                    bottom: plasmoid.location == PlasmaCore.Types.TopEdge ? undefined : parent.bottom
                    topMargin: plasmoid.location == PlasmaCore.Types.BottomEdge ? undefined : -dialog.margins.top
                    leftMargin: plasmoid.location == PlasmaCore.Types.RightEdge ? undefined : -dialog.margins.left
                    rightMargin: plasmoid.location == PlasmaCore.Types.LeftEdge ? undefined : -dialog.margins.right
                    bottomMargin: plasmoid.location == PlasmaCore.Types.TopEdge ? undefined : -dialog.margins.bottom
                }
                height: (plasmoid.location == PlasmaCore.Types.TopEdge || plasmoid.location == PlasmaCore.Types.BottomEdge) ? 1 : undefined
                width: (plasmoid.location == PlasmaCore.Types.LeftEdge || plasmoid.location == PlasmaCore.Types.RightEdge) ? 1 : undefined
                z: 999 /* Draw the line on top of the applet */
                elementId: (plasmoid.location == PlasmaCore.Types.TopEdge || plasmoid.location == PlasmaCore.Types.BottomEdge) ? "horizontal-line" : "vertical-line"
                svg: PlasmaCore.Svg {
                    imagePath: "widgets/line"
                }
            }

246
247
            LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
            LayoutMirroring.childrenInherit: true
Marco Martin's avatar
Marco Martin committed
248
249
250
        }
    }
}