Warning, /maui/vvave/src/widgets/FocusView.qml is written in an unsupported language. File is not indexed.

0001 import QtQuick 2.15
0002 import QtQml 2.15
0003 import QtQuick.Controls 2.15
0004 import QtQuick.Layouts 1.3
0005 
0006 import QtGraphicalEffects 1.0
0007 
0008 import org.mauikit.controls 1.3 as Maui
0009 import org.mauikit.filebrowsing 1.3 as FB
0010 
0011 import org.maui.vvave 1.0 as Vvave
0012 
0013 import "../utils/Player.js" as Player
0014 
0015 import "../widgets/InfoView"
0016 import "BabeTable"
0017 
0018 import "../db/Queries.js" as Q
0019 
0020 StackView
0021 {
0022     id: control
0023 
0024     focus: true
0025     padding: 0
0026 
0027     property alias loader: _loader
0028 
0029     readonly property string progressTimeLabel: player.transformTime((player.duration/1000) * (player.pos/player.duration))
0030     readonly property string durationTimeLabel: player.transformTime((player.duration/1000))
0031 
0032     Maui.Style.adaptiveColorSchemeSource : Vvave.Vvave.artworkUrl(currentTrack.artist, currentTrack.album)
0033 
0034     background: Rectangle
0035     {
0036         color: Maui.Theme.backgroundColor
0037 
0038         Behavior on color
0039         {
0040             Maui.ColorTransition{}
0041         }
0042 
0043         onColorChanged:
0044         {
0045             setAndroidStatusBarColor()
0046         }
0047 
0048         Loader
0049         {
0050             anchors.fill: parent
0051             active: Maui.Style.enableEffects
0052             asynchronous: true
0053 
0054             sourceComponent: Item
0055             {
0056                 Image
0057                 {
0058                     id: artworkBg
0059                     height: parent.height *3
0060                     width: parent.width *3
0061                     anchors.centerIn: parent
0062 
0063                     sourceSize.width: 400
0064                     sourceSize.height: 200
0065 
0066                     fillMode: Image.PreserveAspectCrop
0067 
0068                     asynchronous: true
0069                     cache: true
0070 
0071                     source: "image://artwork/album:"+currentTrack.artist + ":"+ currentTrack.album
0072                 }
0073 
0074                 FastBlur
0075                 {
0076                     id: fastBlur
0077                     height: artworkBg.height
0078                     width: artworkBg.width
0079                     anchors.centerIn: parent
0080 
0081                     source: artworkBg
0082                     radius: 64
0083                     transparentBorder: false
0084                     cached: true
0085 
0086                     Rectangle
0087                     {
0088                         anchors.fill: parent
0089                         color: Maui.Theme.backgroundColor
0090                         opacity: 0.9
0091                     }
0092                 }
0093             }
0094         }
0095     }
0096 
0097     Component
0098     {
0099         id: _infoComponent
0100 
0101         InfoView
0102         {
0103             headBar.background: null
0104             headBar.leftContent: ToolButton
0105             {
0106                 icon.name: control.depth === 2 ? "go-previous" : "go-down"
0107                 onClicked:
0108                 {
0109                     if(control.depth === 2)
0110                     {
0111                         control.pop()
0112                     }
0113                 }
0114             }
0115         }
0116     }
0117 
0118     Item
0119     {
0120         anchors.fill: parent
0121         DragHandler
0122         {
0123             acceptedDevices: PointerDevice.GenericPointer
0124             grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverbyAnything
0125             onActiveChanged: { if (active) root.startSystemMove(); }
0126             // Harmonize(d) with ToolBar.qml, TabBar.qml from MauiKit.
0127         }
0128     }
0129 
0130     initialItem: Loader
0131     {
0132         id: _loader
0133         focus: true
0134         asynchronous: true
0135 
0136         sourceComponent: Maui.Page
0137         {
0138             property alias filterField: _filterField
0139             showCSDControls: settings.focusViewDefault
0140             background: null
0141             headBar.background: null
0142             footBar.background: null
0143             footBar.forceCenterMiddleContent: root.isWide
0144             footBar.middleContent: Maui.TextFieldPopup
0145             {
0146                 id: _filterField
0147                 placeholderText: i18n("Find")
0148                 Layout.alignment: Qt.AlignCenter
0149                 Layout.maximumWidth: 500
0150                 Layout.fillWidth: true
0151                 clip: false
0152                 position: ToolBar.Footer
0153                 KeyNavigation.up: _list
0154                 KeyNavigation.down: _list
0155                 //                popup.height: Math.min(500,Math.max(_list.listBrowser.implicitHeight, 300))
0156 
0157                 Timer
0158                 {
0159                     id: _typeTimer
0160                     interval: 1700
0161                     onTriggered:
0162                     {
0163                         if(_filterField.text.length == 0)
0164                         {
0165                             _list.list.clear()
0166                             return;
0167                         }
0168 
0169                         _list.list.query = Q.GET.tracksWhere_.arg("t.title LIKE \"%"+_filterField.text+"%\" OR t.artist LIKE \"%"+_filterField.text+"%\" OR t.album LIKE \"%"+_filterField.text+"%\" OR t.genre LIKE \"%"+_filterField.text+"%\"")
0170                     }
0171                 }
0172 
0173                 onTextChanged:
0174                 {
0175                     _typeTimer.start()
0176                 }
0177 
0178                 onClosed: _filterField.clear()
0179 
0180                 BabeTable
0181                 {
0182                     id: _list
0183                     headBar.visible: false
0184                     anchors.fill: parent
0185                     coverArtVisible: settings.showArtwork
0186                     clip: true
0187 
0188                     holder.emoji: "qrc:/assets/dialog-information.svg"
0189                     holder.title : i18n("No Results!")
0190                     holder.body: i18n("Try with something else")
0191 
0192                     onRowClicked: (index) =>
0193                     {
0194                         Player.quickPlay(listModel.get(index))
0195                         _filterField.close()
0196                     }
0197 
0198                     onAppendTrack: (index) =>
0199                     {
0200                         Player.addTrack(listModel.get(index))
0201                     }
0202 
0203                     onPlayAll:
0204                     {
0205                         Player.playAllModel(listModel.list)
0206                         _filterField.close()
0207 
0208                     }
0209 
0210                     onAppendAll:
0211                     {
0212                         Player.appendAllModel(listModel.list)
0213                         _filterField.close()
0214                     }
0215 
0216                     onQueueTrack: (index) =>
0217                     {
0218                         Player.queueTracks([listModel.get(index)], index)
0219                     }
0220                 }
0221             }
0222 
0223             Maui.Holder
0224             {
0225                 anchors.fill: parent
0226                 visible: mainPlaylist.table.count === 0
0227                 emoji: "qrc:/assets/view-media-track.svg"
0228                 title : "Nothing to play!"
0229                 body: i18n("Start putting together your playlist.")
0230             }
0231 
0232             ColumnLayout
0233             {
0234                 anchors.fill: parent
0235                 spacing: Maui.Style.space.medium
0236                 visible: mainPlaylist.table.count > 0
0237 
0238                 Loader
0239                 {
0240                     asynchronous: true
0241                     active: mainPlaylist
0242 
0243                     Layout.fillWidth: true
0244                     Layout.fillHeight: true
0245                     Layout.maximumHeight: 400
0246                     Layout.minimumHeight: 100
0247 
0248                     onLoaded: item.positionViewAtIndex(currentTrackIndex, ListView.Center)
0249                     sourceComponent: ListView
0250                     {
0251                         id: _listView
0252                         implicitHeight: 300
0253 
0254                         orientation: ListView.Horizontal
0255 
0256                         focus: true
0257                         interactive: true
0258 
0259                         Binding on currentIndex
0260                         {
0261                             value: currentTrackIndex
0262                             restoreMode: Binding.RestoreBindingOrValue
0263                         }
0264 
0265                         spacing: 0
0266                         highlightFollowsCurrentItem: true
0267                         highlightMoveDuration: 0
0268                         snapMode: ListView.SnapOneItem
0269                         model: mainPlaylist.listModel
0270                         highlightRangeMode: ListView.ApplyRange
0271 
0272                         keyNavigationEnabled: true
0273                         keyNavigationWraps : true
0274 
0275                         Timer
0276                         {
0277                             id: _flickTimer
0278                             interval: 1700
0279                             onTriggered:
0280                             {
0281                                 var index = _listView.indexAt(_listView.contentX, _listView.contentY)
0282                                 if(index !== root.currentTrackIndex && index >= 0)
0283                                     Player.playAt(index)
0284                             }
0285                         }
0286 
0287                         onMovementEnded:
0288                         {
0289                           _flickTimer.start()
0290                         }
0291 
0292                         delegate: ColumnLayout
0293                         {
0294                             height: ListView.view.height
0295                             width: ListView.view.width
0296                             spacing: Maui.Style.space.big
0297                             property bool isCurrentItem : ListView.isCurrentItem
0298 
0299                             Item
0300                             {
0301                                 Layout.fillHeight: true
0302                                 Layout.fillWidth: true
0303                                 Layout.alignment: Qt.AlignCenter
0304 
0305                                 Rectangle
0306                                 {
0307                                     id: _bg
0308                                     width: _image.width + Maui.Style.space.medium
0309                                     height: width
0310                                     anchors.centerIn: parent
0311                                     radius: root.focusView ? Maui.Style.radiusV :  Math.min(width, height)
0312 
0313                                     Behavior on radius
0314                                     {
0315                                         NumberAnimation { duration: 200; easing.type: Easing.OutCubic }
0316                                     }
0317 
0318                                     color: "#fafafa"
0319                                 }
0320 
0321                                 DropShadow
0322                                 {
0323                                     anchors.fill: _bg
0324                                     horizontalOffset: 0
0325                                     verticalOffset: 0
0326                                     radius: 8.0
0327                                     samples: 17
0328                                     color: "#80000000"
0329                                     source: _bg
0330                                 }
0331 
0332                                 Image
0333                                 {
0334                                     id: _image
0335                                     width: Math.min(parent.width, parent.height) * 0.9
0336                                     height: width
0337                                     anchors.centerIn: parent
0338 
0339                                     sourceSize.width: 200
0340 
0341                                     fillMode: Image.PreserveAspectFit
0342                                     antialiasing: false
0343                                     smooth: true
0344                                     asynchronous: true
0345 
0346                                     source: "image://artwork/album:"+model.artist + ":"+ model.album || "image://artwork/artist:"+model.artist
0347 
0348                                     onStatusChanged:
0349                                     {
0350                                         if (status == Image.Error)
0351                                             source = "qrc:/assets/cover.png";
0352                                     }
0353 
0354                                     layer.enabled: true
0355                                     layer.effect: OpacityMask
0356                                     {
0357                                         maskSource: Item
0358                                         {
0359                                             width: _image.width
0360                                             height: _image.height
0361 
0362                                             Rectangle
0363                                             {
0364                                                 anchors.centerIn: parent
0365                                                 width: _image.width
0366                                                 height: _image.height
0367                                                 radius: _bg.radius
0368                                             }
0369                                         }
0370                                     }
0371                                 }
0372                             }
0373 
0374                             ColumnLayout
0375                             {
0376                                 Layout.fillWidth: true
0377                                 implicitHeight: Maui.Style.toolBarHeight
0378                                 spacing: 0
0379 
0380                                 Label
0381                                 {
0382                                     id: _label1
0383                                     visible: text.length
0384                                     Layout.fillWidth: true
0385                                     Layout.fillHeight: false
0386                                     verticalAlignment: Qt.AlignVCenter
0387                                     horizontalAlignment: Qt.AlignHCenter
0388                                     text: model.title
0389                                     elide: Text.ElideMiddle
0390                                     wrapMode: Text.NoWrap
0391                                     color: Maui.Theme.textColor
0392                                     font.weight: Font.Bold
0393                                     font.pointSize: Maui.Style.fontSizes.huge
0394                                 }
0395 
0396                                 Label
0397                                 {
0398                                     id: _label2
0399                                     visible: text.length
0400                                     Layout.fillWidth: true
0401                                     Layout.fillHeight: false
0402                                     verticalAlignment: Qt.AlignVCenter
0403                                     horizontalAlignment: Qt.AlignHCenter
0404                                     text: model.artist
0405                                     elide: Text.ElideMiddle
0406                                     wrapMode: Text.NoWrap
0407                                     color: Maui.Theme.textColor
0408                                     font.weight: Font.Normal
0409                                     font.pointSize: Maui.Style.fontSizes.big
0410                                     opacity: 0.7
0411                                 }
0412                             }
0413                         }
0414                     }
0415                 }
0416 
0417                 RowLayout
0418                 {
0419                     visible: settings.volumeControl
0420                     Layout.fillWidth: true
0421                     Layout.maximumWidth: 300
0422 
0423                     Layout.alignment: Qt.AlignHCenter
0424 
0425                     spacing: Maui.Style.space.small
0426 
0427                     Maui.Icon
0428                     {
0429                         implicitHeight: Maui.Style.iconSizes.small
0430                         implicitWidth: implicitHeight
0431                         source: "audio-volume-low"
0432                     }
0433 
0434                     Slider
0435                     {
0436                         id: volumeBar
0437                         Layout.fillWidth: true
0438                         padding: 0
0439                         spacing: 0
0440                         from: 0
0441                         to: 100
0442                         value: player.volume
0443                         stepSize: 5
0444                         orientation: Qt.Horizontal
0445 
0446                         onMoved:
0447                         {
0448                             player.volume = value
0449                         }
0450                     }
0451 
0452                     Maui.Icon
0453                     {
0454                         implicitHeight: Maui.Style.iconSizes.small
0455                         implicitWidth: implicitHeight
0456                         source: "audio-volume-high"
0457                     }
0458                 }
0459 
0460                 Row
0461                 {
0462                     Layout.alignment: Qt.AlignCenter
0463                     spacing: Maui.Style.space.medium
0464 
0465                     ToolButton
0466                     {
0467                         id: babeBtnIcon
0468                         icon.name: "love"
0469                         flat: true
0470                         enabled: root.currentTrack
0471                         checked: root.currentTrack.url ? FB.Tagging.isFav(root.currentTrack.url) : false
0472                         icon.color: checked ? babeColor :  Maui.Theme.textColor
0473 
0474                         onClicked:
0475                         {
0476                             mainPlaylist.listModel.list.fav(root.currentTrackIndex, !FB.Tagging.isFav(root.currentTrack.url))
0477                             root.currentTrackChanged()
0478                         }
0479                     }
0480 
0481                     ToolButton
0482                     {
0483 
0484                         flat: true
0485 
0486                         icon.name: "documentinfo"
0487                         checkable: true
0488                         checked: control.depth === 2
0489                         onClicked:
0490                         {
0491                             if(control.depth === 2)
0492                             {
0493                                 control.pop()
0494                             }else
0495                             {
0496                                 control.push(_infoComponent)
0497                             }
0498                         }
0499                     }
0500 
0501                     ToolButton
0502                     {
0503                         flat: true
0504                         icon.name: switch(playlist.repeatMode)
0505                                    {
0506                                    case Vvave.Playlist.NoRepeat: return "media-repeat-none"
0507                                    case Vvave.Playlist.RepeatOnce: return "media-playlist-repeat-song"
0508                                    case Vvave.Playlist.Repeat: return "media-playlist-repeat"
0509                                    }
0510                         onClicked:
0511                         {
0512                             switch(playlist.repeatMode)
0513                             {
0514                             case Vvave.Playlist.NoRepeat:
0515                                 playlist.repeatMode = Vvave.Playlist.Repeat
0516                                 break
0517 
0518                             case Vvave.Playlist.Repeat:
0519                                 playlist.repeatMode = Vvave.Playlist.RepeatOnce
0520                                 break
0521 
0522                             case Vvave.Playlist.RepeatOnce:
0523                                 playlist.repeatMode = Vvave.Playlist.NoRepeat
0524                                 break
0525                             }
0526                         }
0527                     }
0528 
0529                     ToolButton
0530                     {
0531                         id: shuffleBtn
0532                         flat: true
0533 
0534                         icon.name: switch(playlist.playMode)
0535                                    {
0536                                    case Vvave.Playlist.Normal: return "media-playlist-normal"
0537                                    case Vvave.Playlist.Shuffle: return "media-playlist-shuffle"
0538                                    }
0539                         onClicked:
0540                         {
0541                             switch(playlist.playMode)
0542                             {
0543                             case Vvave.Playlist.Normal:
0544                                 playlist.playMode = Vvave.Playlist.Shuffle
0545                                 break
0546 
0547                             case Vvave.Playlist.Shuffle:
0548                                 playlist.playMode = Vvave.Playlist.Normal
0549                                 break
0550                             }
0551                         }
0552                     }
0553                 }
0554 
0555                 ColumnLayout
0556                 {
0557                     Layout.fillWidth: true
0558                     Layout.maximumWidth: 600
0559                     Layout.margins: Maui.Style.space.medium
0560                     Layout.alignment: Qt.AlignCenter
0561 
0562                     spacing: 0
0563 
0564                     RowLayout
0565                     {
0566                         Layout.fillWidth: true
0567 
0568                         Label
0569                         {
0570                             visible: text.length
0571                             Layout.fillWidth: true
0572                             verticalAlignment: Qt.AlignVCenter
0573                             horizontalAlignment: Qt.AlignLeft
0574                             text: control.progressTimeLabel
0575                             elide: Text.ElideMiddle
0576                             wrapMode: Text.NoWrap
0577                         }
0578 
0579                         Item
0580                         {
0581                             Layout.fillWidth: true
0582                         }
0583 
0584                         Label
0585                         {
0586                             visible: text.length
0587                             Layout.fillWidth: true
0588                             verticalAlignment: Qt.AlignVCenter
0589                             horizontalAlignment: Qt.AlignRight
0590                             text: control.durationTimeLabel
0591                             elide: Text.ElideMiddle
0592                             wrapMode: Text.NoWrap
0593                         }
0594                     }
0595 
0596                     Slider
0597                     {
0598                         id: progressBar
0599                         Layout.fillWidth: true
0600 
0601                         padding: 0
0602                         from: 0
0603                         to: 1000
0604                         value: player.pos/player.duration*1000
0605                         spacing: 0
0606                         focus: true
0607                         onMoved: player.pos = (player.duration / 1000) * value
0608                     }
0609                 }
0610 
0611             }
0612         }
0613     }
0614 
0615 
0616     function forceActiveFocus()
0617     {
0618         control.item.forceActiveFocus()
0619     }
0620 
0621     Component.onCompleted:
0622     {
0623         forceActiveFocus()
0624     }
0625 
0626     function getFilterField() : Item
0627     {
0628         return control.loader.item.filterField
0629     }
0630     }