Warning, /multimedia/elisa/src/qml/MediaPlayerControl.qml is written in an unsupported language. File is not indexed.

0001 /*
0002    SPDX-FileCopyrightText: 2016 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr>
0003    SPDX-FileCopyrightText: 2020 (c) Carson Black <uhhadd@gmail.com>
0004 
0005    SPDX-License-Identifier: LGPL-3.0-or-later
0006  */
0007 
0008 import QtQuick 2.7
0009 import QtQuick.Layouts 1.2
0010 import QtQuick.Controls 2.7
0011 import org.kde.kirigami 2.5 as Kirigami
0012 import org.kde.elisa 1.0
0013 
0014 import "shared"
0015 
0016 BasePlayerControl {
0017     id: musicWidget
0018 
0019     property alias volume: volumeSlider.value
0020     property bool isMaximized
0021     property bool isTranslucent
0022     property bool isNearCollapse
0023 
0024     signal maximize()
0025     signal minimize()
0026     /*
0027       Emmited when User uses the Item as a handle to resize the layout.
0028       y: difference to previous position
0029       offset: cursor offset (y coordinate relative to this Item, where dragging begun)
0030       */
0031     signal handlePositionChanged(int y, int offset)
0032 
0033     onIsMaximizedChanged: isMaximized ? maximize() : minimize()
0034 
0035     SystemPalette {
0036         id: myPalette
0037         colorGroup: SystemPalette.Active
0038     }
0039 
0040     Theme {
0041         id: elisaTheme
0042     }
0043 
0044     Rectangle {
0045         anchors.fill: parent
0046 
0047         Kirigami.Theme.colorSet: Kirigami.Theme.Header
0048         Kirigami.Theme.inherit: false
0049 
0050         color: isTranslucent ? myPalette.midlight : Kirigami.Theme.backgroundColor
0051         opacity: isTranslucent ? elisaTheme.mediaPlayerControlOpacity : 1.0
0052 
0053         Kirigami.Separator {
0054             anchors {
0055                 left: parent.left
0056                 right: parent.right
0057                 bottom: parent.bottom
0058             }
0059             visible: !isTranslucent
0060         }
0061 
0062         MouseArea {
0063             property int dragStartOffset: 0
0064 
0065             anchors.fill: parent
0066             cursorShape: isMaximized ? Qt.ArrowCursor : Qt.SizeVerCursor
0067 
0068             onPressed: mouse => {
0069                 dragStartOffset = mouse.y
0070             }
0071 
0072             onPositionChanged: mouse => musicWidget.handlePositionChanged(mouse.y, dragStartOffset)
0073 
0074             drag.axis: Drag.YAxis
0075             drag.threshold: 1
0076         }
0077     }
0078 
0079     RowLayout {
0080         anchors.fill: parent
0081         spacing: 0
0082 
0083         Item { implicitWidth: Math.floor(Kirigami.Units.smallSpacing / 2) }
0084 
0085         FlatButtonWithToolTip {
0086             id: minimizeMaximizeButton
0087             text: i18nc("@action:button", "Toggle Party Mode")
0088             icon.name: musicWidget.isMaximized ? "draw-arrow-up" : "draw-arrow-down"
0089             onClicked: musicWidget.isMaximized = !musicWidget.isMaximized
0090         }
0091 
0092         FlatButtonWithToolTip {
0093             id: skipBackwardButton
0094             enabled: skipBackwardEnabled
0095             text: i18nc("@action:button", "Skip Backward")
0096             icon.name: musicWidget.LayoutMirroring.enabled ? "media-skip-forward" : "media-skip-backward"
0097             onClicked: musicWidget.playPrevious()
0098         }
0099 
0100         FlatButtonWithToolTip {
0101             id: playPauseButton
0102             enabled: musicWidget.playEnabled
0103             text: musicWidget.isPlaying ? i18nc("@action:button Pause any media that is playing", "Pause") : i18nc("@action:button Start playing media", "Play")
0104             icon.name: musicWidget.isPlaying ? "media-playback-pause" : "media-playback-start"
0105             onClicked: musicWidget.isPlaying ? musicWidget.pause() : musicWidget.play()
0106         }
0107 
0108         FlatButtonWithToolTip {
0109             id: skipForwardButton
0110             enabled: skipForwardEnabled
0111             text: i18nc("@action:button skip forward in playlists", "Skip Forward")
0112             icon.name: musicWidget.LayoutMirroring.enabled ? "media-skip-backward" : "media-skip-forward"
0113             onClicked: musicWidget.playNext()
0114         }
0115 
0116         DurationSlider {
0117             Layout.fillWidth: true
0118             Layout.fillHeight: true
0119             position: musicWidget.position
0120             duration: musicWidget.duration
0121             seekable: musicWidget.seekable
0122             playEnabled: musicWidget.playEnabled
0123             onSeek: position => musicWidget.seek(position)
0124 
0125             labelColor: myPalette.text
0126         }
0127 
0128         FlatButtonWithToolTip {
0129             id: muteButton
0130             text: i18nc("@action:button", "Toggle Mute")
0131             icon.name: musicWidget.muted ? "player-volume-muted" : "player-volume"
0132             onClicked: musicWidget.muted = !musicWidget.muted
0133         }
0134 
0135         VolumeSlider {
0136             id: volumeSlider
0137             Layout.preferredWidth: elisaTheme.volumeSliderWidth
0138             Layout.maximumWidth: elisaTheme.volumeSliderWidth
0139             Layout.minimumWidth: elisaTheme.volumeSliderWidth
0140             Layout.fillHeight: true
0141 
0142             muted: musicWidget.muted
0143         }
0144 
0145         Item { implicitWidth: Kirigami.Units.largeSpacing }
0146 
0147         FlatButtonWithToolTip {
0148             id: shuffleButton
0149             text: i18nc("@action:button", "Toggle Shuffle")
0150             icon.name: "media-playlist-shuffle"
0151             checkable: true
0152             checked: ElisaApplication.mediaPlayListProxyModel.shufflePlayList
0153             onClicked: ElisaApplication.mediaPlayListProxyModel.shufflePlayList = !ElisaApplication.mediaPlayListProxyModel.shufflePlayList
0154         }
0155 
0156         FlatButtonWithToolTip {
0157             id: repeatButton
0158             text: {
0159                 const map = {
0160                     [MediaPlayListProxyModel.None]: i18nc("@info:tooltip", "Current: Don't repeat tracks"),
0161                     [MediaPlayListProxyModel.One]: i18nc("@info:tooltip", "Current: Repeat current track"),
0162                     [MediaPlayListProxyModel.Playlist]: i18nc("@info:tooltip", "Current: Repeat all tracks in playlist"),
0163                 }
0164                 return map[ElisaApplication.mediaPlayListProxyModel.repeatMode]
0165             }
0166             icon.name: {
0167                 const map = {
0168                     [MediaPlayListProxyModel.None]: "media-repeat-none",
0169                     [MediaPlayListProxyModel.One]: "media-repeat-single",
0170                     [MediaPlayListProxyModel.Playlist]: "media-repeat-all",
0171                 }
0172                 return map[ElisaApplication.mediaPlayListProxyModel.repeatMode]
0173             }
0174 
0175             down: pressed || menu.visible
0176             Accessible.role: Accessible.ButtonMenu
0177 
0178             checkable: true
0179             checked: ElisaApplication.mediaPlayListProxyModel.repeatMode !== 0
0180             onClicked: {
0181                 ElisaApplication.mediaPlayListProxyModel.repeatMode = (ElisaApplication.mediaPlayListProxyModel.repeatMode + 1) % 3
0182             }
0183             onPressAndHold: {
0184                 menu.popup()
0185             }
0186 
0187             menu: Menu {
0188                 PlaylistModeItem {
0189                     text: i18nc("@action:inmenu", "Playlist")
0190                     mode: MediaPlayListProxyModel.Playlist
0191                 }
0192                 PlaylistModeItem {
0193                     text: i18nc("@action:inmenu", "One")
0194                     mode: MediaPlayListProxyModel.One
0195                 }
0196                 PlaylistModeItem {
0197                     text: i18nc("@action:inmenu", "None")
0198                     mode: MediaPlayListProxyModel.None
0199                 }
0200             }
0201 
0202             Kirigami.Icon {
0203                 anchors {
0204                     right: parent.right
0205                     bottom: parent.bottom
0206                     margins: Kirigami.Units.smallSpacing
0207                 }
0208                 width: Math.round(Kirigami.Units.iconSizes.small / 2)
0209                 height: Math.round(Kirigami.Units.iconSizes.small / 2)
0210                 source: "arrow-down"
0211             }
0212         }
0213 
0214         FlatButtonWithToolTip {
0215             // normally toggles the playlist in contentView, but when the headerbar is too narrow to
0216             // show the playlistDrawer handle, this opens the drawer instead
0217 
0218             id: showHidePlaylistAction
0219             property bool _togglesDrawer: mainWindow.width < elisaTheme.viewSelectorSmallSizeThreshold
0220 
0221             action: Action {
0222                 checkable: true
0223                 shortcut: ElisaApplication.actionShortcut(ElisaApplication.action("toggle_playlist"))
0224                 onTriggered: {
0225                     if (showHidePlaylistAction._togglesDrawer) {
0226                         playlistDrawer.visible = !playlistDrawer.visible
0227                     } else {
0228                         contentView.showPlaylist = !contentView.showPlaylist
0229                     }
0230                 }
0231             }
0232 
0233             visible: !musicWidget.isMaximized && (!_togglesDrawer || musicWidget.isNearCollapse)
0234 
0235             display: _togglesDrawer ? AbstractButton.IconOnly : AbstractButton.TextBesideIcon
0236             text: i18nc("@action:button", "Show Playlist")
0237             icon.name: "view-media-playlist"
0238 
0239             checked: _togglesDrawer ? playlistDrawer.visible : contentView.showPlaylist
0240         }
0241 
0242         FlatButtonWithToolTip {
0243             id: menuButton
0244 
0245             function openMenu() {
0246                 if (!menu.visible) {
0247                     menu.open()
0248                 } else {
0249                     menu.dismiss()
0250                 }
0251             }
0252 
0253             text: i18nc("@action:button", "Application Menu")
0254             icon.name: "open-menu-symbolic"
0255 
0256             down: pressed || menu.visible
0257             Accessible.role: Accessible.ButtonMenu
0258 
0259             onPressed: openMenu()
0260             // Need this too because the base control sends onClicked for return/enter
0261             onClicked: openMenu()
0262 
0263             menu: ApplicationMenu {
0264                 y: menuButton.height
0265                 // without modal, clicking on menuButton will not close the menu
0266                 modal: true
0267                 dim: false
0268             }
0269         }
0270 
0271         Item {
0272             implicitWidth: Math.floor(Kirigami.Units.smallSpacing / 2)
0273         }
0274     }
0275 
0276     Component.onCompleted: {
0277         for (const element of [
0278                 menuButton,
0279                 repeatButton,
0280                 shuffleButton,
0281                 muteButton,
0282                 skipForwardButton,
0283                 skipBackwardButton,
0284                 playPauseButton,
0285                 minimizeMaximizeButton,
0286         ]) {
0287             ElisaApplication.installKeyEventFilter(element)
0288         }
0289     }
0290 }