PlayListEntry.qml 12.1 KB
Newer Older
1
/*
Matthieu Gallien's avatar
Matthieu Gallien committed
2
3
4
   SPDX-FileCopyrightText: 2016 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>

   SPDX-License-Identifier: LGPL-3.0-or-later
5
6
 */

Alexander Stippich's avatar
Alexander Stippich committed
7
import QtQuick 2.7
8
import QtQuick.Layouts 1.2
9
import QtQuick.Controls 2.3
10
11
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
12
import org.kde.kirigami 2.5 as Kirigami
13
import org.kde.elisa 1.0
14

15
FocusScope {
16
    id: playListEntry
17

18
    property var index
19
    property bool isSingleDiscAlbum
20
    property int isPlaying
21
    property bool isSelected
22
    property bool isValid
23
    property bool isAlternateColor
24
    property bool containsMouse
25
    property int databaseId: 0
26
    property var entryType
27
28
29
30
31
    property string title
    property string artist
    property string album
    property string albumArtist
    property string duration
32
    property url fileName
33
34
35
36
37
    property url imageUrl
    property int trackNumber
    property int discNumber
    property int rating
    property bool hasValidDiscNumber: true
38
    property int scrollBarWidth
39
    property bool simpleMode: false
40

41
    signal startPlayback()
42
    signal pausePlayback()
43
44
45
    signal removeFromPlaylist(var trackIndex)
    signal switchToTrack(var trackIndex)

46
47
48
    Accessible.role: Accessible.ListItem
    Accessible.name: title + ' ' + album + ' ' + artist

49
50
51
52
    Keys.onReturnPressed: {
        playListEntry.switchToTrack(playListEntry.index)
        playListEntry.startPlayback()
    }
53

54
    height: Kirigami.Units.gridUnit + 3 * Kirigami.Units.smallSpacing
55

56
57
58
    Loader {
        id: metadataLoader
        active: false
59
        onLoaded: item.show()
60
61

        sourceComponent:  MediaTrackMetadataView {
62
            fileName: playListEntry.fileName
63
            showImage: entryType !== ElisaUtils.Radio
64
            modelType: entryType
65
66
67
68
            showTrackFileName: entryType !== ElisaUtils.Radio
            showDeleteButton: entryType === ElisaUtils.Radio
            showApplyButton: entryType === ElisaUtils.Radio
            editableMetadata: entryType === ElisaUtils.Radio
69
70

            onRejected: metadataLoader.active = false
71
72
73
        }
    }

74
75
    Rectangle {
        id: entryBackground
76

77
        anchors.fill: parent
78
        anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0
79
        z: 1
80

81
        color: simpleMode ? "transparent" : myPalette.base
82

Alexander Stippich's avatar
Alexander Stippich committed
83
        height: playListEntry.height
84
    }
stef lep's avatar
stef lep committed
85
86
87
88
89
90
91
    Loader {
        active: isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused
        visible: active
        z: 2
        anchors.fill: parent

        sourceComponent: Rectangle {
92
            property int pos: ElisaApplication.audioPlayer.position
stef lep's avatar
stef lep committed
93
94
95
96

            anchors.left: parent.left
            color: myPalette.mid
            height: playListEntry.height
97
            width: playListEntry.width * (pos/ElisaApplication.audioPlayer.duration)
stef lep's avatar
stef lep committed
98
99
        }
    }
100

101
102
    RowLayout {
        id: trackRow
stef lep's avatar
stef lep committed
103
        z: 3
104

105
        anchors.fill: parent
106
        anchors.leftMargin: Kirigami.Units.largeSpacing
107
        anchors.rightMargin: LayoutMirroring.enabled ? scrollBarWidth : 0
108

109
        spacing: Kirigami.Units.smallSpacing / 2
110

111
        // Container for the play/pause icon and the track/disc label
112
        Item {
113
114
115
116
            TextMetrics {
                id: fakeLabel
                text: '99/9'
            }
117

118
119
120
            Layout.minimumWidth: fakeLabel.width
            Layout.preferredWidth: fakeLabel.width
            Layout.maximumWidth: fakeLabel.width
Alexander Stippich's avatar
Alexander Stippich committed
121
            Layout.preferredHeight: playListEntry.height
122
            Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
123
124
            Layout.leftMargin: !LayoutMirroring.enabled ? Kirigami.Units.smallSpacing : 0
            Layout.rightMargin: LayoutMirroring.enabled ? Kirigami.Units.smallSpacing : 0
125

126
127
            Image {
                id: playIcon
128

129
                anchors.centerIn: parent
130

131
132
                source: (isPlaying === MediaPlayList.IsPlaying ?
                             Qt.resolvedUrl(elisaTheme.playingIndicatorIcon) : Qt.resolvedUrl(elisaTheme.pausedIndicatorIcon))
133

134
135
136
137
                width: Kirigami.Units.iconSizes.smallMedium
                height: Kirigami.Units.iconSizes.smallMedium
                sourceSize.width: Kirigami.Units.iconSizes.smallMedium
                sourceSize.height: Kirigami.Units.iconSizes.smallMedium
138
139
                fillMode: Image.PreserveAspectFit
                mirror: LayoutMirroring.enabled
140
141
142
143
144
145
146

                layer.enabled: simpleMode
                layer.effect: ColorOverlay {
                    cached: true

                    color: myPalette.highlightedText
                }
147

148
                visible: isPlaying === MediaPlayList.IsPlaying || isPlaying === MediaPlayList.IsPaused
149
            }
150

151
152
153
154
            Label {
                id: trackAndDiscNumberLabel

                anchors.fill: parent
155
156
                anchors.rightMargin: LayoutMirroring.enabled ? 0 : Kirigami.Units.largeSpacing
                anchors.leftMargin: !LayoutMirroring.enabled ? 0 : Kirigami.Units.largeSpacing
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

                horizontalAlignment: Text.AlignRight

                text: {
                    var trackNumberString;
                    if (trackNumber !== -1) {
                        trackNumberString = Number(trackNumber).toLocaleString(Qt.locale(), 'f', 0);
                    } else {
                        trackNumberString = ''
                    }
                    if (!isSingleDiscAlbum && discNumber !== 0 ) {
                        return trackNumberString + "/" + Number(discNumber).toLocaleString(Qt.locale(), 'f', 0)
                    } else {
                        return trackNumberString
                    }
                }
173

174
175
                font.weight: (isPlaying ? Font.Bold : Font.Light)
                color: simpleMode ? myPalette.highlightedText : myPalette.text
176

177
                visible: isValid && !playIcon.visible
178
179
            }
        }
180

181
182
        LabelWithToolTip {
            id: mainCompactLabel
183

184
            text: title
185

186
            font.weight: (isPlaying ? Font.Bold : Font.Normal)
187
            color: simpleMode ? myPalette.highlightedText : myPalette.text
188

189
190
191
            Layout.maximumWidth: mainCompactLabel.implicitWidth + 1
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
192

193
            visible: isValid
194

195
196
197
            elide: Text.ElideRight
            horizontalAlignment: Text.AlignLeft
        }
198

199
200
        LabelWithToolTip {
            id: mainInvalidCompactLabel
201

202
            text: title
203

204
            color: simpleMode ? myPalette.highlightedText : myPalette.text
205

206
207
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
208

209
            visible: !isValid
210

211
212
            elide: Text.ElideRight
        }
213

214
215
216
217
        Item {
            Layout.fillWidth: true
            Layout.preferredWidth: 0
        }
218

219
220
221
222
        Loader {
            id: hoverLoader
            active: false
            visible: active
223

224
            Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
225

226
227
            sourceComponent: Row {
                anchors.centerIn: parent
228
229
                enabled: isValid

230
231
232
                FlatButtonWithToolTip {
                    id: infoButton
                    objectName: 'infoButton'
233

Alexander Stippich's avatar
Alexander Stippich committed
234
235
                    implicitHeight: playListEntry.height
                    implicitWidth: playListEntry.height
236

237
238
239
240
241
242
243
244
245
246
247
                    text: i18nc("Show track metadata", "View Details")
                    icon.name: "help-about"
                    onClicked: {
                        if (metadataLoader.active === false) {
                            metadataLoader.active = true
                        }
                        else {
                            metadataLoader.item.close();
                            metadataLoader.active = false
                        }
                    }
248
                }
249

250
251
252
                FlatButtonWithToolTip {
                    id: playPauseButton
                    objectName: 'playPauseButton'
253

Alexander Stippich's avatar
Alexander Stippich committed
254
255
                    implicitHeight: playListEntry.height
                    implicitWidth: playListEntry.height
256

257
                    scale: LayoutMirroring.enabled ? -1 : 1 // We can mirror the symmetrical pause icon
258

259
260
261
262
263
264
265
266
                    text: (isPlaying === MediaPlayList.IsPlaying) ? i18nc("Pause current track from play list", "Pause") : i18nc("Play this track from play list", "Play")
                    icon.name: (isPlaying === MediaPlayList.IsPlaying) ? "media-playback-pause" : "media-playback-start"
                    onClicked: if (isPlaying === MediaPlayList.IsPlaying) {
                        playListEntry.pausePlayback()
                    } else {
                        playListEntry.switchToTrack(playListEntry.index)
                        playListEntry.startPlayback()
                    }
267
                }
268

269
270
271
                FlatButtonWithToolTip {
                    id: removeButton
                    objectName: 'removeButton'
272

Alexander Stippich's avatar
Alexander Stippich committed
273
274
                    implicitHeight: playListEntry.height
                    implicitWidth: playListEntry.height
275
276
277
278

                    text: i18nc("Remove current track from play list", "Remove")
                    icon.name: "error"
                    onClicked: playListEntry.removeFromPlaylist(playListEntry.index)
279
280
281
                }

            }
282
        }
283

284
285
        RatingStar {
            id: ratingWidget
286

287
            starRating: rating
288

289
290
            visible: rating > 0
        }
291

292
293
        LabelWithToolTip {
            id: durationLabel
Safa AlFulaij's avatar
Safa AlFulaij committed
294

295
            text: duration
296

297
            font.weight: (isPlaying ? Font.Bold : Font.Normal)
298
            color: simpleMode ? myPalette.highlightedText : myPalette.text
299

300
            Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
301
302
            Layout.leftMargin: Kirigami.Units.largeSpacing
            Layout.rightMargin: Kirigami.Units.largeSpacing
Safa AlFulaij's avatar
Safa AlFulaij committed
303

304
            horizontalAlignment: Text.AlignRight
305
        }
306
    }
307

308
309
310
    states: [
        State {
            name: 'notSelected'
311
            when: !containsMouse && !isSelected && !playListEntry.activeFocus && !simpleMode
312
            PropertyChanges {
313
314
                target: hoverLoader
                active: false
315
            }
316
            PropertyChanges {
317
                target: entryBackground
318
                color: (isAlternateColor ? myPalette.alternateBase : myPalette.base)
319
            }
320
321
322
323
            PropertyChanges {
                target: entryBackground
                opacity: 1.
            }
324
325
326
327
            PropertyChanges {
                target: ratingWidget
                hoverWidgetOpacity: 0.0
            }
328
        },
329
        State {
330
            name: 'hovered'
331
            when: containsMouse && !playListEntry.activeFocus && !simpleMode
332
            PropertyChanges {
333
334
                target: hoverLoader
                active: true
335
            }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
            PropertyChanges {
                target: entryBackground
                color: myPalette.highlight
            }
            PropertyChanges {
                target: entryBackground
                opacity: 0.2
            }
            PropertyChanges {
                target: ratingWidget
                hoverWidgetOpacity: 1.0
            }
        },
        State {
            name: 'selected'
351
            when: !playListEntry.activeFocus && isSelected && !simpleMode
352
            PropertyChanges {
353
354
                target: hoverLoader
                active: false
355
            }
356
            PropertyChanges {
357
                target: entryBackground
358
                color: myPalette.mid
359
            }
360
361
362
363
364
365
366
367
368
369
370
            PropertyChanges {
                target: entryBackground
                opacity: 1.
            }
            PropertyChanges {
                target: ratingWidget
                hoverWidgetOpacity: 1.0
            }
        },
        State {
            name: 'focused'
371
            when: playListEntry.activeFocus && !simpleMode
372
            PropertyChanges {
373
374
                target: hoverLoader
                active: true
375
376
377
378
379
380
381
382
383
            }
            PropertyChanges {
                target: entryBackground
                color: myPalette.highlight
            }
            PropertyChanges {
                target: entryBackground
                opacity: 0.6
            }
384
385
386
387
            PropertyChanges {
                target: ratingWidget
                hoverWidgetOpacity: 1.0
            }
388
389
        }
    ]
390
391
}