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 }