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 }