Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • Thrillseekr/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
400 results
Show changes
Commits on Source (9)
Showing
with 287 additions and 518 deletions
......@@ -848,6 +848,7 @@ libqt_plugin_la_QML = \
gui/qt/dialogs/toolbar/qml/ToolbarEditorButtonList.qml \
gui/qt/maininterface/qml/BannerSources.qml \
gui/qt/maininterface/qml/MainInterface.qml \
gui/qt/maininterface/qml/MainViewLoader.qml \
gui/qt/maininterface/qml/MainDisplay.qml \
gui/qt/maininterface/qml/MainGridView.qml \
gui/qt/maininterface/qml/MainTableView.qml \
......
/*****************************************************************************
* Copyright (C) 2023 VLC authors and VideoLAN
*
* Author: Prince Gupta <guptaprince8832@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
import QtQuick 2.11
import QtQml.Models 2.11
import org.videolan.vlc 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///util/" as Util
import "qrc:///util/Helpers.js" as Helpers
Widgets.StackViewExt {
id: root
/*
A component for loading view subtypes depending on model or user preferences.
It also handles common actions across sub views such as -
restoring of initialIndex when view is reloaded and navigation cancel.
Following are required inputs -
*/
// components to load depending on MainCtx.gridView
/* required */ property Component grid
/* required */ property Component list
// component to load when provided model is empty
/* required */ property Component emptyLabel
// view's model
/* required */ property var model
property var selectionModel: Util.SelectableDelegateModel {
model: root.model
}
readonly property ColorContext colorContext: ColorContext {
id: theme
colorSet: ColorContext.View
}
// the index to "go to" when the view is loaded
property int initialIndex: -1
// used in custom focus management for explicit "focusReason" transfer
readonly property var setCurrentItemFocus: {
return Helpers.get(currentItem, "setCurrentItemFocus", _setCurrentItemFocusDefault)
}
property var currentComponent: {
if (typeof model === "undefined" || !model)
return null // invalid state
if (!model.ready && model.count === 0)
return emptyLabel
else if (MainCtx.gridView)
return grid
else
return list
}
onCurrentComponentChanged: {
_loadCurrentViewType()
}
onModelChanged: resetFocus()
onInitialIndexChanged: resetFocus()
Connections {
target: model
onCountChanged: {
if (model.count === 0 || selectionModel.hasSelection)
return
resetFocus()
}
}
function _setCurrentItemFocusDefault(reason) {
if (currentItem)
currentItem.forceActiveFocus(reason)
}
function _loadCurrentViewType() {
if (typeof currentComponent === "undefined" || !currentComponent) {
// invalid case, don't show anything
clear()
return
}
replace(null, currentComponent)
}
// makes the views currentIndex initial index and position view at that index
function resetFocus() {
if (!model || model.count === 0) return
var initialIndex = root.initialIndex
if (initialIndex >= model.count)
initialIndex = 0
selectionModel.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (currentItem && currentItem.hasOwnProperty("positionViewAtIndex")) {
currentItem.positionViewAtIndex(initialIndex, ItemView.Contain)
// Table View require this for focus handling
if (!MainCtx.gridView)
currentItem.currentIndex = initialIndex
}
}
// handle cancelAction, if currentIndex is set reset it to 0
// otherwise perform default Navigation action
Navigation.cancelAction: function () {
if (Helpers.get(currentItem, "currentIndex", 0) <= 0) {
return false // transfer cancel action to parent
}
currentItem.currentIndex = 0
currentItem.positionViewAtIndex(0, ItemView.Contain)
return true
}
}
......@@ -16,31 +16,31 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtQml.Models 2.2
import org.videolan.medialib 0.1
import org.videolan.vlc 0.1
import "qrc:///util/" as Util
import "qrc:///widgets/" as Widgets
import "qrc:///main/" as MainInterface
import "qrc:///util/Helpers.js" as Helpers
import "qrc:///style/"
FocusScope {
MainInterface.MainViewLoader {
id: root
// Properties
//the index to "go to" when the view is loaded
property int initialIndex: 0
property int gridViewMarginTop: VLCStyle.margin_large
property var gridViewRowX: MainCtx.gridView ? _currentView.rowX : undefined
property var gridViewRowX: Helpers.get(currentItem, "rowX", 0)
readonly property var currentIndex: Helpers.get(currentItem, "currentIndex", - 1)
readonly property var currentIndex: _currentView.currentIndex
property Component header: Item {}
readonly property Item headerItem: Helpers.get(currentItem, "headerItem", null)
property Component header: Item{}
readonly property Item headerItem: _currentView ? _currentView.headerItem : null
readonly property int contentLeftMargin: Helpers.get(currentItem, "contentLeftMargin", 0)
readonly property int contentRightMargin: Helpers.get(currentItem, "contentRightMargin", 0)
property var sortModel: [
{ text: I18n.qtr("Alphabetic"), criteria: "title"},
......@@ -49,39 +49,16 @@ FocusScope {
{ text: I18n.qtr("Artist"), criteria: "main_artist" },
]
// Aliases
property alias leftPadding: view.leftPadding
property alias rightPadding: view.rightPadding
property alias model: albumModelId
property alias parentId: albumModelId.parentId
readonly property int contentLeftMargin: _currentView ? _currentView.contentLeftMargin : 0
readonly property int contentRightMargin: _currentView ? _currentView.contentRightMargin : 0
model: albumModelId
property alias _currentView: view.currentItem
grid: gridComponent
list: tableComponent
emptyLabel: emptyLabelComponent
onInitialIndexChanged: resetFocus()
onModelChanged: resetFocus()
onParentIdChanged: resetFocus()
function resetFocus() {
if (albumModelId.count === 0) {
return
}
var initialIndex = root.initialIndex
if (initialIndex >= albumModelId.count)
initialIndex = 0
selectionModel.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (_currentView)
_currentView.positionViewAtIndex(initialIndex, ItemView.Contain)
}
function setCurrentItemFocus(reason) {
_currentView.setCurrentItemFocus(reason);
}
function _actionAtIndex(index) {
if (selectionModel.selectedIndexes.length > 1) {
MediaLib.addAndPlay( model.getIdsForIndexes( selectionModel.selectedIndexes ) )
......@@ -90,30 +67,10 @@ FocusScope {
}
}
function _onNavigationCancel() {
if (_currentView.currentIndex <= 0) {
root.Navigation.defaultNavigationCancel()
} else {
_currentView.currentIndex = 0;
_currentView.positionViewAtIndex(0, ItemView.Contain)
}
}
MLAlbumModel {
id: albumModelId
ml: MediaLib
onCountChanged: {
if (albumModelId.count > 0 && !selectionModel.hasSelection) {
root.resetFocus()
}
}
}
Util.SelectableDelegateModel {
id: selectionModel
model: albumModelId
ml: MediaLib
}
Widgets.MLDragItem {
......@@ -201,7 +158,6 @@ FocusScope {
}
Navigation.parentItem: root
Navigation.cancelAction: root._onNavigationCancel
Connections {
target: contextMenu
......@@ -282,8 +238,6 @@ FocusScope {
sortModel: (availableRowWidth < VLCStyle.colWidth(4)) ? _modelSmall
: _modelMedium
Navigation.cancelAction: root._onNavigationCancel
onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
onItemDoubleClicked: MediaLib.addAndPlay( model.id )
......@@ -310,32 +264,13 @@ FocusScope {
}
}
Widgets.StackViewExt {
id: view
anchors.fill: parent
focus: albumModelId.count !== 0
initialItem: MainCtx.gridView ? gridComponent : tableComponent
Component {
id: emptyLabelComponent
Connections {
target: MainCtx
onGridViewChanged: {
if (MainCtx.gridView)
view.replace(gridComponent)
else
view.replace(tableComponent)
}
EmptyLabelButton {
text: I18n.qtr("No albums found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtAlbumCover
}
}
EmptyLabelButton {
anchors.fill: parent
visible: albumModelId.isReady && (albumModelId.count <= 0)
focus: visible
text: I18n.qtr("No albums found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtAlbumCover
}
}
......@@ -16,10 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
import QtQuick.Controls 2.4
import QtQuick 2.11
import QtQml.Models 2.2
import QtQuick.Layouts 1.3
import org.videolan.medialib 0.1
import org.videolan.vlc 0.1
......@@ -27,71 +24,26 @@ import org.videolan.vlc 0.1
import "qrc:///util/" as Util
import "qrc:///widgets/" as Widgets
import "qrc:///main/" as MainInterface
import "qrc:///util/Helpers.js" as Helpers
import "qrc:///style/"
FocusScope {
MainInterface.MainViewLoader {
id: root
// Properties
readonly property int currentIndex: _currentView.currentIndex
property int initialIndex: 0
// Aliases
property alias leftPadding: view.leftPadding
property alias rightPadding: view.rightPadding
property alias model: artistModel
property alias _currentView: view.currentItem
onInitialIndexChanged: resetFocus()
readonly property int currentIndex: Helpers.get(currentItem, "currentIndex", - 1)
signal requestArtistAlbumView(int reason)
function resetFocus() {
if (artistModel.count === 0)
return
var initialIndex = root.initialIndex
if (initialIndex >= artistModel.count)
initialIndex = 0
selectionModel.select(artistModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (_currentView) {
_currentView.currentIndex = initialIndex
_currentView.positionViewAtIndex(initialIndex, ItemView.Contain)
}
}
function setCurrentItemFocus(reason) {
_currentView.setCurrentItemFocus(reason);
}
function _onNavigationCancel() {
if (_currentView.currentIndex <= 0) {
root.Navigation.defaultNavigationCancel()
} else {
_currentView.currentIndex = 0;
_currentView.positionViewAtIndex(0, ItemView.Contain);
}
}
MLArtistModel {
model: MLArtistModel {
id: artistModel
ml: MediaLib
onCountChanged: {
if (artistModel.count > 0 && !selectionModel.hasSelection) {
root.resetFocus()
}
}
}
Util.SelectableDelegateModel {
id: selectionModel
model: artistModel
}
grid: gridComponent
list: tableComponent
emptyLabel: emptyLabelComponent
Util.MLContextMenu {
id: contextMenu
......@@ -114,7 +66,6 @@ FocusScope {
MainInterface.MainGridView {
id: artistGrid
anchors.fill: parent
topMargin: VLCStyle.margin_large
selectionDelegateModel: selectionModel
model: artistModel
......@@ -123,13 +74,12 @@ FocusScope {
cellHeight: VLCStyle.gridItem_music_height
Navigation.parentItem: root
Navigation.cancelAction: root._onNavigationCancel
onActionAtIndex: {
if (selectionModel.selectedIndexes.length > 1) {
MediaLib.addAndPlay( artistModel.getIdsForIndexes( selectionModel.selectedIndexes ) )
} else {
_currentView.currentIndex = index
currentIndex = index
requestArtistAlbumView(Qt.TabFocusReason)
}
}
......@@ -214,7 +164,6 @@ FocusScope {
}
}]
anchors.fill: parent
selectionDelegateModel: selectionModel
model: artistModel
focus: true
......@@ -223,13 +172,13 @@ FocusScope {
headerTopPadding: VLCStyle.margin_normal
Navigation.parentItem: root
Navigation.cancelAction: root._onNavigationCancel
onActionForSelection: {
if (selection.length > 1) {
MediaLib.addAndPlay( artistModel.getIdsForIndexes( selection ) )
} else if ( selection.length === 1) {
requestArtistAlbumView(Qt.TabFocusReason)
// FIX ME - requestArtistAlbumView will destroy this view
MediaLib.addAndPlay( artistModel.getIdForIndex( selection[0] ) )
}
}
......@@ -250,33 +199,13 @@ FocusScope {
}
}
Widgets.StackViewExt {
id: view
anchors.fill: parent
visible: artistModel.count > 0
focus: artistModel.count > 0
initialItem: MainCtx.gridView ? gridComponent : tableComponent
}
Component {
id: emptyLabelComponent
Connections {
target: MainCtx
onGridViewChanged: {
if (MainCtx.gridView) {
view.replace(gridComponent)
} else {
view.replace(tableComponent)
}
EmptyLabelButton {
text: I18n.qtr("No artists found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtArtistCover
}
}
EmptyLabelButton {
anchors.fill: parent
visible: artistModel.isReady && (artistModel.count <= 0)
focus: visible
text: I18n.qtr("No artists found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtArtistCover
}
}
......@@ -19,15 +19,17 @@ import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Templates 2.4 as T
import QtQml.Models 2.2
import org.videolan.vlc 0.1
import org.videolan.medialib 0.1
import "qrc:///util/" as Util
import "qrc:///widgets/" as Widgets
import "qrc:///main/" as MainInterface
import "qrc:///util/Helpers.js" as Helpers
import "qrc:///style/"
FocusScope {
MainInterface.MainViewLoader {
id: root
// Properties
......@@ -36,47 +38,18 @@ FocusScope {
{ text: I18n.qtr("Alphabetic"), criteria: "title" }
]
readonly property var currentIndex: _currentView.currentIndex
//the index to "go to" when the view is loaded
property int initialIndex: 0
// Aliases
property alias leftPadding: view.leftPadding
property alias rightPadding: view.rightPadding
readonly property var currentIndex: Helpers.get(currentItem, "currentIndex", - 1)
property alias model: genreModel
property alias _currentView: view.currentItem
// FIXME: remove this
property var _currentView: currentItem
signal showAlbumView(var id, string name, int reason)
onInitialIndexChanged: resetFocus()
function loadView() {
if (MainCtx.gridView) {
view.replace(gridComponent)
} else {
view.replace(tableComponent)
}
}
function resetFocus() {
if (genreModel.count === 0) {
return
}
var initialIndex = root.initialIndex
if (initialIndex >= genreModel.count)
initialIndex = 0
selectionModel.select(genreModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (_currentView)
_currentView.positionViewAtIndex(initialIndex, ItemView.Contain)
}
model: genreModel
function setCurrentItemFocus(reason) {
_currentView.setCurrentItemFocus(reason);
}
list: tableComponent
grid: gridComponent
emptyLabel: emptyLabelComponent
MLGenreModel {
id: genreModel
......@@ -101,12 +74,6 @@ FocusScope {
}
}
Util.SelectableDelegateModel {
id: selectionModel
model: genreModel
}
Widgets.MLDragItem {
id: genreDragItem
......@@ -125,10 +92,11 @@ FocusScope {
onActiveFocusChanged: {
if (activeFocus && genreModel.count > 0 && !selectionModel.hasSelection) {
var initialIndex = 0
if (_currentView.currentIndex !== -1)
initialIndex = _currentView.currentIndex
if (currentIndex !== -1)
initialIndex = currentIndex
selectionModel.select(genreModel.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
_currentView.currentIndex = initialIndex
currentItem.currentIndex = initialIndex
}
}
......@@ -221,12 +189,6 @@ FocusScope {
onActionAtIndex: _actionAtIndex(index)
Navigation.parentItem: root
Navigation.cancelAction: function() {
if (_currentView.currentIndex <= 0)
root.Navigation.defaultNavigationCancel()
else
_currentView.currentIndex = 0;
}
}
}
......@@ -289,12 +251,6 @@ FocusScope {
focus: true
onActionForSelection: _actionAtIndex(selection)
Navigation.parentItem: root
Navigation.cancelAction: function() {
if (_currentView.currentIndex <= 0)
root.Navigation.defaultNavigationCancel()
else
_currentView.currentIndex = 0;
}
dragItem: genreDragItem
rowHeight: VLCStyle.tableCoverRow_height
headerTopPadding: VLCStyle.margin_normal
......@@ -319,33 +275,14 @@ FocusScope {
}
}
Widgets.StackViewExt {
id: view
anchors.fill: parent
initialItem: MainCtx.gridView ? gridComponent : tableComponent
focus: genreModel.count !== 0
}
Component {
id: emptyLabelComponent
Connections {
target: MainCtx
onGridViewChanged: {
if (MainCtx.gridView) {
view.replace(gridComponent)
} else {
view.replace(tableComponent)
}
EmptyLabelButton {
text: I18n.qtr("No genres found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtAlbumCover
}
}
EmptyLabelButton {
anchors.fill: parent
visible: genreModel.isReady && (genreModel.count <= 0)
focus: visible
text: I18n.qtr("No genres found\nPlease try adding sources, by going to the Browse tab")
Navigation.parentItem: root
cover: VLCStyle.noArtAlbumCover
}
}
......@@ -102,7 +102,6 @@ Widgets.PageLoader {
History.push(["mc", "music", "playlists", "list",
{ parentId: model.id, name: model.name }]);
stackView.currentItem.setCurrentItemFocus(reason);
}
}
}
......
/*****************************************************************************
* Copyright (C) 2021 VLC authors and VideoLAN
* Copyright (C) 2021-23 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -27,9 +27,10 @@ import org.videolan.vlc 0.1
import "qrc:///widgets/" as Widgets
import "qrc:///main/" as MainInterface
import "qrc:///util/" as Util
import "qrc:///util/Helpers.js" as Helpers
import "qrc:///style/"
FocusScope {
MainInterface.MainViewLoader {
id: root
//---------------------------------------------------------------------------------------------
......@@ -38,9 +39,7 @@ FocusScope {
property bool isMusic: false
readonly property int currentIndex: _currentView.currentIndex
property int initialIndex: 0
readonly property int currentIndex: Helpers.get(currentItem, "currentIndex", -1)
property var sortModel: [{ text: I18n.qtr("Alphabetic"), criteria: "title" }]
......@@ -62,16 +61,8 @@ FocusScope {
property string _placeHolder: (isMusic) ? VLCStyle.noArtAlbumCover
: VLCStyle.noArtVideoCover
//---------------------------------------------------------------------------------------------
// Alias
//---------------------------------------------------------------------------------------------
property alias leftPadding: view.leftPadding
property alias rightPadding: view.rightPadding
property alias model: model
property alias _currentView: view.currentItem
// FIXME: remove this
property var _currentView: currentItem
//---------------------------------------------------------------------------------------------
// Signals
......@@ -84,75 +75,44 @@ FocusScope {
//---------------------------------------------------------------------------------------------
// NOTE: Define the initial position and selection. This is done on activeFocus rather than
// Component.onCompleted because modelSelect.selectedGroup update itself after this
// Component.onCompleted because selectionModel.selectedGroup update itself after this
// event.
onActiveFocusChanged: {
if (activeFocus == false || model.count === 0 || modelSelect.hasSelection)
if (activeFocus == false || model.count === 0 || selectionModel.hasSelection)
return;
var initialIndex = 0;
if (_currentView.currentIndex !== -1) {
initialIndex = _currentView.currentIndex;
}
modelSelect.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect);
_currentView.currentIndex = initialIndex;
resetFocus()
}
onInitialIndexChanged: resetFocus()
//---------------------------------------------------------------------------------------------
// Connections
//---------------------------------------------------------------------------------------------
Connections {
target: MainCtx
onGridViewChanged: {
if (MainCtx.gridView) view.replace(grid);
else view.replace(table);
}
}
//---------------------------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------------------------
function resetFocus() {
if (model.count === 0)
return;
// Private
var initialIndex = root.initialIndex;
grid: grid
list: table
emptyLabel: emptyLabel
if (initialIndex >= model.count)
initialIndex = 0;
model: MLPlaylistListModel {
ml: MediaLib
modelSelect.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect);
coverSize: (isMusic) ? Qt.size(512, 512)
: Qt.size(1024, 640)
if (_currentView)
_currentView.positionViewAtIndex(initialIndex, ItemView.Contain);
}
coverDefault: root._placeHolder
function setCurrentItemFocus(reason) {
_currentView.setCurrentItemFocus(reason);
coverPrefix: (isMusic) ? "playlist-music" : "playlist-video"
}
//---------------------------------------------------------------------------------------------
// Private
function _actionAtIndex() {
if (modelSelect.selectedIndexes.length > 1) {
MediaLib.addAndPlay(model.getIdsForIndexes(modelSelect.selectedIndexes));
} else if (modelSelect.selectedIndexes.length === 1) {
var index = modelSelect.selectedIndexes[0];
if (root.selectionModel.selectedIndexes.length > 1) {
MediaLib.addAndPlay(model.getIdsForIndexes(selectionModel.selectedIndexes));
} else if (root.selectionModel.selectedIndexes.length === 1) {
var index = selectionModel.selectedIndexes[0];
showList(model.getDataAt(index), Qt.TabFocusReason);
}
}
function _getCount(model)
{
function _getCount(model) {
var count = model.count;
if (count < 100)
......@@ -161,55 +121,17 @@ FocusScope {
return I18n.qtr("99+");
}
function _onNavigationCancel() {
if (_currentView.currentIndex <= 0) {
Navigation.defaultNavigationCancel()
} else {
_currentView.currentIndex = 0;
_currentView.positionViewAtIndex(0, ItemView.Contain);
}
}
//---------------------------------------------------------------------------------------------
// Childs
//---------------------------------------------------------------------------------------------
MLPlaylistListModel {
id: model
ml: MediaLib
coverSize: (isMusic) ? Qt.size(512, 512)
: Qt.size(1024, 640)
coverDefault: root._placeHolder
coverPrefix: (isMusic) ? "playlist-music" : "playlist-video"
onCountChanged: {
if (count === 0 || modelSelect.hasSelection)
return;
resetFocus();
}
}
Widgets.StackViewExt {
id: view
anchors.fill: parent
initialItem: (MainCtx.gridView) ? grid : table
focus: (model.count !== 0)
}
Widgets.MLDragItem {
id: dragItemPlaylist
mlModel: model
indexes: modelSelect.selectedIndexes
indexes: selectionModel.selectedIndexes
coverRole: "thumbnail"
......@@ -218,12 +140,6 @@ FocusScope {
titleRole: "name"
}
Util.SelectableDelegateModel {
id: modelSelect
model: root.model
}
PlaylistListContextMenu {
id: contextMenu
......@@ -247,12 +163,10 @@ FocusScope {
model: root.model
selectionDelegateModel: modelSelect
selectionDelegateModel: selectionModel
Navigation.parentItem: root
Navigation.cancelAction: root._onNavigationCancel
delegate: VideoGridItem {
//---------------------------------------------------------------------------------
// Properties
......@@ -288,7 +202,7 @@ FocusScope {
onContextMenuButtonClicked: {
gridView.rightClickOnItem(index);
contextMenu.popup(modelSelect.selectedIndexes, globalMousePos);
contextMenu.popup(selectionModel.selectedIndexes, globalMousePos);
}
//---------------------------------------------------------------------------------
......@@ -301,13 +215,13 @@ FocusScope {
// Events
// NOTE: Define the initial position and selection. This is done on activeFocus rather
// than Component.onCompleted because modelSelect.selectedGroup update itself
// than Component.onCompleted because selectionModel.selectedGroup update itself
// after this event.
onActiveFocusChanged: {
if (activeFocus == false || model.count === 0 || modelSelect.hasSelection)
if (activeFocus == false || model.count === 0 || selectionModel.hasSelection)
return;
modelSelect.select(model.index(0,0), ItemSelectionModel.ClearAndSelect)
selectionModel.select(model.index(0,0), ItemSelectionModel.ClearAndSelect)
}
onActionAtIndex: _actionAtIndex()
......@@ -383,12 +297,11 @@ FocusScope {
sortModel: (availableRowWidth < VLCStyle.colWidth(4)) ? _modelSmall
: _modelMedium
selectionDelegateModel: modelSelect
selectionDelegateModel: selectionModel
dragItem: dragItemPlaylist
Navigation.parentItem: root
Navigation.cancelAction: root._onNavigationCancel
//-------------------------------------------------------------------------------------
// Events
......@@ -397,10 +310,10 @@ FocusScope {
onItemDoubleClicked: showList(model, Qt.MouseFocusReason)
onContextMenuButtonClicked: contextMenu.popup(modelSelect.selectedIndexes,
onContextMenuButtonClicked: contextMenu.popup(selectionModel.selectedIndexes,
globalMousePos)
onRightClick: contextMenu.popup(modelSelect.selectedIndexes, globalMousePos)
onRightClick: contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
//-------------------------------------------------------------------------------------
// Childs
......@@ -435,16 +348,18 @@ FocusScope {
}
}
EmptyLabelHint {
anchors.fill: parent
Component {
id: emptyLabel
visible: (model.count === 0)
EmptyLabelHint {
visible: (model.count === 0)
focus: visible
focus: true
text: I18n.qtr("No playlists found")
hint: I18n.qtr("Right click on a media to add it to a playlist")
text: I18n.qtr("No playlists found")
hint: I18n.qtr("Right click on a media to add it to a playlist")
cover: VLCStyle.noArtAlbumCover
cover: VLCStyle.noArtAlbumCover
}
}
}
/*****************************************************************************
* Copyright (C) 2021 VLC authors and VideoLAN
* Copyright (C) 2021-23 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -30,23 +30,19 @@ import "qrc:///util/" as Util
import "qrc:///util/Helpers.js" as Helpers
import "qrc:///style/"
FocusScope {
MainInterface.MainViewLoader {
id: root
// Properties
readonly property int contentMargin: (_currentView) ? _currentView.contentLeftMargin : 0
readonly property int contentMargin: Helpers.get(currentItem, "contentLeftMargin", 0)
// NOTE: Specify an optional header for the view.
property Component header: null
property Item headerItem: (_currentView) ? _currentView.headerItem : null
property Item headerItem: Helpers.get(currentItem, "headerItem", null)
readonly property int currentIndex: _currentView.currentIndex
property int initialIndex: 0
/* required */ property var model
readonly property int currentIndex: Helpers.get(currentItem, "currentIndex", -1)
// NOTE: The ContextMenu depends on the model so we have to provide it too.
/* required */ property var contextMenu
......@@ -56,69 +52,12 @@ FocusScope {
{ text: I18n.qtr("Duration"), criteria: "duration" }
]
// Aliases
property alias leftPadding: view.leftPadding
property alias rightPadding: view.rightPadding
property alias dragItem: dragItem
// Private
property alias _currentView: view.currentItem
// Events
onModelChanged: resetFocus()
onInitialIndexChanged: resetFocus()
// Connections
Connections {
target: MainCtx
onGridViewChanged: {
if (MainCtx.gridView) view.replace(grid)
else view.replace(list)
}
}
Connections {
target: model
onCountChanged: {
if (model.count === 0 || modelSelect.hasSelection)
return;
resetFocus();
}
}
// Functions
function setCurrentItemFocus(reason) {
_currentView.setCurrentItemFocus(reason);
}
function resetFocus() {
if (!model || model.count === 0) return
var initialIndex = root.initialIndex
if (initialIndex >= model.count)
initialIndex = 0
list: list
grid: grid
emptyLabel: emptylabel
modelSelect.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (_currentView) {
_currentView.positionViewAtIndex(initialIndex, ItemView.Contain)
// Table View require this for focus handling
if (!MainCtx.gridView)
_currentView.currentIndex = initialIndex
}
}
function getLabel(model) {
if (!model) return ""
......@@ -158,51 +97,18 @@ FocusScope {
Navigation.defaultNavigationUp()
}
function _onNavigationCancel() {
if (_currentView.currentIndex <= 0) {
Navigation.defaultNavigationCancel()
} else {
_currentView.currentIndex = 0
_currentView.positionViewAtIndex(0, ItemView.Contain)
}
}
// Children
readonly property ColorContext colorContext: ColorContext {
id: theme
colorSet: ColorContext.View
}
Widgets.StackViewExt {
id: view
anchors.fill: parent
focus: (model.count !== 0)
initialItem: (MainCtx.gridView) ? grid : list
}
Widgets.MLDragItem {
id: dragItem
mlModel: root.model
indexes: modelSelect.selectedIndexes
indexes: selectionModel.selectedIndexes
coverRole: "thumbnail"
defaultCover: VLCStyle.noArtVideoCover
}
Util.SelectableDelegateModel {
id: modelSelect
model: root.model
}
Component {
id: grid
......@@ -218,7 +124,7 @@ FocusScope {
model: root.model
selectionDelegateModel: modelSelect
selectionDelegateModel: selectionModel
headerDelegate: root.header
......@@ -230,22 +136,19 @@ FocusScope {
Navigation.upAction: _onNavigationUp
// NOTE: cancelAction takes a function, we pass it directly.
Navigation.cancelAction: root._onNavigationCancel
// Events
// NOTE: Define the initial position and selection. This is done on activeFocus rather
// than Component.onCompleted because modelSelect.selectedGroup update itself
// than Component.onCompleted because selectionModel.selectedGroup update itself
// after this event.
onActiveFocusChanged: {
if (activeFocus == false || model.count === 0 || modelSelect.hasSelection)
if (activeFocus == false || model.count === 0 || selectionModel.hasSelection)
return;
resetFocus() // restores initialIndex
}
onActionAtIndex: root.onAction(modelSelect.selectedIndexes)
onActionAtIndex: root.onAction(selectionModel.selectedIndexes)
// Connections
......@@ -296,7 +199,7 @@ FocusScope {
if (root.isInfoExpandPanelAvailable(model))
options["information"] = index
root.contextMenu.popup(modelSelect.selectedIndexes, globalMousePos, options);
root.contextMenu.popup(selectionModel.selectedIndexes, globalMousePos, options);
}
// Animations
......@@ -336,7 +239,7 @@ FocusScope {
model: root.model
selectionDelegateModel: modelSelect
selectionDelegateModel: selectionModel
dragItem: root.dragItem
......@@ -354,18 +257,15 @@ FocusScope {
Navigation.upAction: _onNavigationUp
//cancelAction takes a *function* pass it directly
Navigation.cancelAction: root._onNavigationCancel
// Events
onActionForSelection: root.onAction(modelSelect.selectedIndexes)
onActionForSelection: root.onAction(selectionModel.selectedIndexes)
onItemDoubleClicked: root.onDoubleClick(model)
onContextMenuButtonClicked: root.contextMenu.popup(modelSelect.selectedIndexes, globalMousePos)
onContextMenuButtonClicked: root.contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
onRightClick: root.contextMenu.popup(modelSelect.selectedIndexes, globalMousePos)
onRightClick: root.contextMenu.popup(selectionModel.selectedIndexes, globalMousePos)
// Functions
......@@ -373,20 +273,20 @@ FocusScope {
}
}
EmptyLabelButton {
anchors.fill: parent
coverWidth : VLCStyle.dp(182, VLCStyle.scale)
coverHeight: VLCStyle.dp(114, VLCStyle.scale)
Component {
id: emptylabel
visible: model.isReady && (model.count <= 0)
EmptyLabelButton {
coverWidth : VLCStyle.dp(182, VLCStyle.scale)
coverHeight: VLCStyle.dp(114, VLCStyle.scale)
focus: visible
focus: true
text: I18n.qtr("No video found\nPlease try adding sources, by going to the Browse tab")
text: I18n.qtr("No video found\nPlease try adding sources, by going to the Browse tab")
cover: VLCStyle.noArtVideoCover
cover: VLCStyle.noArtVideoCover
Navigation.parentItem: root
Navigation.parentItem: root
}
}
}
......@@ -91,7 +91,7 @@ VideoAll {
if (headerItem && headerItem.focus)
headerItem.forceActiveFocus(reason)
else
_currentView.setCurrentItemFocus(reason)
currentItem.setCurrentItemFocus(reason)
}
// VideoAll events reimplementation
......@@ -234,7 +234,7 @@ VideoAll {
Navigation.parentItem: root
Navigation.downAction: function() {
_currentView.setCurrentItemFocus(Qt.TabFocusReason);
currentItem.setCurrentItemFocus(Qt.TabFocusReason)
}
onImplicitHeightChanged: {
......
......@@ -102,8 +102,6 @@ Widgets.PageLoader {
onShowList: {
History.push(["mc", "video", "playlists", "list",
{ parentId: model.id, name: model.name }]);
stackView.currentItem.setCurrentItemFocus(reason);
}
}
}
......
......@@ -30,7 +30,7 @@ function isValidInstanceOf(object, type) {
// If the hash contains no item with the key,
// or the value is invalid, returns defaultValue
function get(dict, key, defaultValue) {
var v = typeof dict !== "undefined" ? dict[key] : undefined
var v = typeof dict !== "undefined" && !!dict ? dict[key] : undefined
return typeof v === "undefined" ? defaultValue : v
}
......
......@@ -151,6 +151,7 @@
<file alias="NoMedialibHome.qml">maininterface/qml/NoMedialibHome.qml</file>
<file alias="MainTableView.qml">maininterface/qml/MainTableView.qml</file>
<file alias="MainGridView.qml">maininterface/qml/MainGridView.qml</file>
<file alias="MainViewLoader.qml">maininterface/qml/MainViewLoader.qml</file>
</qresource>
<qresource prefix="/widgets">
<file alias="ActionButtonOverlay.qml">widgets/qml/ActionButtonOverlay.qml</file>
......
......@@ -36,9 +36,16 @@ void NavigationAttached::defaultNavigationGeneric(QJSValue& jsCallback, QQuickIt
Qt::FocusReason reason)
{
if (jsCallback.isCallable()) {
jsCallback.call();
const auto ret = jsCallback.call();
// if the function returns nothing or true, the action has been handled, stop the traversal
// if the function returns a false explictly, continue traversal
if (!ret.isBool() || ret.toBool())
return;
}
else if (directionItem)
if (directionItem)
{
NavigationAttached* nextItem = qobject_cast<NavigationAttached*>(qmlAttachedPropertiesObject<NavigationAttached>(directionItem));
if (directionItem->isVisible()
......