Warning, /maui/clip/src/main.qml is written in an unsupported language. File is not indexed.
0001 import QtQuick 2.14 0002 import QtQuick.Controls 2.14 0003 import QtQuick.Layouts 1.3 0004 0005 import QtMultimedia 5.8 0006 0007 import Qt.labs.settings 1.0 0008 0009 import org.mauikit.controls 1.3 as Maui 0010 import org.mauikit.filebrowsing 1.2 as FB 0011 0012 import org.maui.clip 1.0 as Clip 0013 0014 import "views" 0015 import "views/player" 0016 import "views/collection" 0017 import "views/tags" 0018 import "views/settings" 0019 import "views/youtube" 0020 0021 Maui.ApplicationWindow 0022 { 0023 id: root 0024 0025 title: _playerView.currentVideo.label 0026 Maui.Style.styleType: Maui.Handy.isAndroid ? (settings.darkMode ? Maui.Style.Dark : Maui.Style.Light) : undefined 0027 0028 property bool selectionMode : false 0029 0030 readonly property alias dialog : dialogLoader.item 0031 readonly property alias player: _playerView.player 0032 0033 // onIsPortraitChanged: 0034 // { 0035 // if(!isPortrait) 0036 // { 0037 // root.showFullScreen() 0038 // } 0039 // else 0040 // { 0041 // root.showNormal() 0042 // } 0043 // } 0044 0045 Settings 0046 { 0047 id: settings 0048 property int volumeStep: 5 0049 property string colorScheme: "Breeze" 0050 property string sortBy: "date" 0051 property int sortOrder: Qt.AscendingOrder 0052 property bool hardwareDecoding: true 0053 property string preferredLanguage: "eng" 0054 property string subtitlesPath 0055 property font font 0056 property bool playerTagBar: true 0057 property string youtubeKey: "AIzaSyDMLmTSEN7i6psE2tHdaG6hy3ljWKXIYBk" 0058 property int youtubeQueryLimit : 50 0059 property bool darkMode : true 0060 } 0061 0062 Loader 0063 { 0064 anchors.fill: parent 0065 asynchronous: true 0066 sourceComponent: DropArea 0067 { 0068 onDropped: (drop) => 0069 { 0070 if(drop.urls) 0071 { 0072 Clip.Clip.openVideos(drop.urls) 0073 } 0074 } 0075 } 0076 } 0077 0078 Component 0079 { 0080 id: _settingsDialogComponent 0081 SettingsDialog {} 0082 } 0083 0084 Component 0085 { 0086 id: _openUrlDialogComponent 0087 Maui.InputDialog 0088 { 0089 title: i18n("Open URL") 0090 textEntry.placeholderText: "URL" 0091 message: i18n("Enter any remote location, like YouTube video URLs, or from other services supported by MPV.") 0092 onAccepted: player.url = textEntry.text 0093 } 0094 } 0095 0096 Component 0097 { 0098 id: tagsDialogComponent 0099 FB.TagsDialog 0100 { 0101 onTagsReady: composerList.updateToUrls(tags) 0102 composerList.strict: false 0103 } 0104 } 0105 0106 Component 0107 { 0108 id: fmDialogComponent 0109 FB.FileDialog 0110 { 0111 mode: modes.SAVE 0112 settings.filterType: FB.FMList.IMAGE 0113 settings.onlyDirs: false 0114 } 0115 } 0116 0117 Component 0118 { 0119 id: removeDialogComponent 0120 0121 Maui.InfoDialog 0122 { 0123 title: i18n("Delete files?") 0124 0125 message: i18n("Are sure you want to delete %1 files", String(selectionBar.count)) 0126 standardButtons: Dialog.Ok | Dialog.Cancel 0127 template.iconSource: "emblem-warning" 0128 0129 onRejected: close() 0130 onAccepted: 0131 { 0132 for(var url of selectionBox.uris) 0133 FB.FM.removeFile(url) 0134 selectionBox.clear() 0135 close() 0136 } 0137 } 0138 } 0139 0140 Loader { id: dialogLoader } 0141 0142 StackView 0143 { 0144 id: _stackView 0145 anchors.fill: parent 0146 initialItem: initModule === "viewer" ? _sideBarView : _appViewsComponent 0147 0148 Component 0149 { 0150 id: _appViewsComponent 0151 0152 CollectionView {} 0153 } 0154 0155 Maui.SideBarView 0156 { 0157 id: _sideBarView 0158 focus: true 0159 0160 visible: StackView.status === StackView.Active 0161 0162 height: parent.height 0163 width: parent.width 0164 0165 sideBar.enabled: _playlist.count > 1 0166 sideBar.autoHide: true 0167 sideBar.autoShow: false 0168 sideBar.preferredWidth: Maui.Style.units.gridUnit * 16 0169 0170 sideBarContent: Maui.Page 0171 { 0172 anchors.fill: parent 0173 title: i18n("Now playing") 0174 showTitle: true 0175 0176 headBar.visible: _playlist.count > 0 0177 headBar.background: null 0178 0179 background: Rectangle 0180 { 0181 color: Maui.Theme.backgroundColor 0182 opacity: 0.2 0183 } 0184 0185 headBar.rightContent: ToolButton 0186 { 0187 icon.name: "edit-delete" 0188 onClicked: 0189 { 0190 player.stop() 0191 _playlist.list.clear() 0192 } 0193 } 0194 0195 headBar.leftContent: ToolButton 0196 { 0197 icon.name: "document-save" 0198 onClicked: saveList() 0199 } 0200 0201 Playlist 0202 { 0203 id: _playlist 0204 anchors.fill: parent 0205 } 0206 } 0207 0208 Maui.Page 0209 { 0210 id: _playerPage 0211 anchors.fill: parent 0212 autoHideHeader: _playerView.player.playbackState === MediaPlayer.PlayingState 0213 // autoHideFooter: _playerView.player.playbackState === MediaPlayer.PlayingState 0214 0215 floatingHeader: autoHideHeader 0216 headBar.visible: !_playerHolderLoader.active 0217 0218 showCSDControls: true 0219 0220 onGoBackTriggered: _stackView.pop() 0221 0222 Keys.enabled: !Maui.Handy.isMobile 0223 Keys.onSpacePressed: player.playbackState === MediaPlayer.PlayingState ? player.pause() : player.play() 0224 Keys.onLeftPressed: player.seek(player.position - 500) 0225 Keys.onRightPressed: player.seek(player.position + 500) 0226 0227 PlayerView 0228 { 0229 id: _playerView 0230 anchors.fill: parent 0231 } 0232 0233 BusyIndicator 0234 { 0235 anchors.centerIn: parent 0236 running: _playerView.status === MediaPlayer.Loading 0237 } 0238 0239 Loader 0240 { 0241 anchors.fill: parent 0242 asynchronous: true 0243 // active: !player.stopped 0244 0245 sourceComponent: RowLayout 0246 { 0247 MouseArea 0248 { 0249 Layout.fillWidth: true 0250 Layout.fillHeight: true 0251 onDoubleClicked: player.seek(player.position - 5) 0252 } 0253 0254 MouseArea 0255 { 0256 Layout.fillWidth: true 0257 Layout.fillHeight: true 0258 onClicked: player.playbackState === MediaPlayer.PlayingState ? player.pause() : player.play() 0259 onDoubleClicked: root.toggleFullScreen() 0260 } 0261 0262 MouseArea 0263 { 0264 Layout.fillWidth: true 0265 Layout.fillHeight: true 0266 onDoubleClicked: player.seek(player.position + 5) 0267 } 0268 } 0269 } 0270 0271 Loader 0272 { 0273 id: _playerHolderLoader 0274 anchors.fill: parent 0275 active: _playerView.stopped && _playerView.status === MediaPlayer.NoMedia 0276 asynchronous: true 0277 visible: active 0278 sourceComponent: Maui.Holder 0279 { 0280 emoji: "qrc:/img/assets/media-playback-start.svg" 0281 title: i18n("Nothing Here!") 0282 body: i18n("Open a new video from your collection or file system.") 0283 actions: [ 0284 0285 Action 0286 { 0287 text: "Open" 0288 onTriggered: root.openFileDialog() 0289 }, 0290 0291 Action 0292 { 0293 text: "Collection" 0294 onTriggered: toggleViewer() 0295 } 0296 ] 0297 } 0298 } 0299 0300 headBar.leftContent: ToolButton 0301 { 0302 text: i18n("Collection") 0303 icon.name: "go-previous" 0304 onClicked: toggleViewer() 0305 } 0306 0307 footerColumn: Loader 0308 { 0309 active: !player.stopped 0310 width: parent.width 0311 asynchronous: true 0312 visible: active 0313 0314 sourceComponent: Maui.ToolBar 0315 { 0316 preferredHeight: Maui.Style.rowHeightAlt 0317 0318 position: ToolBar.Footer 0319 leftContent: Label 0320 { 0321 text: Maui.Handy.formatTime(player.video.position/1000) 0322 } 0323 0324 rightContent: Label 0325 { 0326 text: Maui.Handy.formatTime(player.video.duration/1000) 0327 } 0328 0329 middleContent: Item 0330 { 0331 Layout.fillHeight: true 0332 Layout.fillWidth: true 0333 0334 Label 0335 { 0336 anchors.fill: parent 0337 visible: text.length 0338 verticalAlignment: Qt.AlignVCenter 0339 horizontalAlignment: Qt.AlignHCenter 0340 text: root.title 0341 elide: Text.ElideMiddle 0342 wrapMode: Text.NoWrap 0343 color: Maui.Theme.textColor 0344 } 0345 } 0346 0347 background: Slider 0348 { 0349 id: _slider 0350 z: parent.z+1 0351 padding: 0 0352 orientation: Qt.Horizontal 0353 from: 0 0354 to: player.video.duration 0355 value: player.video.position 0356 0357 onMoved: player.video.seek( _slider.value ) 0358 spacing: 0 0359 focus: true 0360 0361 Maui.Separator 0362 { 0363 anchors.top: parent.top 0364 width: parent.width 0365 } 0366 0367 background: Rectangle 0368 { 0369 implicitWidth: _slider.width 0370 implicitHeight: _slider.height 0371 width: _slider.availableWidth 0372 height: implicitHeight 0373 color: "transparent" 0374 opacity: 0.4 0375 0376 Rectangle 0377 { 0378 width: _slider.visualPosition * parent.width 0379 height: _slider.pressed ? _slider.height : 2 0380 color: Maui.Theme.highlightColor 0381 } 0382 } 0383 0384 handle: Rectangle 0385 { 0386 x: _slider.leftPadding + _slider.visualPosition 0387 * (_slider.availableWidth - width) 0388 y: 0 0389 implicitWidth: Maui.Style.iconSizes.medium 0390 implicitHeight: _slider.height 0391 color: _slider.pressed ? Qt.lighter(Maui.Theme.highlightColor, 1.2) : "transparent" 0392 } 0393 } 0394 } 0395 } 0396 0397 headBar.rightContent: [ 0398 ToolButton 0399 { 0400 // text: i18n("Open") 0401 display: isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly 0402 icon.name: "folder-open" 0403 onClicked: root.openFileDialog() 0404 }, 0405 Loader 0406 { 0407 active: Clip.Clip.mpvAvailable 0408 asynchronous: true 0409 sourceComponent: Maui.ToolButtonMenu 0410 { 0411 icon.name: "overflow-menu" 0412 0413 Maui.MenuItemActionRow 0414 { 0415 Action 0416 { 0417 icon.name: "edit-share" 0418 } 0419 0420 Action 0421 { 0422 icon.name: "edit" 0423 } 0424 0425 Action 0426 { 0427 icon.name: "view-fullscreen" 0428 onTriggered: toggleFullscreen() 0429 } 0430 } 0431 0432 MenuSeparator{} 0433 0434 MenuItem 0435 { 0436 text: "Corrections" 0437 onTriggered: control.editing = !control.editing 0438 } 0439 0440 MenuItem 0441 { 0442 text: "Subtitles" 0443 onTriggered: _subtitlesDialog.open() 0444 } 0445 0446 MenuItem 0447 { 0448 text: "Audio" 0449 onTriggered: _audioTracksDialog.open() 0450 } 0451 } 0452 }] 0453 0454 footBar.visible: _sideBarView.sideBar.enabled 0455 footBar.farLeftContent: Loader 0456 { 0457 active: _sideBarView.sideBar.enabled 0458 visible: active 0459 asynchronous: true 0460 sourceComponent: ToolButton 0461 { 0462 icon.name: _sideBarView.sideBar.visible ? "sidebar-collapse" : "sidebar-expand" 0463 onClicked: _sideBarView.sideBar.toggle() 0464 checked: _sideBarView.sideBar.visible 0465 ToolTip.delay: 1000 0466 ToolTip.timeout: 5000 0467 ToolTip.visible: hovered 0468 ToolTip.text: i18n("Toggle SideBar") 0469 } 0470 } 0471 0472 footBar.middleContent: [ 0473 0474 Maui.ToolActions 0475 { 0476 Layout.alignment: Qt.AlignCenter 0477 expanded: true 0478 checkable: false 0479 autoExclusive: false 0480 0481 Action 0482 { 0483 icon.name: "media-skip-backward" 0484 onTriggered: playPrevious() 0485 } 0486 0487 Action 0488 { 0489 icon.name: player.playing ? "media-playback-pause" : "media-playback-start" 0490 onTriggered: player.paused ? player.video.play() : player.video.pause() 0491 } 0492 0493 Action 0494 { 0495 icon.name: "media-skip-forward" 0496 onTriggered: playNext() 0497 } 0498 } 0499 ] 0500 } 0501 } 0502 } 0503 0504 Loader 0505 { 0506 visible: active 0507 active: !_sideBarView.visible && !_playerView.player.stopped 0508 asynchronous: true 0509 sourceComponent: FloatingVideo {} 0510 } 0511 0512 Connections 0513 { 0514 target: Clip.Clip 0515 function onOpenUrls(urls) 0516 { 0517 for(var url of urls) 0518 _playlist.list.appendUrl(url) 0519 0520 playAt(_playlist.count - urls.length) 0521 } 0522 } 0523 0524 Component.onCompleted: 0525 { 0526 setAndroidStatusBarColor() 0527 } 0528 0529 function setAndroidStatusBarColor() 0530 { 0531 if(Maui.Handy.isAndroid) 0532 { 0533 Maui.Android.statusbarColor( Maui.Theme.backgroundColor, !settings.darkMode) 0534 Maui.Android.navBarColor(Maui.Theme.backgroundColor, !settings.darkMode) 0535 } 0536 } 0537 0538 function toggleViewer() 0539 { 0540 if(_sideBarView.visible) 0541 { 0542 if(_stackView.depth === 1) 0543 { 0544 _stackView.replace(_sideBarView, _appViewsComponent) 0545 0546 }else 0547 { 0548 _stackView.pop() 0549 } 0550 0551 }else 0552 { 0553 _stackView.push(_sideBarView) 0554 } 0555 0556 _stackView.currentItem.forceActiveFocus() 0557 } 0558 0559 function playNext() 0560 { 0561 if(_playlist.list.count > 0) 0562 { 0563 const next = _playerView.currentVideoIndex+1 >= _playlist.list.count ? 0 : _playerView.currentVideoIndex+1 0564 0565 playAt(next) 0566 } 0567 } 0568 0569 function playPrevious() 0570 { 0571 if(_playlist.list.count > 0) 0572 { 0573 const previous = _playerView.currentVideoIndex-1 >= 0 ? _playerView.currentVideoIndex-1 : _playlist.list.count-1 0574 0575 playAt(previous) 0576 } 0577 } 0578 0579 function play(item) 0580 { 0581 queue(item) 0582 playAt(_playlist.list.count-1) 0583 } 0584 0585 //Index of the video in the playlist 0586 function playAt(index) 0587 { 0588 if((index < _playlist.list.count) && (index > -1)) 0589 { 0590 _playerView.currentVideoIndex = index 0591 _playerView.currentVideo = _playlist.model.get(index) 0592 0593 if(!_playerView.visible) 0594 { 0595 toggleViewer() 0596 } 0597 } 0598 } 0599 0600 function playItems(items) 0601 { 0602 _playlist.list.clear() 0603 for(var item of items) 0604 { 0605 queue(item) 0606 } 0607 playAt(0) 0608 } 0609 0610 function queueItems(items) 0611 { 0612 for(var item of items) 0613 { 0614 queue(item) 0615 } 0616 } 0617 0618 function queue(item) 0619 { 0620 _playlist.append(item) 0621 } 0622 0623 function openFileDialog() 0624 { 0625 dialogLoader.sourceComponent= fmDialogComponent 0626 dialog.mode = dialog.modes.OPEN 0627 dialog.settings.filterType= FB.FMList.VIDEO 0628 dialog.settings.onlyDirs= false 0629 dialog.callback = function(paths) 0630 { 0631 Clip.Clip.openVideos(paths) 0632 }; 0633 dialog.open() 0634 } 0635 0636 function openSettingsDialog() 0637 { 0638 dialogLoader.sourceComponent = _settingsDialogComponent 0639 dialog.open() 0640 } 0641 0642 }