1 /*****************************************************************************
2 * Copyright (C) 2019 VLC authors and VideoLAN
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * ( at your option ) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17 *****************************************************************************/
19 import QtQuick.Controls 2.4
20 import QtQuick.Layouts 1.3
21 import QtQml.Models 2.2
23 import org.videolan.medialib 0.1
25 import "qrc:///util/" as Util
26 import "qrc:///widgets/" as Widgets
27 import "qrc:///dialogs/" as DG
28 import "qrc:///style/"
30 Widgets.NavigableFocusScope {
32 readonly property var currentIndex: view.currentItem.currentIndex
33 //the index to "go to" when the view is loaded
34 property var initialIndex: 0
36 property alias contentModel: videosDelegate.model;
38 navigationCancel: function() {
39 if (view.currentItem.currentIndex <= 0) {
40 defaultNavigationCancel()
42 view.currentItem.currentIndex = 0;
43 view.currentItem.positionViewAtIndex(0, ItemView.Contain)
47 onCurrentIndexChanged: {
48 history.update([ "mc", "video", {"initialIndex": currentIndex}])
51 onInitialIndexChanged: resetFocus()
52 onContentModelChanged: resetFocus()
54 function resetFocus() {
55 if (videosDelegate.items.count === 0) {
58 var initialIndex = root.initialIndex
59 if (initialIndex >= videosDelegate.items.count)
61 videosDelegate.selectNone()
62 videosDelegate.items.get(initialIndex).inSelected = true
63 view.currentItem.currentIndex = initialIndex
64 view.currentItem.positionViewAtIndex(initialIndex, ItemView.Contain)
70 title: i18n.qtr("Are you sure you want to delete?")
71 standardButtons: Dialog.Yes | Dialog.No
73 onAccepted: console.log("Ok clicked")
74 onRejected: console.log("Cancel clicked")
79 property var model: ({})
80 closePolicy: Popup.CloseOnReleaseOutside | Popup.CloseOnEscape
84 text: "Play from start"
85 onTriggered: medialib.addAndPlay( contextMenu.model.id )
89 onTriggered: console.log("not implemented")
93 onTriggered: console.log("not implemented")
97 onTriggered: medialib.addToPlaylist( contextMenu.model.id )
100 enabled: medialib.gridView
103 view.currentItem.switchExpandItem(contextMenu.model.index)
106 Widgets.MenuItemExt {
107 text: "Download subtitles"
108 onTriggered: console.log("not implemented")
110 Widgets.MenuItemExt {
111 text: "Add to playlist"
112 onTriggered: console.log("not implemented")
114 Widgets.MenuItemExt {
116 onTriggered: deleteDialog.open()
119 onClosed: contextMenu.parent.forceActiveFocus()
122 Util.SelectableDelegateModel {
125 model: MLVideoModel {
129 Item { Package.name: "grid" }
133 if (videosDelegate.items.count > 0 && videosDelegate.selectedGroup.count === 0) {
138 function actionAtIndex(index) {
140 for (var i = 0; i < videosDelegate.selectedGroup.count; i++)
141 list.push(videosDelegate.selectedGroup.get(i).model.id)
142 medialib.addAndPlay( list )
149 Widgets.ExpandGridView {
151 property Item currentItem: Item{}
153 activeFocusOnTab:true
154 model: videosDelegate
155 modelCount: videosDelegate.items.count
157 headerDelegate: Widgets.LabelSeparator {
159 width: videosGV.width
160 text: i18n.qtr("Videos")
164 delegate: VideoGridItem {
167 onContextMenuButtonClicked: {
168 contextMenu.model = videoGridItem.model
173 videosDelegate.updateSelection( modifier , videosGV.currentIndex, index)
174 videosGV.currentIndex = index
175 videosGV.forceActiveFocus()
179 expandDelegate: VideoInfoExpandPanel {
180 visible: !videosGV.isAnimating
182 implicitHeight: videosGV.height - videosGV.cellHeight
183 width: videosGV.width
185 onRetract: videosGV.retract()
186 notchPosition: videosGV.getItemPos(videosGV._expandIndex)[0] + (videosGV.cellWidth / 2)
188 navigationParent: videosGV
189 navigationCancel: function() { videosGV.retract() }
190 navigationUp: function() { videosGV.retract() }
191 navigationDown: function() { videosGV.retract() }
194 navigationParent: root
197 *define the intial position/selection
198 * This is done on activeFocus rather than Component.onCompleted because videosDelegate.
199 * selectedGroup update itself after this event
201 onActiveFocusChanged: {
202 if (activeFocus && videosDelegate.items.count > 0 && videosDelegate.selectedGroup.count === 0) {
203 videosDelegate.items.get(0).inSelected = true
207 cellWidth: VLCStyle.gridItem_video_width
208 cellHeight: VLCStyle.gridItem_video_height
210 onSelectAll: videosGV.model.selectAll()
211 onSelectionUpdated: videosGV.model.updateSelection( keyModifiers, oldIndex, newIndex )
212 onActionAtIndex: switchExpandItem( index )
223 onContextMenuButtonClicked:{
224 contextMenu.model = menuModel
225 contextMenu.popup(menuParent)
229 contextMenu.model = menuModel
233 navigationParent: root
237 Widgets.StackViewExt {
242 initialItem: medialib.gridView ? gridComponent : listComponent
246 if (medialib.gridView)
247 view.replace(gridComponent)
249 view.replace(listComponent)
256 horizontalAlignment: Text.AlignHCenter
257 verticalAlignment: Text.AlignVCenter
258 visible: videosDelegate.items.count === 0
259 font.pixelSize: VLCStyle.fontHeight_xxlarge
260 color: root.activeFocus ? VLCStyle.colors.accent : VLCStyle.colors.text
261 wrapMode: Text.WordWrap
262 text: i18n.qtr("No video found\nPlease try adding sources, by going to the Network tab")