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 }